class DynamicImage::ImageSizing

DynamicImage Image Sizing

Calculates cropping and fitting for image sizes.

Attributes

record[R]

Public Class Methods

new(record, options = {}) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 8
def initialize(record, options = {})
  @record = record
  @uncropped = options[:uncropped] ? true : false
end

Public Instance Methods

crop_geometry(ratio_vector) click to toggle source

Calculates crop geometry. The given vector is scaled to match the image size, since DynamicImage performs cropping before resizing.

Example

image = Image.find(params[:id]) # 320x200 image
sizing = DynamicImage::ImageSizing.new(image)

sizing.crop_geometry(Vector2d(100, 100))
# => [Vector2d(200, 200), Vector2d(60, 0)]

Returns a tuple with crop size and crop start vectors.

# File lib/dynamic_image/image_sizing.rb, line 26
def crop_geometry(ratio_vector)
  # Maximize the crop area to fit the image size
  crop_size = ratio_vector.fit(size).round

  # Ignore pixels outside the pre-cropped area for now
  center = crop_gravity - crop_start

  start = center - (crop_size / 2).floor
  start = clamp(start, crop_size, size)

  [crop_size, (start + crop_start)]
end
fit(fit_size, options = {}) click to toggle source

Adjusts fit_size to fit the image dimensions. Any dimension set to zero will be ignored.

Options

  • :crop - Don’t keep aspect ratio. This will allow the image to be cropped to the requested size.

  • :upscale - Don’t limit to the size of the image. Images smaller than the given size will be scaled up.

Examples

image = Image.find(params[:id]) # 320x200 image
sizing = DynamicImage::ImageSizing.new(image)

sizing.fit(Vector2d(0, 100))
# => Vector2d(160.0, 100.0)

sizing.fit(Vector2d(500, 500))
# => Vector2d(320.0, 200.0)

sizing.fit(Vector2d(500, 500), crop: true)
# => Vector2d(200.0, 200.0)

sizing.fit(Vector2d(500, 500), upscale: true)
# => Vector2d(500.0, 312.5)
# File lib/dynamic_image/image_sizing.rb, line 66
def fit(fit_size, options = {})
  fit_size = parse_vector(fit_size)
  require_dimensions!(fit_size)     if options[:crop]
  fit_size = size.fit(fit_size)     unless options[:crop]
  fit_size = size.contain(fit_size) unless options[:upscale]
  fit_size
end

Private Instance Methods

clamp(start, size, max_size) click to toggle source

Clamps the rectangle defined by start and size to fit inside 0, 0 and max_size. It is assumed that size will always be smaller than max_size.

Returns the start vector.

# File lib/dynamic_image/image_sizing.rb, line 105
def clamp(start, size, max_size)
  start += shift_vector(start)
  start -= shift_vector(max_size - (start + size))
  start
end
crop_gravity() click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 76
def crop_gravity
  if uncropped? && !record.crop_gravity?
    size / 2
  else
    record.crop_gravity
  end
end
crop_start() click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 84
def crop_start
  if uncropped?
    Vector2d.new(0, 0)
  else
    record.crop_start
  end
end
parse_vector(vector) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 111
def parse_vector(vector)
  vector.is_a?(String) ? str_to_vector(vector) : vector
end
require_dimensions!(vector) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 117
def require_dimensions!(vector)
  return if vector.x.positive? && vector.y.positive?

  raise DynamicImage::Errors::InvalidSizeOptions
end
shift_vector(vect) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 123
def shift_vector(vect)
  vector(
    vect.x.negative? ? vect.x.abs : 0,
    vect.y.negative? ? vect.y.abs : 0
  )
end
size() click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 92
def size
  if uncropped?
    record.real_size
  else
    record.size
  end
end
str_to_vector(str) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 130
def str_to_vector(str)
  x, y = str.match(/(\d*)x(\d*)/)[1, 2].map(&:to_i)
  Vector2d.new(x, y)
end
uncropped?() click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 135
def uncropped?
  @uncropped
end
vector(width, height) click to toggle source
# File lib/dynamic_image/image_sizing.rb, line 139
def vector(width, height)
  Vector2d.new(width, height)
end