carrierwave recreate_versions! corrupts original image - ruby-on-rails

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!

Related

Image uploading issue with Carrierwave and Minimagick (Ruby on rails)

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.

cant see the aws-s3 url saved in rails database

I have successfully implemented image uploading using carrierwave, fog and Amazon S3. In my imageuploader am using only fog as storage. But when i check my database i can see that just the file name is written instead of the amazon url. In my views its fetching correctly from aws without any issues.
Is it supposed to be like this?
If so how the application figure out the exact url to s3?
imageuploader.rb`
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
include CarrierWave::MiniMagick
#Include the sprockets-rails helper for Rails 4+ compatibility:
include Sprockets::Rails::Helper
storage :fog
version :index_size do
process :resize_to_fill => [258, 173]
end
version :thumb_size do
process :resize_to_fill => [100, 100]
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Your config has the bucket name and the database has the filename. These are the only two pieces of information that are actually required to construct a filename (and it can be done without other API calls). The urls are actually pretty regular, so it is fairly straightforward for the server to do this. Hope that helps!

CarrierWave: Uploads and saves original file...I don't want it to

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?

Unable to upload and process image with CarrierWave and MiniMagick

I am trying to implement image-upload with CarrierWave and MiniMagick. I was able to upload an image with carrierwave, but when I implemented MiniMagick to resize uploaded images, it returned this error:
Errno::ENOENT in ItemsController#create
No such file or directory - identify -ping /var/folders/6y/j8zfcgmd02x5s439c0np8fjh0000gn/T/mini_magick20121228-71203-bdoeul.jpg
image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_fill => [100, 100]
end
end
I have imagemagick installed.
Not sure what went wrong, but after I uninstalled MacPort and all its ports, installed Homebrew and reinstalled ImageMagick, everything works as expected.

Generate imagemagick / carrierwave thumbnails when they are requested

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

Resources