Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RMagick changing image extents with gravity

I've got an image that i'd like to 'pad' with white space and centre.

In most cases I need to resize the image from 16 or 32 pixels up to 32 pixels. If the image is 16 pixels, I want to add 8px of white space on each side, making it a 32 pixel image (with the original floating in the middle).

If it's a 32 pixel image, then nothing changes.

I'm using RMagick to do the conversion:

image.change_geometry!("#{size}x#{size}") { |cols, rows, img|
  newimg = img.extent(cols, rows)
  newimg.write("#{RAILS_ROOT}#{path}/#{name}.png")
}

Which is working OK, but the smaller images are in the top left of the new image, not centred. I was looking at the gravity setting, it seems to be what I need, but I can't work out how to specify it in the call?

Thanks in advance.

like image 871
d2kagw Avatar asked Feb 03 '26 21:02

d2kagw


2 Answers

Check the implementation of the following carrierwave function http://rubydoc.info/gems/carrierwave/0.5.1/CarrierWave/RMagick#resize_and_pad-instance_method

This is a version of the above method by using only RMagick dependency

require 'RMagick'
include Magick

module Converter
  def self.resize_and_pad(img, new_img_path, width, height, background=:transparent, gravity=::Magick::CenterGravity)
    img.resize_to_fit!(width, height)
    new_img = ::Magick::Image.new(width, height)
    if background == :transparent
      filled = new_img.matte_floodfill(1, 1)
    else
      filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
    end
    # destroy_image(new_img)
    filled.composite!(img, gravity, ::Magick::OverCompositeOp)
    # destroy_image(img)
    # filled = yield(filled) if block_given?
    # filled
    filled.write new_img_path
  end
end
like image 107
Christos K Avatar answered Feb 06 '26 11:02

Christos K


The extent() method takes two more parameters, x & y offsets, which is where the image will be placed within the extent. If you're asking extent for a 100x100 image, for example, and your original is only 50x50, you'd do img.extent(100, 100, 25, 25) -- which would set the image to start at offset 25,25 (thus centering it).

NOTE: There's some issue with extent expecting to use negative offset values (in which case you'd want to do -25, -25) -- check this:

why is the behavior of extent (imagemagick) not uniform across my machines?

like image 21
dotdotdotPaul Avatar answered Feb 06 '26 09:02

dotdotdotPaul



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!