From dd6aaaf4843902b0e3d44ef953fc0b1670cabc3d Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 21 Mar 2013 12:15:28 +1300 Subject: [PATCH] ENHANCEMENT Additional image generation functions now self-determine if a modification to the underlying image backend is necessary before generating additional image files. --- model/Image.php | 186 +++++++++++++++++++++++++++++++++++--- tests/model/ImageTest.php | 75 +++++++++++++++ 2 files changed, 246 insertions(+), 15 deletions(-) diff --git a/model/Image.php b/model/Image.php index 810c456ae..8b3298c72 100644 --- a/model/Image.php +++ b/model/Image.php @@ -187,30 +187,61 @@ class Image extends File { } } - public function SetWidth($width) { - return $this->getWidth() == $width ? $this : $this->getFormattedImage('SetWidth', $width); - } - - public function SetHeight($height) { - return $this->getHeight() == $height ? $this : $this->getFormattedImage('SetHeight', $height); - } - - public function SetSize($width, $height) { - return (($this->getWidth() == $width) && ($this->getHeight() == $height)) - ? $this - : $this->getFormattedImage('SetSize', $width, $height); - } - + /** + * Resize the image by preserving aspect ratio, keeping the image inside the + * $width and $height + * + * @param integer $width The width to size within + * @param integer $height The height to size within + * @return Image + */ public function SetRatioSize($width, $height) { - return $this->getFormattedImage('SetRatioSize', $width, $height); + + // Check if image is already sized to the correct dimension + $widthRatio = $width / $this->width; + $heightRatio = $height / $this->height; + if( $widthRatio < $heightRatio ) { + // Target is higher aspect ratio than image, so check width + if($this->isWidth($width)) return $this; + } else { + // Target is wider aspect ratio than image, so check height + if($this->isHeight($height)) return $this; + } + + // Item must be regenerated + return $this->getFormattedImage('SetRatioSize', $width, $height); } + /** + * Resize the image by preserving aspect ratio, keeping the image inside the + * $width and $height + * + * @param Image_Backend $backend + * @param integer $width The width to size within + * @param integer $height The height to size within + * @return Image_Backend + */ public function generateSetRatioSize(Image_Backend $backend, $width, $height) { return $backend->resizeRatio($width, $height); } /** * Resize this Image by width, keeping aspect ratio. Use in templates with $SetWidth. + * + * @param integer $width The width to set + * @return Image + */ + public function SetWidth($width) { + return $this->isWidth($width) + ? $this + : $this->getFormattedImage('SetWidth', $width); + } + + /** + * Resize this Image by width, keeping aspect ratio. Use in templates with $SetWidth. + * + * @param Image_Backend $backend + * @param type $width The width to set * @return Image_Backend */ public function generateSetWidth(Image_Backend $backend, $width) { @@ -219,6 +250,21 @@ class Image extends File { /** * Resize this Image by height, keeping aspect ratio. Use in templates with $SetHeight. + * + * @param integer $height The height to set + * @return Image + */ + public function SetHeight($height) { + return $this->isHeight($height) + ? $this + : $this->getFormattedImage('SetHeight', $height); + } + + /** + * Resize this Image by height, keeping aspect ratio. Use in templates with $SetHeight. + * + * @param Image_Backend $backend + * @param integer $height The height to set * @return Image_Backend */ public function generateSetHeight(Image_Backend $backend, $height){ @@ -227,6 +273,24 @@ class Image extends File { /** * Resize this Image by both width and height, using padded resize. Use in templates with $SetSize. + * @see Image::PaddedImage() + * + * @param integer $width The width to size to + * @param integer $height The height to size to + * @return Image + */ + public function SetSize($width, $height) { + return $this->isSize($width, $height) + ? $this + : $this->getFormattedImage('SetSize', $width, $height); + } + + /** + * Resize this Image by both width and height, using padded resize. Use in templates with $SetSize. + * + * @param Image_Backend $backend + * @param integer $width The width to size to + * @param integer $height The height to size to * @return Image_Backend */ public function generateSetSize(Image_Backend $backend, $width, $height) { @@ -269,9 +333,62 @@ class Image extends File { return $backend->croppedResize($this->stat('strip_thumbnail_width'),$this->stat('strip_thumbnail_height')); } + /** + * Resize this Image by both width and height, using padded resize. Use in templates with $PaddedImage. + * @see Image::SetSize() + * + * @param integer $width The width to size to + * @param integer $height The height to size to + * @return Image + */ + public function PaddedImage($width, $height) { + return $this->isSize($width, $height) + ? $this + : $this->getFormattedImage('PaddedImage', $width, $height); + } + + /** + * Resize this Image by both width and height, using padded resize. Use in templates with $PaddedImage. + * + * @param Image_Backend $backend + * @param integer $width The width to size to + * @param integer $height The height to size to + * @return Image_Backend + */ public function generatePaddedImage(Image_Backend $backend, $width, $height) { return $backend->paddedResize($width, $height); } + + /** + * Determine if this image is of the specified size + * + * @param integer $width Width to check + * @param integer $height Height to check + * @return boolean + */ + public function isSize($width, $height) { + return $this->isWidth($width) && $this->isHeight($height); + } + + /** + * Determine if this image is of the specified width + * + * @param integer $width Width to check + * @return boolean + */ + public function isWidth($width) { + return !empty($width) && $this->getWidth() == $width; + } + + /** + * Determine if this image is of the specified width + * + * @param integer $height Height to check + * @return boolean + */ + public function isHeight($height) { + return !empty($height) && $this->getHeight() == $height; + } /** * Return an image object representing the image in the given format. @@ -316,6 +433,7 @@ class Image extends File { * Generate an image on the specified format. It will save the image * at the location specified by cacheFilename(). The image will be generated * using the specific 'generate' method for the specified format. + * * @param string $format Name of the format to generate. * @param string $arg1 Argument to pass to the generate method. * @param string $arg2 A second argument to pass to the generate method. @@ -345,6 +463,25 @@ class Image extends File { /** * Generate a resized copy of this image with the given width & height. * Use in templates with $ResizedImage. + * + * @param integer $width Width to resize to + * @param integer $height Height to resize to + * @return Image + */ + public function ResizedImage($width, $height) { + return $this->isSize($width, $height) + ? $this + : $this->getFormattedImage('ResizedImage', $width, $height); + } + + /** + * Generate a resized copy of this image with the given width & height. + * Use in templates with $ResizedImage. + * + * @param Image_Backend $backend + * @param integer $width Width to resize to + * @param integer $height Height to resize to + * @return Image_Backend */ public function generateResizedImage(Image_Backend $backend, $width, $height) { if(!$backend){ @@ -354,10 +491,29 @@ class Image extends File { return $backend->resize($width, $height); } } + + /** + * Generate a resized copy of this image with the given width & height, cropping to maintain aspect ratio. + * Use in templates with $CroppedImage + * + * @param integer $width Width to crop to + * @param integer $height Height to crop to + * @return Image + */ + public function CroppedImage($width, $height) { + return $this->isSize($width, $height) + ? $this + : $this->getFormattedImage('CroppedImage', $width, $height); + } /** * Generate a resized copy of this image with the given width & height, cropping to maintain aspect ratio. * Use in templates with $CroppedImage + * + * @param Image_Backend $backend + * @param integer $width Width to crop to + * @param integer $height Height to crop to + * @return Image_Backend */ public function generateCroppedImage(Image_Backend $backend, $width, $height) { return $backend->croppedResize($width, $height); diff --git a/tests/model/ImageTest.php b/tests/model/ImageTest.php index 20626065b..0b54f380e 100644 --- a/tests/model/ImageTest.php +++ b/tests/model/ImageTest.php @@ -81,6 +81,9 @@ class ImageTest extends SapphireTest { $this->assertEquals($expected, $actual); } + /** + * Tests that multiple image manipulations may be performed on a single Image + */ public function testMultipleGenerateManipulationCalls() { $image = $this->objFromFixture('Image', 'imageWithoutTitle'); @@ -98,6 +101,78 @@ class ImageTest extends SapphireTest { $this->assertEquals($expected, $actual); } + /** + * Tests that image manipulations that do not affect the resulting dimensions + * of the output image do not resample the file. + */ + public function testReluctanceToResampling() { + + $image = $this->objFromFixture('Image', 'imageWithoutTitle'); + $this->assertTrue($image->isSize(300, 300)); + + // Set width to 50 pixels + $imageSetWidth = $image->SetWidth(300); + $this->assertEquals($imageSetWidth->getWidth(), 300); + $this->assertEquals($image->Filename, $imageSetWidth->Filename); + + // Set height to 300 pixels + $imageSetHeight = $image->SetHeight(300); + $this->assertEquals($imageSetHeight->getHeight(), 300); + $this->assertEquals($image->Filename, $imageSetHeight->Filename); + + // Crop image to 300 x 300 + $imageCropped = $image->CroppedImage(300, 300); + $this->assertTrue($imageCropped->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageCropped->Filename); + + // Resize (padded) to 300 x 300 + $imageSized = $image->SetSize(300, 300); + $this->assertTrue($imageSized->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageSized->Filename); + + // Padded image 300 x 300 (same as above) + $imagePadded = $image->PaddedImage(300, 300); + $this->assertTrue($imagePadded->isSize(300, 300)); + $this->assertEquals($image->Filename, $imagePadded->Filename); + + // Resized (stretched) to 300 x 300 + $imageStretched = $image->ResizedImage(300, 300); + $this->assertTrue($imageStretched->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageStretched->Filename); + + // SetRatioSize (various options) + $imageSetRatioSize = $image->SetRatioSize(300, 600); + $this->assertTrue($imageSetRatioSize->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageSetRatioSize->Filename); + $imageSetRatioSize = $image->SetRatioSize(600, 300); + $this->assertTrue($imageSetRatioSize->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageSetRatioSize->Filename); + $imageSetRatioSize = $image->SetRatioSize(300, 300); + $this->assertTrue($imageSetRatioSize->isSize(300, 300)); + $this->assertEquals($image->Filename, $imageSetRatioSize->Filename); + } + + public function testImageResize() { + $image = $this->objFromFixture('Image', 'imageWithoutTitle'); + $this->assertTrue($image->isSize(300, 300)); + + // Test normal resize + $resized = $image->SetSize(150, 100); + $this->assertTrue($resized->isSize(150, 100)); + + // Test cropped resize + $cropped = $image->CroppedImage(100, 200); + $this->assertTrue($cropped->isSize(100, 200)); + + // Test padded resize + $padded = $image->PaddedImage(200, 100); + $this->assertTrue($padded->isSize(200, 100)); + + // Test SetRatioSize + $ratio = $image->SetRatioSize(80, 160); + $this->assertTrue($ratio->isSize(80, 80)); + } + public function testGeneratedImageDeletion() { $image = $this->objFromFixture('Image', 'imageWithMetacharacters'); $image_generated = $image->SetWidth(200);