How to open .jpg file with Minimagick? - ruby-on-rails

I have an error with MiniMagick during my "after_upload" in my image_concern.rb
My code makes the image that is poster be converted to jpg. Then it will take the file which is in / tmp and will modify this file to have it also in smaller to display it for later. But I have an error during this step:
`mogrify -resize 360x200^ -gravity Center -crop 360x200+0+0 /tmp/RackMultipart20200211-5215-1lxtqf1.png` failed with error: mogrify: unable to open image '/tmp/RackMultipart20200211-5215-1lxtqf1.png':
It tries to open this file in .png but it is in jpg in my tmp /. How to say that it opens this file but not in png but in jpg. Thank you
This is my after_upload code:
def #{field}_after_upload
path = #{field}_path
options = #{options}
if #{field}_file.respond_to? :path
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
image = MiniMagick::Image.new(#{field}_file.path) do |b|
if options[:resize].ends_with?('!')
b.resize '#{options[:resize].delete('!')}^'
b.gravity 'Center'
b.crop '#{options[:resize].delete('!')}+0+0'
else
b.resize '#{options[:resize].delete('!')}\>'
end
end
image.format 'jpg'
image.write path
if options[:formats]
options[:formats].each do |k, v|
image = MiniMagick::Image.new(#{field}_file.path) do |b|
b.resize "\#{v}^"
b.gravity 'Center'
b.crop "\#{v}+0+0"
end
image.format 'jpg'
image.write path.gsub('.jpg', "_\#{k}.jpg")
end
end
end
end
The bug starts from "if options[:formats]"
Thank you !

Related

why Getting error on uploading the file with Webp-ffi gem?

Unsupported color conversion request
*** WebP::EncoderError Exception: Cannot read input picture file
got this error on certain jpg file. while converting into jpg again from google does the job but why is this?
'''webp_path = "#{filename.ext}.webp"
# Encode (convert) image to webp format with passed options
WebP.encode(path, webp_path, options)
# HACK: Changing of this two instance variables is the only way
# I found to make CarrierWave save new file that was created
# by encoding original image.
#filename = webp_path.split('/').pop
#file = CarrierWave::SanitizedFile.new(
tempfile: webp_path,
filename: webp_path,
content_type: 'image/webp'
)'''
This is what I use successfully, obviously need MiniMagick installed on the dev computer and server:
class ImagesUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"uploads/story/#{model.created_at.strftime('%Y').to_s.underscore}/#{model.created_at.strftime('%m').to_s.underscore}/#{model.created_at.strftime('%d').to_s.underscore}"
end
def default_url(*args)
"/fallback.webp"
end
process :resize_to_fill => [1200, 677]
process convert_to_webp: [{ quality: 80 }]
version :preview do
process convert_to_webp: [{ quality: 80, resize_w: 470, resize_h: 265 }]
end
def extension_allowlist
%w(jpg jpeg gif png webp)
end
private
def convert_to_webp(options = {})
# Build path for new file
webp_path = "#{path}.webp"
# Encode (convert) image to webp format with passed options
WebP.encode(path, webp_path, options)
# HACK: Changing of this two instance variables is the only way
# I found to make CarrierWave save new file that was created
# by encoding original image.
#filename = webp_path.split('/').pop.split('.').first + '.webp'
#file = CarrierWave::SanitizedFile.new(
tempfile: webp_path,
filename: webp_path,
content_type: 'image/webp'
)
end
end

When downloading an image uploaded with Carrierwave to S3, I get a blank empty image

In my app, I use carrierwave and fog to upload images to S3. In the site, people can select a size and download the photo. When they click download, the program will use image magick to resize the image according to the selected size and then send it to the user. It works find and it send the file. But the problem is when I open the image it's blank! Nothing in the file. When I test it in my local server it works but in production it won't. Here's the action which sends the download :
def download
#photo = Photo.friendly.find(params[:photo_id])
if #photo.free?
if params[:size].present?
size = Size.find(params[:size])
#photo.file.cache_stored_file!
img = Magick::Image.read(#photo.file.file.file).first
img.resize!(size.width, size.height)
filename = "#{size.width}x#{size.height}-#{#photo.file.file.filename}"
path = "#{Rails.root}/tempfreedownload/#{filename}"
File.write(path, '')
img.write path
File.open(path, 'r') do |f|
send_data f.read, type: 'image/png', filename: filename
end
File.delete(path)
img.destroy!
downloads = #photo.downloads + 1
#photo.update_attribute(:downloads, downloads)
else
end
else
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
end
end
What might be the issue?

Rails + Carrierwave + RMagick: GIF converts to JPG but doesn't save right file extension

I'm currently trying to get the first frame of a gif file, resize it and save it as a jpg file.
The conversion seems fine I think. But it doesn't save it with the right file extension. It still gets saved as .gif
So when I try to open it it says can't open image, doesn't seem to be a GIF file. Then I rename the extension myself and it works.
Here is my processing code:
version :gif_preview, :if => :is_gif? do
process :remove_animation
process :resize_to_fill => [555, 2000]
process :convert => 'jpg'
end
def remove_animation
manipulate! do |img, index|
index == 0 ? img : nil
end
end
There is actually another, cleaner way to achieve this; and it is even somewhat documented in the official wiki: How To: Move version name to end of filename, instead of front
Using this method your version code would look like this:
version :gif_preview, :if => :is_gif? do
process :remove_animation
process :resize_to_fill => [555, 2000]
process :convert => 'jpg'
def full_filename(for_file)
super.chomp(File.extname(super)) + '.jpg'
end
end
def remove_animation
manipulate! do |img, index|
index == 0 ? img : nil
end
end
So ... I finally found a solution after hours of headaches why this didn't work. Turns out you have to touch/create a file first in order to make this work. I also switched from RMagick to Mini Magick. Not for a particular reason just tried it out if it would work with MiniMagick but I still had the same problem. Here is my new process code with Mini Magick:
version :gif_preview, :if => :is_gif? do
process :gif_to_jpg_convert
end
def gif_to_jpg_convert
image = MiniMagick::Image.open(current_path)
image.collapse! #get first gif frame
image.format "jpg"
File.write("public/#{store_dir}/gif_preview.jpg", "") #"touch" file
image.write "public/#{store_dir}/gif_preview.jpg"
end
I just don't understand why there is really 0 documenation about this ...

How can I create thumbnail with carrierwave and a imagemagick script?

I'm using carrierwave to creating thumbnails, but I don't know how can -i use with this script.
mogrify -resize 246x246 -background none -gravity center -extent 246x246 -format png -quality 75 -path thumbs penguins.jpg
This script creating thumbnails and works good, but I would like to use this or similar in carrierwave versions.
The documentation on doing advanced configuration of image manipulation with carrierwave is here:
https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Efficiently-converting-image-formats#full-example
If you look at the def mogrify section, you see that in the img.format("png") do |c| block is where the image manipulation options are passed.
That variable c is actually an instance of MiniMagick, which is a thin wrapper around mogrify.
https://github.com/minimagick/minimagick/
The full API for MiniMagick is not quite there, but if you dig into the source, you can find they have a list of all the possible methods they use here:
https://github.com/minimagick/minimagick/blob/master/lib/mini_magick.rb#L39
And those are all defined down below:
https://github.com/minimagick/minimagick/blob/master/lib/mini_magick.rb#L456
I would suggest adding the options you want to your own uploader:
def mogrify(options = {})
manipulate! do |img|
img.format("png") do |c|
# Add other options here:
c.gravity options[:gravity]
c.background options[:background]
c.extend options[:extend]
c.quality options[:quality]
# Original options follow:
c.fuzz "3%"
c.trim
c.rotate "#{options[:rotate]}" if options.has_key?(:rotate)
c.resize "#{options[:resolution]}>" if options.has_key?(:resolution)
c.resize "#{options[:resolution]}<" if options.has_key?(:resolution)
c.push '+profile'
c.+ "!xmp,*"
c.profile "#{Rails.root}/lib/color_profiles/sRGB_v4_ICC_preference_displayclass.icc"
c.colorspace "sRGB"
end
img
end
end
in your app/uploaders/image_uploader.rb
do something like this
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_limit => [246, 246]
end
end
Take a look at this rails cast 253-carrierwave-file-uploads

CarrierWave Renaming the Original, when I only Specified to do so for Versions

The ultimate goal is to be able to upload PDFs, have thumbnails created, and have them saved as PNGs. One thing I should mention is that many of the PDFs are multipage. I have a temporary work around for that, as CarrierWave currently doesn't like them. It's included in the manipulate function I define myself.
Currently what I have is working, except that the original PDF file get's its extension changed to .png, even though I don't believe I'm telling it to. The content remains PDF, which is what I want, but having the extension change, breaks everything. Here's the my whole uploader:
class PdfUploader < CarrierWave::Uploader::Base
def cache_dir
"#{Rails.root}/tmp/uploads"
end
include CarrierWave::RMagick
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Create different versions of your uploaded files:
version :for_crop do
convert('png')
process :resize_to_limit_png => [700, 700]
end
version :thumb do
convert('png')
process :crop
process :resize_to_limit_png => [100, 100]
end
version :medium do
convert('png')
process :crop
process :resize_to_limit_png => [300, 300]
end
version :large do
convert('png')
process :crop
process :resize_to_limit_png => [700, 700]
end
def extension_white_list
%w(jpg jpeg gif png pdf)
end
# Crop Method, grabs the crop ratio and applies the crop
# Called when creating versions
def crop
if model.crop_x.present?
manipulate!(:format => 'png') do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!(x, y, w, h)
end
end
end
def manipulate!(options={})
cache_stored_file! if !cached?
image = ::Magick::Image.read(current_path)
frames = if image.size > 1
list = ::Magick::ImageList.new
#image.each do |frame|
# list << yield( frame )
#end
list = image.first
list
else
frame = image.first
frame = yield( frame ) if block_given?
frame
end
if options[:format]
frames.write("#{options[:format]}:#{current_path}")
else
frames.write(current_path)
end
destroy_image(frames)
rescue ::Magick::ImageMagickError => e
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e)
end
def resize_to_limit_png(width, height)
manipulate!(:format => 'png') do |img|
geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
new_img = img.change_geometry(geometry) do |new_width, new_height|
img.resize(new_width, new_height)
end
destroy_image(img)
new_img = yield(new_img) if block_given?
new_img
end
def filename
(super.chomp(File.extname(super))).to_s + '.png'
end
end
end
So, I did some temporary janky customization just to make this work until CarrierWave handles multipage PDFs. But I wanted to include it in the event that I messed up somewhere in there. Any help would be much appreciated! Thank you!

Resources