56 lines
1.7 KiB
Ruby
56 lines
1.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "fastimage"
|
|
|
|
module Ezdoc
|
|
class ImageDimensions
|
|
EMUS_PER_INCH = 914_400
|
|
DEFAULT_DPI = 96
|
|
|
|
def self.read(path)
|
|
FastImage.size(path) || raise(ArgumentError, "Could not read image dimensions: #{path}")
|
|
end
|
|
|
|
def self.calculate_emus(path, width: nil, height: nil)
|
|
native_width, native_height = read(path)
|
|
calculate_dimensions_emu(native_width, native_height, width, height)
|
|
end
|
|
|
|
def self.calculate_dimensions_emu(native_width, native_height, width, height)
|
|
if width && height
|
|
[parse_dimension(width), parse_dimension(height)]
|
|
elsif width
|
|
w = parse_dimension(width)
|
|
ratio = native_height.to_f / native_width
|
|
[w, (w * ratio).to_i]
|
|
elsif height
|
|
h = parse_dimension(height)
|
|
ratio = native_width.to_f / native_height
|
|
[(h * ratio).to_i, h]
|
|
else
|
|
pixels_to_emus(native_width, native_height)
|
|
end
|
|
end
|
|
|
|
def self.parse_dimension(value)
|
|
case value
|
|
when Integer
|
|
pixels_to_emus(value, 0).first
|
|
when /\A(\d+(?:\.\d+)?)\s*in\z/i
|
|
(::Regexp.last_match(1).to_f * EMUS_PER_INCH).to_i
|
|
when /\A(\d+(?:\.\d+)?)\s*cm\z/i
|
|
(::Regexp.last_match(1).to_f * 360_000).to_i
|
|
when /\A(\d+(?:\.\d+)?)\s*px\z/i, /\A(\d+)\z/
|
|
pixels_to_emus(::Regexp.last_match(1).to_i, 0).first
|
|
else
|
|
raise ArgumentError, "Invalid dimension format: #{value}. Use '2in', '5cm', '100px', or integer pixels."
|
|
end
|
|
end
|
|
|
|
def self.pixels_to_emus(width_px, height_px)
|
|
emu_per_pixel = EMUS_PER_INCH / DEFAULT_DPI
|
|
[(width_px * emu_per_pixel).to_i, (height_px * emu_per_pixel).to_i]
|
|
end
|
|
end
|
|
end
|