I would like to use the RMagick Compression in Carrierwave before the image is uploaded to Cloudinary.
The local imagemagick tests showed that a 37MB File (Please don't ask why it has that size ;) ) was compressed to only 4,6 MB with an acceptable quality.
So now I would like to use the same functionality in my rails app with rmagick, but it seems like the preprocessing does not take place at all. The uploader uploads the original file with 37MB.
This is what I have at the moment:
class ImageUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
include CarrierWave::RMagick
process :compress => Magick::JPEGCompression
def compress(compression_type)
manipulate! do |img|
img = img.compression(compression_type)
end
img
end
...
How can I achieve that the compression takes place and only the compressed file is uploaded to cloudinary?
You might want to try our incoming transformation.
For example, you can upload the image using upload widget and add the incoming transformation in the upload preset. or use the SDK. For example:
Cloudinary::Uploader.upload("sample.jpg",
:width => 2000, :height => 1000, :crop => :limit, :quality => 70)
Related
Using ruby on rails. I want carrierwave upload of an SVG file to make .png thumbnails.
I'm having trouble with the syntax of getting carrierwave to convert the files to png.
This is close, and the contents of the thumbnails are png data, but the filename extension is .svg
class SvgUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
version :thumb do
process :convert => 'png'
process resize_to_fit: [50, 50]
end
version :thumb_small do
process :convert => 'png'
process resize_to_fit: [15, 15]
end
After lots of research, there's a way to change the file suffix. The difficult part is to get carrierwave to change only the suffix of the thumbnails. If you're not careful it will change all files suffixes including the your original upload file.
Here's what worked
class SvgUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
version :thumb do
def full_filename(for_file)
super(for_file).chomp(File.extname(super(for_file))) + '.png'
end
process :convert => 'png'
process resize_to_fit: [50, 50]
end
version :thumb_small do
def full_filename(for_file)
super(for_file).chomp(File.extname(super(for_file))) + '.png'
end
process :convert => 'png'
process resize_to_fit: [15, 15]
end
My default image is working with carrierwave, except I can't get a thumb version of the default. #profile.photo and #profile.photo.thumb both return the same default_profile.png. How do I get this to work
Also, when I do upload a photo, #profile.photo.thumb does correctly return the resized version of the uploaded photo.
In /assets/images:
I have default_profile.png and thumb_default_profile.png, the latter is, of course, a scaled down version of the former. I also tried renaming the thumb file to default_profile_thumb.png
relevant portion of profile_photo_uploader.rb:
def default_url
"default_profile.png"
end
version :thumb do
process :resize_to_fill => [60, 60]
end
def default_url
"default_profile.png"
end
version :thumb do
process :resize_to_fill => [60, 60]
def default_url
"thumb_default_profile.png"
end
end
Nicer way todo:
def default_url(*args)
ActionController::Base.helpers.asset_path([version_name, "default_profile.png"].compact.join('_'))
end
I have Image model:
class Image < ActiveRecord::Base
mount_uploader :file, ModuleImageUploader
end
To upload image I use carrierwave + cloudinary:
class ModuleImageUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
process :resize_to_limit => [700, 700]
version :mini do
process :resize_and_pad => [50, 50, '#ffffff']
end
version :thumb do
process :resize_and_pad => [100, 100, '#ffffff']
end
def public_id
return SecureRandom.uuid
end
end
I created new model AccountMediaContent:
class AccountMediaContent < ActiveRecord::Base
mount_uploader :image, AccountMediaContentImageUploader
end
with it's uploader which also uses carrierwave:
class AccountMediaContentImageUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
process :resize_to_limit => [700, 700]
version :mini do
process :resize_and_pad => [50, 50, '#ffffff']
end
version :thumb do
process :resize_and_pad => [100, 100, '#ffffff']
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Right now I need to the way to transfer the image from Image to AccountMediaContent. So, that means if I had such file in Image:
http://res.cloudinary.com/isdfldg/image/upload/v1344344359/4adcda41-49c0-4b01-9f3e-6b3e817d0e4e.jpg
Then it means that I need the exact same file in AccountMediaContent so the link to the file will be the same. Is there any way to achieve this?
The optimal solution for this would be to have a new model which represents the image, and then link it to both models.
Ok my solution is not really good but anyway. What I did is I wrote the script which downloaded already existing images Image in Cloudinary and then I attached them to new model AccountMediaContent.
My task looks like this:
Image.find_in_batches do |imgs_in_batch|
imgs_in_batch.each do |img|
# Downloading image to tmp folder (works on heroku too)
file_format = img.file.format
img_url = img.file.url
tmp_file = "#{Rails.root.join('tmp')}/tmp-img.#{file_format}"
File.open(tmp_file, 'wb') do |fo|
fo.write open(img_url).read
end
# Creating AccountMediaContent with old image (it'll be uploaded to cloudinary.
AccountMediaContent.create(image: File.open(tmp_file))
FileUtils.rm(tmp_file)
end
end
Hope it'll be useful for someone.
I am attempting to optimize images when resizing them with Carrierwave but haven't had any luck getting this to work. Carrierwave is generating the different sized versions, but my custom optimize and the convert processes aren't running. I've tried calling the different processes in different places, but nothing seems to work.
Any ideas on what I might be doing wrong? Could it be the same issue here: CarrierWave RMagick - How do I cause manipulate! to be called?
class FooUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# Attempt #1
process :convert => 'jpg'
process :optimize
version :meow do
process :resize_to_fill => [700, 400]
end
# Attempt #2
version :meow do
process :convert => 'jpg', :optimize => nil, :resize_to_fill => [700, 400]
end
# Attempt #3
version :meow do
process :resize_to_limit => [700, 400]
process :optimize
process :convert => 'jpg'
end
# Attempt #4
# Tried switching order around since they are being resized but not converted
version :meow do
process :convert => 'jpg'
process :optimize
process :resize_to_limit => [700, 400]
end
# Optimize method used by all versions
def optimize
manipulate! do |img|
img.strip
img.combine_options do |c|
c.quality "96"
c.depth "24"
c.interlace "plane"
#c.interlace "Plane" # Tried both cases, seen examples of both
end
img
end
end
end
Well that not entirely possible they way you want if you are using carrierwave mini-magick or rmagick helper method
Solution 1)
if you get rid of carrierwave helper then perhaps it can work
do something like this
process :custom_processing
def custom_processing
// You have to write you own code for and not CarrierWave helper method to achieve this
// write your own code to convert to jpg
// write your code to optimize
// write your code to resize from the converted n optimize image
end
this way you do all your processing in one shot ,having said but you have to dig in mini_magick/rmagick documentation to know how what method to call for each as you cant rely on carrierwave helper (since they are registered/called via process method and one cannot call call/invoke process inside process )
so something like this you can't achieve
def custom_processing
process :convert => 'jpg'
process :optimize
process :resize_to_fit => [700, 400]
end
Solution 2)
With Carrierwave Helper but through multiple versions you can eventually achieve this
version :jpg do
process :convert => 'jpg'
end
version :optimize_jpg ,:from => :jpg do
process :optimize
end
version :meow,:from => :optimize_jpg do
process :resize_to_limit => [700, 400]
end
More reference of this can be found here
Now this approach take care of headache of Approach 1 digging to documentation(since we are using Carrierwave helper methods), but as you can see you have to create multiple versions to achieve this
Question : Why Multiple version ?
Well that how it Carrierwave work it create a uploader for each version and if from options isnt applied it consider the original images (uploaded images) as the source file(parent file) create the desired version
This is the message that I get when I try to upload something that is not an image for example an mp3.
Failed to manipulate with MiniMagick, maybe it is not an image?
Original Error: MiniMagick::Invalid
So I tried to put a condition by checking the file extension. Only resize if It's not an mp3.
Here is my FileUploader using CarrierWave:
class FileUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
...
if File.extname(File.name) != ".mp3"
process :resize_to_fit => [100, 100]
version :thumb do
process :resize_to_fit => [80, 80]
end
end
...
end
File.name provide me only the name without the extension of the current file. Do you know the variable which provide me the name + the extension ?
EDIT:
I have found an alternative in my controller:
def create
#myfile = File.new(params[:icon])
if #myfile.save
if #myfile.file.file.extension != "mp3"
#myfile.file.resize_to_fit(100, 100)
#file.save
end
end
But now I'm stuck with on my CarrierWave FileUploader:
version :thumb do
process :resize_to_fit => [80, 80]
end
It's getting too complicated, I need MiniMagick only for images
I just need a small condition:
if file_is_image? ==> resize + create a thumbnail
else ==> do nothing
thanks
process :resize_to_fit => [100, 100]; :if => :processable?
def processable? upload_name
File.extname(upload_name.path) != ".mp3"
end