I cannot get this CarrierWave uploader to process the image and resize how I would like.
The image is initially created with this.
class Screenshot
include Sidekiq::Worker
def perform(link_id)
link = Link.find(link_id)
file = Tempfile.new(["template_#{link.id.to_s}", '.jpg'], 'tmp', :encoding => 'ascii-8bit')
file.write(IMGKit.new(link.given_url, #quality: 50, width: 300).to_img(:jpg))
:quality => 50,
:width => 300,
:height => 300,
"crop-w" => 300,
"crop-h" => 300,
"disable-smart-width" => true,
"zoom" => 0.35).to_img(:jpg))
file.flush
link.snapshot = file
link.save
file.unlink
end
end
I could not get that working, so I thought I'll just resize in the uploader. Then I modified the uploader to do that as per this:
class SnapshotUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
storage :fog
process :convert_it
def convert_it
manipulate! do |img|
img.resize '300x300'
img
end
end
def convert_it2
resize_to_limit [300,300]
end
def convert_it3
resize_to_fit [300,-1]
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def cache_dir
"#{Rails.root}/tmp/uploads"
end
end
And that doesn't work either. I've tried each of the convert it methods, along with just a direct
process :resize_to_limit [300,300]
The image is created. Seems to be now always at 600 width by whatever height.
The image is uploaded to AWS S3.
I have Imagemagick installed with the --disable-openmp from homebrew. I can run mogrify and convert from the command line.
I can resize an image and save it in rails console with MiniMagick without issue.
I have made sure CarrierWave initializer has config.enable_processing = true.
I dont see any error messages in the console, or the sidekiq terminal window.
I'm new at this so I'm stumped at what else to try. Why is my image not resizing to the dimensions I've asked?
EDIT: The 600 widths were coming from IMGKit which means I have still never had carrierwave actually process the image.
Well this turned out to be causd by Sidekiq not being restarted everytime I changed the code.
I was unaware you needed to do that, however as far as I know the uploader does not use sidekiq to do its upload, so I'm unclear why it was a side effect.
At any rate, stopping sidekiq each time I did a code change, has caused this to work.
I have also found the gem Foreman to help start/stop all services together.
If anyone can explain to me why Sidekiq interfered with this let me know. Sidekiq was responsible for making the image, and an image was being created. The resize was just not happening during upload.
Related
Love carrierwave.
When running the recreate_version! the quality of ORIGINAL image is dramatically reduced/corrupted.
I need to use carrierwave's recreate_version! to add a new "mobile" version to an existing Photo model via the mount_uploader :image.
Existing version: original, :card and :thumb
Again, when running the recreate_version! the quality of ORIGINAL image is dramatically reduced.
Mayor image corruption of the original to the point the image should be discarded and re-uploaded.
The :mobile version which is created new from the original is of excellent quality.
And the :card and :thumb versions remain the same, no difference.
Just the original is corrupted. Weird.
As a test, I re-ran the 'photo.image.recreate_versions!(:mobile)' several times to test different parameters trying to catch the corruption culprit (removed un-need gems, recreate :thumb version, etc.). But each time the quality of the original image got worst and worst.
And the higher the dpi the quicker the corruption: 300dpi first pass super ugly, 100dpi two passes yuck, and 72dpi after three passes is just criminal.
Corruption happens on localhost, as well as, Heroku (both staging and production).
Weird. I have used Carrierwave for years and this is the first time with such a problem.
ruby '2.4.1'
rails '5.1.7'
gem 'carrierwave', :git => 'https://github.com/carrierwaveuploader/carrierwave.git'
Here is the setup.
I pass the call to carrierwave recreate_version through Delayed_Job one user at a time
<% #user.photos.find_each do |photo| %>
<% photo.delay.recreate_mobile %>
<% end %>
and in the Photo model
class Photo < ApplicationRecord
def recreate_mobile
self.image.recreate_versions!(:mobile) if self.image?
end
end
and in the ImageUploader
class ImageUploader < CarrierWave::Uploader::Base
include ::CarrierWave::Backgrounder::Delay
include CarrierWave::MiniMagick
include CarrierWave::BombShelter
include CarrierWave::Processing::MiniMagick
storage :aws
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process resize_to_limit: [1350, 1350]
process :store_dimensions
version :mobile do
process resize_to_limit: [400, 600]
end
version :card do
process resize_to_limit: [300, 460]
end
version :thumb, from_version: :card do
process resize_to_limit: [100, 150]
end
private
def store_dimensions
if file && model
model.width, model.height = ::MiniMagick::Image.open(file.file)[:dimensions]
end
end
def max_pixel_dimensions
[6024, 6024]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
and the gems
gem 'carrierwave-aws'
gem 'carrierwave', :git => 'https://github.com/carrierwaveuploader/carrierwave.git'
gem 'carrierwave_backgrounder'
gem 'carrierwave-bombshelter'
gem 'carrierwave-processing'
gem 'mini_magick'
gem 'remotipart', '~> 1.2'
Removed ALL of the unnecessary gems. Still a image corruption issue.
Quality of the original image and all versions are excellent.
It is just after running recreate_version the original image is corrupted.
Any ideas on how to prevent the original image quality from corrupting after recreate_version?
Solved it: switch processing to RMagick
Within the carriewave image_uploader.rb file
replace:
include CarrierWave::MiniMagick
include CarrierWave::Processing::MiniMagick
with:
include CarrierWave::RMagick
include CarrierWave::Processing::RMagick
MiniMagick is considered to have better memory management, but is rather outdated. Plus is corrupted the images. Fingers crossed RMagick has better memory management by now.
RMagick for the win!
I am using Carrierwave to upload images and that works fine but I am now trying to use Minimagick to process these uploaded images.
What is going on?
The images still upload as well as their thumb version, however both images are exactly the same size.
Here is the uploader code:
class FileUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# Override the directory where uploaded files will be stored.
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_fit => [100, 100]
end
# Add a white list of extensions which are allowed to be uploaded.
def extension_white_list
%w(jpg jpeg gif png)
end
end
And here is how I am calling it:
<%= image_tag example.my_file.url(:thumb).to_s %>
I dont think it is anything to do with the way I am calling it because the two files created by all this are the same, so sound slike its to do with processing it on upload.
Here is the folder created for each object:
Image
--- Fixed ---
The issue was ImageMagick. It was not properly configured on my machine so that means no gem that deals with image processing (Paperclip, Minimagick or Dragonfly) could complete any image manipulation.
I've been trying to use RMagick auto_orient method to fix mobile uploads. Currently they are rotated 90 degrees. My uploader file currently looks like this.
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def root
Rails.root.join 'public/'
end
include CarrierWave::MimeTypes
process :set_content_type
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process :resize_to_fill => [200, 200]
version :thumb do
process :resize_to_fill => [50, 50]
end
process :auto_orient
def extension_white_list
%w(jpg jpeg gif png)
end
end
This is giving me an error
undefined local variable or method auto_orient for AvatarUploader:Class (NameError)
I've tried several solutions,
exif image rotation issue using carrierwave and rmagick to upload to s3, https://github.com/minimagick/minimagick/issues/68
but no dice.
Anyone got a clue what I'm doing wrong?
Try adding the following:
def auto_orient
manipulate! do |img|
img.auto_orient!
end
end
As it stands now, the auto_orient process you're referencing doesn't exist in the context, hence the error.
Edit: according to the imagemagick github link you posted, auto_orient! might be broken. You could then use auto_orient instead in a similar way (it just creates a new image instead of modifying the one passed to the method). Refer to the links you posted for possible solutions using the auto_orient method.
I am using carrierwave_backgrounder to upload images to S3 in a background process with Sidekiq.
Here's my background_uploader.rb class...
class BackgroundUploader < CarrierWave::Uploader::Base
include ::CarrierWave::Backgrounder::Delay
include CarrierWave::RMagick
include CarrierWave::MimeTypes
process :set_content_type
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
storage :fog
def store_dir
"uploads/backgrounds/#{model.id}"
end
def default_url
"/assets/default.jpg"
end
process :resize_to_fit => [1024, 1024]
process :convert => 'jpg'
process :fix_exif_rotation
def extension_white_list
%w(jpg jpeg png)
end
def filename
#name ||= Digest::MD5.hexdigest(File.dirname(current_path.to_s))
"#{#name}.#{file.extension}" if original_filename
end
# Rotates the image based on the EXIF Orientation & applies gaussian blur
def fix_exif_rotation
manipulate! do |img|
img.auto_orient!
img = yield(img) if block_given?
img = img.gaussian_blur(0.0, 20.0)
img
end
end
end
carrierwave_backgrounder.rb:
CarrierWave::Backgrounder.configure do |c|
c.backend :sidekiq, queue: :carrierwave
end
background.rb contains:
mount_uploader :image, BackgroundUploader
process_in_background :image
I then run sidekiq -q carrierwave to fire up the background workers. All is working good! Upload a file, I see the queue accept it and start working...
If I immediately open up my AWS S3 Console I see the original file in there. Non-resized and un-blurred. Once the job is complete...I refresh S3 and there's the resized/blurred version. Now both images are in there, but I only want the blurred image to be there. In my view I use...
<%= image_tag(#background.image.to_s) %>
It displays the original file. If I check the checkbox to remove the file, it does so as it should (deletes the original from S3), but the blurred version stays there.
What's getting uploaded to S3...
original.jpg (immediate...I don't want this uploaded at all)
modified.jpg (after job completes)
Long story short: I don't want the original file to upload to S3.
I think your problem is the filename method, which carrierwave may rely on to find (and delete) the original file. Does the problem go away when you use a filename that doesn't change between when it's initially stored and when you process it?
I am using the carrierwave gem with Rmagick in a Rails app. I've set up a new version in my uploader file:
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 :preview do
process :resize_to_fill => [580, 350]
end
end
Of course, I included rmagick and carrierwave in my gemfile. Now I try to load the preview version of my images in my views:
#product.photos.first.image.preview
This does not give any errors, but loads a broken image. If I copy the url of the image, I get a routing error ('no route matches /path/to_my_imagesfolder/preview_image.png'). If I remove the preview method, the image loads properly.
What can the problem be? I thought maybe it was a permissions issue, but I set the uploads folder with 777 and it still fails.
Any ideas?
EDIT: I realized if I upload the images again the new versions are created. Is it possible to make Rmagick create them when they are requested (like TimThumb does in PHP) Or at least is there any command to batch create all the versions?
There must be a better way than uploading all the images...
You can use .recreate_versions!
For example:
Product.all.each do |product|
product.photos.each do |photo|
photo.recreate_versions!
end
end
I'd just use this: https://github.com/markevans/dragonfly