app/services/riiif/crop.rb in riiif-2.0.0.beta2 vs app/services/riiif/crop.rb in riiif-2.0.0

- old
+ new

@@ -1,54 +1,123 @@ module Riiif # Represents a cropping operation class Crop - attr_reader :image_info + # @param transformation [IIIF::Image::Region] the result the user requested + # @param image_info [] + def initialize(region, image_info) + @region = region + @image_info = image_info + end + attr_reader :image_info, :region + # @return [String] a region for imagemagick to decode # (appropriate for passing to the -crop parameter) def to_imagemagick - "#{width}x#{height}+#{offset_x}+#{offset_y}" + case region + when IIIF::Image::Region::Full + nil + when IIIF::Image::Region::Absolute + "#{region.width}x#{region.height}+#{region.offset_x}+#{region.offset_y}" + when IIIF::Image::Region::Square + imagemagick_square + when IIIF::Image::Region::Percent + imagemagick_percent + else + raise "Unknown region #{region.class}" + end end # @return [String] a region for kakadu to decode # (appropriate for passing to the -region parameter) def to_kakadu - "\{#{decimal_offset_y},#{decimal_offset_x}\},\{#{decimal_height},#{decimal_width}\}" + case region + when IIIF::Image::Region::Full + nil + when IIIF::Image::Region::Absolute + "\{#{decimal_offset_y(region.offset_y)},#{decimal_offset_x(region.offset_x)}\}," \ + "\{#{decimal_height(region.height)},#{decimal_width(region.width)}\}" + when IIIF::Image::Region::Square + kakadu_square + when IIIF::Image::Region::Percent + kakadu_percent + else + raise "Unknown region #{region.class}" + end end - attr_reader :offset_x + private - attr_reader :offset_y + def imagemagick_percent + offset_x = (image_info.width * percentage_to_fraction(region.x_pct)).round + offset_y = (image_info.height * percentage_to_fraction(region.y_pct)).round + "#{region.width_pct}%x#{region.height_pct}+#{offset_x}+#{offset_y}" + end - # @return [Integer] the height in pixels - def height - image_info.height - end + def kakadu_percent + offset_x = (image_info.width * percentage_to_fraction(region.x_pct)).round + offset_y = (image_info.height * percentage_to_fraction(region.y_pct)).round + "\{#{decimal_offset_y(offset_y)},#{decimal_offset_x(offset_x)}\}," \ + "\{#{percentage_to_fraction(region.height_pct)},#{percentage_to_fraction(region.width_pct)}\}" + end - # @return [Integer] the width in pixels - def width - image_info.width - end + def kakadu_square + min, max = [image_info.width, image_info.height].minmax + offset = (max - min) / 2 + if image_info.height >= image_info.width + # Portrait + "\{#{decimal_height(offset)},0\}," \ + "\{#{decimal_height(image_info.height)},#{decimal_width(image_info.height)}\}" + else + # Landscape + "\{0,#{decimal_width(offset)}\}," \ + "\{#{decimal_height(image_info.width)},#{decimal_width(image_info.width)}\}" + end + end - # @return [Float] the fractional height with respect to the original size - def decimal_height(n = height) - n.to_f / image_info.height - end + def imagemagick_square + min, max = [image_info.width, image_info.height].minmax + offset = (max - min) / 2 + if image_info.height >= image_info.width + "#{min}x#{min}+0+#{offset}" + else + "#{min}x#{min}+#{offset}+0" + end + end - # @return [Float] the fractional width with respect to the original size - def decimal_width(n = width) - n.to_f / image_info.width - end + # @return [Integer] the height in pixels + def height + image_info.height + end - def decimal_offset_x - offset_x.to_f / image_info.width - end + # @return [Integer] the width in pixels + def width + image_info.width + end - def decimal_offset_y - offset_y.to_f / image_info.height - end + # @return [Float] the fractional height with respect to the original size + def decimal_height(n = height) + n.to_f / image_info.height + end - def maintain_aspect_ratio? - (height / width) == (image_info.height / image_info.width) - end + # @return [Float] the fractional width with respect to the original size + def decimal_width(n = width) + n.to_f / image_info.width + end + + def decimal_offset_x(offset_x) + offset_x.to_f / image_info.width + end + + def decimal_offset_y(offset_y) + offset_y.to_f / image_info.height + end + + def maintain_aspect_ratio? + (height / width) == (image_info.height / image_info.width) + end + + def percentage_to_fraction(n) + n / 100.0 + end end end