module Fleximage
module Operator
# Resize this image, constraining proportions. Options allow cropping, stretching, upsampling and
# padding.
#
# image.resize(size, options = {})
#
# +size+ is size of the output image after the resize operation. Accepts either '123x456'
# format or [123, 456] format.
#
# Use the following keys in the +options+ hash:
#
# * +crop+: pass true to this option to make the ouput image exactly
# the same dimensions as +size+. The default behaviour will resize the image without
# cropping any part meaning the image will be no bigger than the +size+. When :crop
# is true the final image is resized to fit as much as possible in the frame, and then crops it
# to make it exactly the dimensions declared by the +size+ argument.
#
# * +upsample+: By default the image will never display larger than its original dimensions,
# no matter how large the +size+ argument is. Pass +true+ to use this option to allow
# upsampling, disabling the default behaviour.
#
# * +padding+: This option will pad the space around your image with a solid color to make it exactly the requested
# size. Pass +true+, for the default of +white+, or give it a text or pixel color like "red" or
# color(255, 127, 0). This is like the opposite of the +crop+ option. Instead of trimming the
# image to make it exactly the requested size, it will make sure the entire image is visible, but adds space
# around the edges to make it the right dimensions.
#
# * +stretch+: Set this option to true and the image will not preserve its aspect ratio. The final image will
# stretch to fit the requested +size+. The resulting image is exactly the size you ask for.
#
# Example:
#
# @photo.operate do |image|
# image.resize '200x200', :crop => true
# end
class Resize < Operator::Base
def operate(size, options = {})
options = options.symbolize_keys
# Find dimensions
x, y = size_to_xy(size)
# prevent upscaling unless :usample param exists.
unless options[:upsample]
x = @image.columns if x > @image.columns
y = @image.rows if y > @image.rows
end
# Perform image resize
case
when options[:crop] && !options[:crop].is_a?(Hash) && @image.respond_to?(:crop_resized!)
# perform resize and crop
scale_and_crop([x, y])
when options[:stretch]
# stretch the image, ignoring aspect ratio
stretch([x, y])
else
# perform the resize without crop
scale([x, y])
end
# apply padding if necesary
if padding_color = options[:padding]
# get color
padding_color = 'white' if padding_color == true
# get original x and y. This makes it play nice if the requested size is larger
# than the image and upsampling is not allowed.
x, y = size_to_xy(size)
# get proper border sizes
x_border = [0, (x - @image.columns + 1) / 2].max
y_border = [0, (y - @image.rows + 1) / 2].max
# apply padding
@image.border!(x_border, y_border, padding_color)
# crop to remove possible extra pixel
@image.crop!(0, 0, x, y, true)
end
return @image
end
end
end
end