Module: SafeImage::VipsBackend
- Defined in:
- lib/safe_image/vips_backend.rb
Constant Summary collapse
- DIMENSIONS_RE =
/\A(?:(?<percent>\d+(?:\.\d+)?)%|(?<w>\d*)x(?<h>\d*)(?<only_down>>)?|(?<pixels>\d+)@)\z/
Class Method Summary collapse
- .crop_north(input:, output:, width:, height:, format:, quality: 85, max_pixels: nil) ⇒ Object
- .downsize(input:, output:, dimensions:, format:, quality: 85, max_pixels: nil) ⇒ Object
- .normalized_format(format) ⇒ Object
- .scale_for(width, height, dimensions) ⇒ Object
Class Method Details
.crop_north(input:, output:, width:, height:, format:, quality: 85, max_pixels: nil) ⇒ Object
9 10 11 |
# File 'lib/safe_image/vips_backend.rb', line 9 def crop_north(input:, output:, width:, height:, format:, quality: 85, max_pixels: nil) Native.crop_north(input.to_s, output.to_s, Integer(width), Integer(height), format.to_s, Integer(quality), max_pixels) end |
.downsize(input:, output:, dimensions:, format:, quality: 85, max_pixels: nil) ⇒ Object
13 14 15 16 17 18 19 20 21 |
# File 'lib/safe_image/vips_backend.rb', line 13 def downsize(input:, output:, dimensions:, format:, quality: 85, max_pixels: nil) probe = SafeImage.probe(input, max_pixels: max_pixels) scale = scale_for(probe.width, probe.height, dimensions) # Never upscale, but always re-encode through the native saver — even on a # no-op scale of 1.0 — so the output is metadata-stripped rather than a # verbatim copy of the untrusted input bytes. scale = [scale, 1.0].min Native.resize(input.to_s, output.to_s, scale, normalized_format(format), Integer(quality), max_pixels) end |
.normalized_format(format) ⇒ Object
23 24 25 26 |
# File 'lib/safe_image/vips_backend.rb', line 23 def normalized_format(format) format = format.to_s.downcase format == "jpeg" ? "jpg" : format end |
.scale_for(width, height, dimensions) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/safe_image/vips_backend.rb', line 28 def scale_for(width, height, dimensions) dimensions = dimensions.to_s match = DIMENSIONS_RE.match(dimensions) or raise ArgumentError, "unsupported dimensions: #{dimensions.inspect}" if match[:percent] return Float(match[:percent]) / 100.0 end if match[:pixels] target_pixels = Float(match[:pixels]) return Math.sqrt(target_pixels / (Integer(width) * Integer(height))) end target_w = match[:w].to_s.empty? ? nil : Float(match[:w]) target_h = match[:h].to_s.empty? ? nil : Float(match[:h]) scales = [] scales << target_w / width if target_w scales << target_h / height if target_h raise ArgumentError, "missing width/height in dimensions: #{dimensions.inspect}" if scales.empty? scales.min end |