Carrierwave Cropping

Carrierwave Cropping

You can do something like this:

process :cropper

def cropper
manipulate! do |img|
if model.crop_x.blank?
image = MiniMagick::Image.open(current_path)
model.crop_w = ( image[:width] * 0.8 ).to_i
model.crop_h = ( image[:height] * 0.8 ).to_i
model.crop_x = ( image[:width] * 0.1 ).to_i
model.crop_y = ( image[:height] * 0.1 ).to_i
end
img.crop "#{model.crop_w}x#{model.crop_h}+#{model.crop_x}+#{model.crop_y}"
end
end

I'm running code equivalent to that in one of my apps.

How to crop image on upload with Rails, Carrierwave and Minimagick?

I have understood.

  version :thumb do    
process resize_to_fit: [300, nil]
process crop: '300x150+0+0'
#process resize_and_crop: 200
end

private

# Simplest way
def crop(geometry)
manipulate! do |img|
img.crop(geometry)
img
end
end

# Resize and crop square from Center
def resize_and_crop(size)
manipulate! do |image|
if image[:width] < image[:height]
remove = ((image[:height] - image[:width])/2).round
image.shave("0x#{remove}")
elsif image[:width] > image[:height]
remove = ((image[:width] - image[:height])/2).round
image.shave("#{remove}x0")
end
image.resize("#{size}x#{size}")
image
end
end

resize_and_crop from here:

http://blog.aclarke.eu/crop-and-resize-an-image-using-minimagick/

Devise + Carrierwave crop image

Make sure before avatar is set you have set cropping params.

For eg:

This doesn't make height available in uploader:

User.new(avatar: file, height: "10px")

This does:

User.new(height: "10px", avatar: file)

Check order where you are permitting params.

Cropping transparent pixels with carrierwave

The MiniMagick::Image.trim is all that's needed. Without a pixel-iterator, it would be simplest to apply trim on a clone image, and act on the smallest result.

require 'mini_magick'

def trimed_image(path)
image = MiniMagick::Image.open(path)
test_image = image.clone
test_image.trim
if test_image.width < image.width || test_image.height < image.height
test_image
else
image
end
end

Test case with convert rose: -resize x100 rose.png

rose = trimed_image("rose.png")
rose.write("rose_output.png")

No change expected.

rose_output.png

Test transparent image with convert -size 100x100 gradient: -background black -extent 200x200-50-50 -alpha copy trim.png

trim = trimed_image("trim.png")
trim.write("trim_output.png")

Trim expected.

trim_output.png

Carrierwave: how to crop and resize so that the final picture has exactly the same width and height?

Change your line

process :resize_to_fit => [250, 250]

To

process :resize_to_fill => [192, 135]

I asked a similar question about a month ago. Hope this helps! :)

Rails Cropping and Uploading to S3 using CarrierWave and MiniMagick

Like a bad plane crash, there are a lot of things that I did incorrectly.

First, I had the arguments for crop in the wrong order. In my question, you'll notice I had:

img.crop('[x offset]x[y offset]+[width]+[height]')

The correct order is:

img.crop('[width]x[height]+[x offset]+[y offset]')

So that was problem one. Trying to do it in the wrong order was throwing an error (dug into the console to find it) about the geometry being provided as invalid.

Next problem: breaking a yield chain with my cropper method and returning a STRING instead of an IMAGE. Turns out that the crop method returns a string. Look at the original cropper method:

def cropper
return unless model.cropping?
manipulate! do |img|
img = img.crop("#{model.crop_x}x#{model.crop_y}+#{model.crop_w}+#{model.crop_h}")
img
end
end

Oops! Last thing being returned there is a string. Turns out, the correct way is to just call the method on the image directly:

def cropper
return unless model.cropping?
manipulate! do |img|
img.crop("#{model.crop_w}x#{model.crop_h}+#{model.crop_x}+#{model.crop_y}")
img = yield(img) if block_given?
img
end
end

The final thing I was doing wrong - and this was a complete amateur hour mistake - was not making some key attributes accessible. In my infinite wisdom, I assumed that attr_accessor would make the attributes accessible. Nope. I had to modify my model to make the crop_x, crop_y, crop_w, and crop_h arguments accessible.

attr_accessor :crop_x, :crop_y, :crop_w, :crop_h, :original_width, :original_height
attr_accessible :avatar, :remove_avatar, :crop_x, :crop_y, :crop_w, :crop_h
after_update :reprocess_avatar, :if => :cropping?

A last note, not critical but handy to know. I did not need to call process! as recreate_versions! does that for me.

Hope this helps at least one person out there.

How do you crop an image with carrierwave 'after the fact' in rails?

This is the best I can do. There's probably an easier way to do it, but this is my hack:

Here is my 'POST' controller action when the cropping info is passed:

  def update_crop
@user = User.find(current_user.id)
@user.crop(params[:x].to_i, params[:y].to_i, params[:h].to_i, params[:w].to_i)

redirect_to(profile_path, :notice => 'Your profile and avatar was successfully updated.')
end

Here is the method to add to the User model that contains an "avatar" image uploader:

  def crop(x, y, h, w)
image = Magick::ImageList.new(avatar.current_path)
cropped_image = image.crop(x, y, h, w)
cropped_image.write(avatar.current_path)

avatar.recreate_versions!
end

Basically this just hi-jacks the current one, overwrites it, and then tells Carrierwave to create

Carrierwave - Dynamic height/width and cropping

I have had exactly the same problem.

You basically need to have your model store the original image dimensions when the file is first uploaded. You can then use these with jCrop to control the cropping process.

My carrier wave uploaded as this function

  def get_geometry
if (@file)
img = ::Magick::Image::read(@file.file).first
@geometry = [ img.columns, img.rows ]
end
end

You have to do rather a lot in the Model, the uploader and in your views.

A full write up is on my web site at the link below.

http://mark.stratmann.me/content_items/image-cropping-with-rails-3-2-carrierwave-bootstrap-modals-jcrop



Related Topics



Leave a reply



Submit