ActiveStorage::InvariableError in Home#index - ruby-on-rails

Currently I'm trying to display .HEIC images in Rails 6. I'm using ActiveStorage ImageMagic to use variant to display jpg. Basically I'm trying to use
mogrify -format jpg myimage.heic
In the image to display jpg.
I added Rails.application.config.active_storage.variant_processor into application.rb to be able to use the variant. However it seems to break in the following line:
<%= image_tag post.image.variant(format: 'jpg'), class: "card-home__img" %>
Why is not working?

You can only call variant on an image that returns true when you call variable? on it.
Internally, ActiveStorage checks if ActiveStorage.variable_content_types contains your image's type. The default supported values are:
image/png
image/gif
image/jpg
image/jpeg
image/pjpeg
image/tiff
image/bmp
image/vnd.adobe.photoshop
image/vnd.microsoft.icon
image/webp
So it seems that currently .HEIC images are not supported.
You can instead apply a format transformation before attaching the image to a model or storing it, it might solve your use case.

Raised when ActiveStorage::Blob#variant is called on a blob that isn't variable. Use ActiveStorage::Blob#variable? to determine whether a blob is variable.
Source: https://edgeapi.rubyonrails.org/classes/ActiveStorage/InvariableError.html

Related

ImageProcessing::Error when passing crop argument to variant

I am having a model with has_one_attached :file that I want to process with a custom crop parameter. The attached file is a photo in jpg format that I use for testing.
Before, I was scaling and cropping images this way, which works as intended.
my_model.file.variant(resize_to_fill: [1440, 560, { gravity: 'Center' }])
Now I wanted to change the center / focus point for cropping the image to a custom position. The plain imagemagick command would be convert input.jpg -crop 1440x560+580+120 output.jpg, working as intended on the command line.
The docs state that you can pass almost any imagemagick commant to .variant(), which lead me to try this:
my_model.file.variant(crop: '1440x560+580+120')
This raises the following error:
ImageProcessing::Error - Source format is multi-layer, but destination format is
single-layer. If you care only about the first layer, add `.loader(page: 0)` to
your pipeline. If you want to process each layer,
see https://github.com/janko/image_processing/wiki/Splitting-a-PDF-into-multiple-images
or use `.saver(allow_splitting: true)`.
I read the manual of image_processing and understand how the pipeline works, but I am missing the part of where/how to adapt the pipeline through .variant() in order to get a result.
Am I doing something wrong here or am I just missing some simple part? Otherwise I'd go the way of writing it raw with an image_processing pipeline and work around it.
My environment consists of:
rails - v6.0.2.2
mini_magick gem - v4.10.1
image_processing gem - v1.10.3
ImageMagick 7.0.8-66
Try my_model.file.variant(combine_options: { crop: '1440x560+580+120')

miniMagick identify error in rails_admin app: Failed to manipulate with MiniMagick, maybe it is not an image?

I am using carrierwave and mini_magick gems to use images inside rails_admin. When I upload an image it fails with this error:
Failed to manipulate with MiniMagick, maybe it is not an image?
Original Error: `identify C:/Users/Zeke/AppData/Local/Temp/mini_magick20161027-21132-xdongz.png` failed with error:
identify.exe: RegistryKeyLookupFailed `CoderModulesPath' # error/module.c/GetMagickModulePath/662.
identify.exe: no decode delegate for this image format `PNG' # error/constitute.c/ReadImage/501.
And this doesn't happen when I don't include the following lines in my uploader.rb
# Process files as they are uploaded:
process resize_to_fit: [800, 600]
# Create different versions of your uploaded files:
version :thumb do
process resize_to_fill: [40, 30]
end
I require thumbnails, and how do I do it?
Here's What I'm sure of:
ImageMagick has been installed and is working for sure. I am able to convert png to jpg and jpg to png, identify images...
identify C:/Users/Zeke/AppData/Local/Temp/mini_magick20161027-21132-xdongz.png executes successfully when run in cmd (without admin priv, if that matters)
identify -list format gives a huuuuge list that almost contains every image format I can think of. And yes, it includes JPG, JPEG, PNG and all that I need.
convert -version does include jpeg png delegates
What am I doing wrong?
Both identify and convert I tested were working fine except for the fact that they were not actually used by rails, which used another installation of imagemagick which was very old and threw this translation missing error at first which I managed to solve by adding a few lines in en.yml
It is notable that System Environment Variables can be overridden by set path that only lasts long for that instance of cmd
Making rails use the new version of ImageMagick solved the problem.
Credits: Mark Setchell

Paperclip Processor - Convert image format dynamically

I need to convert image format dynamically from paperclip custom processor.
My application have a rails 3.2.18 and paperclip 4.1
I am trying to convert format using 'convert' command as below.
extension = attachment.instance.resource_spec.extension
source = #file
destination = Tempfile.new([#basename, extension])
destination.binmode
Paperclip.run("convert #{File.expand_path(source.path)} {File.expand_path(destination.path)}")
extension value will fetch from database.
Paperclip could not able to convert images to expected format through processor.
Please help if any
Thanks in advanced.
Nitin
Try changing the key then using
rake paperclip:refresh CLASS=User
Which will regenerate all your images. Make sure you replace the class with the correct one for your app. See this link on thumbnail generation for more info.
via Devin M

Can't open uploaded image file with RMagick

In my Rails app, I have a form that allows users to upload images. My app is supposed to resize the images with the following controller method. (POST to this method, params[:file] contains the ActionDispatch::Http::UploadedFile that was uploaded:
def resize_and_store
file = params[:file]
# resize image
Magick::Image.read(file.tempfile).first
newimg = image.resize(100,100)
#etc... Store newimg
end
I get the following error, on the line that says Image.read:
Magick::ImageMagickError (no decode delegate for this image format `0xb9f6052c>' # error/constitute.c/ReadImage/544):
Testing this with an uploaded PNG file, it seems RMagick doesn't pick up that the temporary file is a PNG file. The code above does work if I read a locally stored PNG file, so it can't be that I'm missing the PNG decoder. How can I fix this and why does this happen?
You can do from_blob on a ActionDispatch::Http::UploadedFile param (this is how a file comes in):
images = Magick::Image.from_blob(params[:file].read)
Storing the file temporarily will solve the problem:
open('temp.png', 'wb') do |file|
file << uploaded.tempfile.read
end
images=Magick::Image.read('temp.png')
Probably wise to check input size as well.
Alternatively, parse the image from a blob.
Using the answer by #joost (or similar approach) really helped to point me in the right direction but it didn't work on the second attempt with the same temp file - my use case was creating multiple image types from the tempfile source. This is what I've used, wrapping in a File.open block so we don't leak the file descriptor:
File.open(tempfile, "rb") do |f|
img = Magick::Image::from_blob(f.read).first
resized = img.resize_to_fit(w, h)
resized.write(dest)
resized.destroy!
img.destroy!
end
Maybe there's something wrong with the form? You can consult with Rails Guide here:
Rails Guides: Uploading Files
I think that you may have multipart: true missing in your form declaration.
Also, I would strongly advise to use Carrierwave to handle file uploads. Among several things, it will help you to organize your file transformations (putting logic out of the controllers). Here's a railscast about it:
RailsCasts: CarrierWave File Uploads.
Good luck!

Splitting PDF to png

I'm using paperclip to upload a pdf. Once the file is uploaded I need to split every page into a png. This is the command I think I need to use
convert -size 640x300 fileName.pdf slide.png
Now if I run that command from terminal it works fine, but I need a way of getting each slides name so I can add it into a model.
What's the best way to achieve this?
You should be able to have Paperclip do this conversion for you at the time of the upload, like this:
has_attached_file :pdfupload, :styles => { :pinged => ["640x300", :png] }
Then you can show the PNG version like so:
<%= image_tag #mymodel.pdfupload.url(:pinged) %>
(Obviously the name of the model and file will need to be changed to match yours.)
use `command` to execute system commads
(`-quotes)
`convert -size 640x300 fileName.pdf slide.png`

Resources