Rails | Carrierwave rotates image 90 degrees - ruby-on-rails

I am uploading images to s3 using fog and carrierwave. I am using the below code for profile picture:
version :listpic do
process :resize_to_fill_modfied => [100, 100]
end
version :usershow do
process :resize_to_fill_modfied => [225, 225] #user profile pic kullanılıyor
end
def resize_to_fill_modfied(width, height, gravity=::Magick::CenterGravity)
manipulate! do |img|
img.crop_resized!(width, height, gravity) unless (img.columns <= width && img.rows <= height)
img = yield(img) if block_given?
img
end
end
The problem is, when I try to upload an image 193x193 it rotates to 90 degrees to left. Why is that?
EDIT
When I try to upload 250x250 it again rotates.

I see from the comments on the question that you've "tried all the solutions," but have you installed MiniMagick?
# Add this in your Gemfile after CarrierWave and Fog:
gem 'mini_magick'
# then run `bundle install`
Once you've done that, try again with this in the uploader:
def fix_exif_rotation
manipulate! do |img|
img.tap(&:auto_orient)
end
end

Related

heroku with carrierwave dropbox storage and rails showing always same image

so I have a web application that runs fine in development, and with carrierwave and imagemagick I make some changes on the photos that I need to upload. The problem is that when on heroku when i ask for the main version of the photo it still gives me the thumb version
class BannerUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
if Rails.env.development?
storage :file
else
storage :dropbox
end
def store_dir
if version_name.nil?
"uploads/#{model.class.to_s.underscore}/#{mounted_as}"
else
"uploads/#{model.class.to_s.underscore}/#{mounted_as}_#{version_name}"
end
end
process convert: :jpg
process :crop
process resize_to_limit: [1200, 260]
def crop
if model.crop_x.present?
manipulate! 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
r = model.crop_r.to_i
img.rotate r
img.crop([[w, h].join('x'), [x, y].join('+')].join('+'))
end
end
end
version :thumb do
process resize_to_fill: [640, 320]
end
def extension_whitelist
%w(jpg jpeg png)
end
def filename
if original_filename
"#{secure_token}.#{file.extension}"
elsif file
file.filename
end
end
protected
def secure_token
var = :"##{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
end
this is my uploader
then in my views i have image_tag(model.banner_url(:thumb) to get the thumb version and image_tag #model.banner_url to get the large version. The problem is that the second one on my local machine runs just fine, but when on heroku it gives me the same image of the first one. It does create the right folders and files, and it does crop them right, but it doesn't retrieve the correct one. I am using the
gem 'dropbox-sdk-v2', '~> 0.0.3'
gem 'carrierwave-dropbox', '~> 2.0'
as heroku storage, with obviously a dropbox account
Often you'll want to add different versions of the same file. The
classic example is image thumbnails. There is built in support for
this*
I think the problem is the way you define the store_dir method.
Define it this way:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
And also CarrierWave documentation recommends to use the uploader this way:
uploader = AvatarUploader.new
uploader.store!(my_file) # size: 1024x768
uploader.url # => '/url/to/my_file.png' # size: 800x800
uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
Source: https://github.com/carrierwaveuploader/carrierwave

Rails 5 Carrierwave and MiniMagick breaks gif at resizing for thumbnail

I'm using carrierwave and mini_magick to resize my images, generate thumbnails. It works great for still images such as jpg and png, but when I try gif, it distorts it. You can see original vs the resized example below. Any idea how I make make it generate gif thumb without breaking it?
Original GIF :) https://imgur.com/oi1f8XT
Generated Thumbnail GIF :( https://imgur.com/a/PwAXv
ps how came the thumbnail's size is bigger than the original? Original is 800*600px and thumbnail is 400*300px. The whole point of generating thumbnail is having smaller file size anyways.
Thank you!
image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
def default_url(*args)
ActionController::Base.helpers.asset_path("fallback/" + [version_name, "post.jpg"].compact.join('_'))
end
# Process files as they are uploaded:
# process scale: [800, 600]
# process :resize_to_fit => [800, 600]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
version :thumb do
process resize_to_fit: [400, 300]
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_whitelist
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
The gif you're trying to resize is optimized so that, after the first frame, each subsequent frame contains only the pixels that need to change. When the gif animates, the frames are stacked on top of one another creating the full animation.
Additionally, each frame is only large enough to contain the pixels that need to change. So, the size of each frame is different. When you resize the gif, Imagemagick is resizing each frame to be 400 by 300px regardless of its original size, which is causing the distortion you see.
You can fix this applying an Imagemagick command (with Minimagick bindings in Ruby) called coalesce. It de-optimizes the original image so that each frame is the full size of the canvas.
Calling coalesce makes the file size much larger, so it's necessary to re-optimize the gif once you're done resizing it.
Here's an example:
version :thumb do
process my_resize: [400, 300]
end
def my_resize(width, height)
if #file.content_type == "image/gif"
gif_safe_transform! do |image|
image.resize "#{width}x#{height}" # Perform any transformations here.
end
else
# Process other filetypes if necessary.
end
end
def gif_safe_transform!
MiniMagick::Tool::Convert.new do |image|
image << #file.path
image.coalesce # Remove optimizations so each layer shows the full image.
yield image
image.layers "Optimize" # Re-optimize the image.
image << #file.path
end
end
I wrote a more in-depth explanation with some examples here

Minimagick throwing an error after deployment to heroku

I've uploaded my little project to Heroku and changed storage from file to fog and now this issue has arose thats got me stumped.
So when using the carrierwave uploader I have 2 methods inside
version :landscape, if: :is_landscape? do
process resize_to_fit: [#land_height, 200]
end
version :portrait, if: :is_portrait? do
process resize_to_fit: [200, #port_width]
end
def is_landscape? picture
image = MiniMagick::Image.open(picture.path)
width = image[:width]
aspect = image[:width] / image[:height].to_f
#land_height = aspect * width
image[:width] > image[:height]
end
def is_portrait? picture
image = MiniMagick::Image.open(picture.path)
height = image[:height]
aspect = image[:width] / image[:height].to_f
#port_width = height / aspect
image[:width] < image[:height]
end
The error is occuring when Minimagick::Image.open is being called.
The error is =
No such file or directory # rb_sysopen - uploads/cover/image/12/p1.jpg
It looks like it's trying to find the image in my local storage to run the method on and not AWS.
I might add the original version of the image is being saved to AWS
As always any help is appreciated.
You are missing storage location. Try adding this under storage :file or uploader file
def store_dir
"uploads/logo/#{model.id}"
end
then push code again on heroku.
It works for me.

CarrierWave Backgrounder not uploading versions images to AWS S3

I was using carrierwave 0.10.0 gem with RMagic to upload images on AWS S3. Everything was working fine except it was taking too much time to upload on AWS S3. So thought using carrierwave backgrounder to upload images in background. I set up carrierwave backgrounder (0.4.2) but In this one My original file is always get upload to S3 but versions of that image is never gets uploaded on S3.
Here is my carrierwave_backgrounder.rb
CarrierWave::Backgrounder.configure do |c|
c.backend :sidekiq, queue: :carrierwave
end
I have defined my queue in sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { :url => "redis://#{ENV['REDIS_ENDPOINT']}:6379", :namespace=> "#{ENV['REDIS_NAMESPACE']}" }
config.options =
queues: %w{
critical
carrierwave
}
})
end
Here is my photo_uploader.rb
class PhotoUploader < CarrierWave::Uploader::Base
include ::CarrierWave::Backgrounder::Delay
include CarrierWave::RMagick
storage :fog
def store_dir
"uploads/images/"
end
def filename
"#{secure_token}.#{file.extension}" if original_filename.present?
end
def orient_image
manipulate! do |img|
img.auto_orient
img
end
end
# Create different versions of your uploaded files:
version :thumb_small do
process :resize_to_fill => [100,100]
process :strip
end
def strip
manipulate! do |img|
img.strip!
img = yield(img) if block_given?
img
end
end
def extension_white_list
%w(jpg jpeg gif png)
end
def get_version_dimensions
model.width, model.height = `identify -format "%wx%h " #{file.path}`.split(/x/)
end
protected
def secure_token
var = :"##{mounted_as}_secure_token"
model.instance_variable_get(var) || model.instance_variable_set(var, SecureRandom.hex(5))
end
end
Here is my profile.rb file
mount_uploader :image_url, PhotoUploader
process_in_background :image_url
I have started the sidekiq worker using this command
bundle exec sidekiq -d -L log/sidekiq.log -C config/sidekiq.yml -e development
When I upload image_url only the original image is uploaded. This is sidekiq log after uploading original file. But I don't see any version file uploaded. I checked the S3 bucket also(No version file only the original file)
2016-01-11T08:52:20.772Z 3983 TID-ownpyrrxk CarrierWave::Workers::ProcessAsset JID-91e3803d50defb2d1419cef1 INFO: start
2016-01-11T08:52:31.119Z 3983 TID-ownpyrrxk CarrierWave::Workers::ProcessAsset JID-91e3803d50defb2d1419cef1 INFO: done: 10.347 sec
Is There something I am missing. Please Help
Thanks in Advance
After investigating with few documentations, here is my suggestion:
From careerwave_backgrounder readme: https://github.com/lardawge/carrierwave_backgrounder#background-options
Its clearly shows,
# This stores the original file with no processing/versioning.
# It will upload the original file to s3.
From this #113 , the author said
I found a bug related to Rmagick but no issue with versions
You can try with MiniMagick/ImageMagick instead of RMagick.
Documentation to look for the similar issue:
https://github.com/lardawge/carrierwave_backgrounder/issues/113
https://github.com/lardawge/carrierwave_backgrounder/issues/130
Rails CarrierWave versions are not created for some reason
Thanks!

CarrierWave not resizing / Minimagick

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.

Resources