diff --git a/lib/dynamic_image/errors.rb b/lib/dynamic_image/errors.rb
index c143481..b8bae16 100644
--- a/lib/dynamic_image/errors.rb
+++ b/lib/dynamic_image/errors.rb
@@ -33,6 +33,7 @@ class InvalidSignature < DynamicImage::Errors::Error; end
# the size works out to less than a pixel, as "0x0" does, or "1x1" against a very wide image.
#
# @see DynamicImage::ImageSizing#fit
+ # @see DynamicImage::Model::Transformations#resize
class InvalidSizeOptions < DynamicImage::Errors::Error; end
# Raised when a transformation can't be applied, either because a rotation isn't a multiple of 90 degrees or
diff --git a/lib/dynamic_image/model/transformations.rb b/lib/dynamic_image/model/transformations.rb
index 792eeb2..4f8dafe 100644
--- a/lib/dynamic_image/model/transformations.rb
+++ b/lib/dynamic_image/model/transformations.rb
@@ -17,9 +17,11 @@ module Transformations
# @param max_size [Vector2d, String] the size to fit within, either a vector or a "{width}x{height}"
# string. Either dimension may be omitted to scale by the other alone.
# @return [self]
+ # @raise [DynamicImage::Errors::InvalidSizeOptions] if the result is less than a pixel in either dimension
+ # @raise [DynamicImage::Errors::InvalidImage] if the stored data can't be processed
def resize(max_size)
transform_image do |image|
- resized = image.resize(real_size.fit(max_size))
+ resized = image.resize(fit_size(max_size))
scale_crop(resized.size)
resized
end
@@ -30,6 +32,7 @@ def resize(max_size)
# @param degrees [Integer] the angle, which must be a multiple of 90. Rotating by 0 is a no-op.
# @return [self]
# @raise [DynamicImage::Errors::InvalidTransformation] if the angle isn't a multiple of 90
+ # @raise [DynamicImage::Errors::InvalidImage] if the stored data can't be processed
#
# @example
# image.rotate(90)
@@ -52,6 +55,16 @@ def rotate(degrees = 90)
private
+ # Scales +max_size+ against the image, rejecting a result smaller than a pixel in either dimension, as
+ # {DynamicImage::ImageSizing#fit} does for the sizes rendered on request.
+ def fit_size(max_size)
+ new_size = real_size.fit(max_size)
+ return new_size if new_size.x >= 1 && new_size.y >= 1
+
+ raise DynamicImage::Errors::InvalidSizeOptions,
+ "#{new_size} has a dimension smaller than one pixel"
+ end
+
def scale_crop(new_size)
scale = new_size.to_f_vector / real_size
@@ -121,6 +134,8 @@ def transform_image(&block)
end
read_image_metadata
self
+ rescue Vips::Error => e
+ raise DynamicImage::Errors::InvalidImage, e.message
end
end
end
diff --git a/spec/dynamic_image/model/transformations_spec.rb b/spec/dynamic_image/model/transformations_spec.rb
index b7c3c00..23ecc22 100644
--- a/spec/dynamic_image/model/transformations_spec.rb
+++ b/spec/dynamic_image/model/transformations_spec.rb
@@ -77,6 +77,27 @@
expect(resized.crop_gravity).to eq(Vector2d(1, 1))
end
end
+
+ context "when the size is smaller than a pixel" do
+ subject(:resized) { image.resize("0x0") }
+
+ it "raises an error" do
+ expect { resized }.to(
+ raise_error(DynamicImage::Errors::InvalidSizeOptions)
+ )
+ end
+ end
+
+ context "when vips fails to process the data" do
+ before do
+ allow(DynamicImage::ImageProcessor)
+ .to receive(:new).and_raise(Vips::Error, "unable to read")
+ end
+
+ it "raises an error" do
+ expect { resized }.to raise_error(DynamicImage::Errors::InvalidImage)
+ end
+ end
end
describe "#rotate" do
@@ -96,6 +117,17 @@
end
end
+ context "when vips fails to process the data" do
+ before do
+ allow(DynamicImage::ImageProcessor)
+ .to receive(:new).and_raise(Vips::Error, "unable to read")
+ end
+
+ it "raises an error" do
+ expect { rotated }.to raise_error(DynamicImage::Errors::InvalidImage)
+ end
+ end
+
context "with a 90 degree rotation" do
it "rotates the image" do
expect(rotated.real_size).to eq(Vector2d.new(200, 320))