diff --git a/model/Image.php b/model/Image.php
index d488c689a..7edcdc6eb 100644
--- a/model/Image.php
+++ b/model/Image.php
@@ -70,7 +70,7 @@ class Image extends File implements Flushable {
* @config
* @var bool Force all images to resample in all cases
*/
- private static $force_resample = false;
+ private static $force_resample = true;
/**
* @config
@@ -163,7 +163,34 @@ class Image extends File implements Flushable {
public function forTemplate() {
return $this->getTag();
}
+
+ /**
+ * Gets the source image URL for this resource
+ *
+ * @return string
+ */
+ public function getSourceURL() {
+ return parent::getURL();
+ }
+ /**
+ * Gets the relative URL accessible through the web. If forced resampling is enabled
+ * the URL will point to an optimised file, if it is smaller than the original
+ *
+ * @uses Director::baseURL()
+ * @return string
+ */
+ public function getURL() {
+ if ($this->config()->force_resample) {
+ //return $resampled->getURL();
+ $resampled = $this->getFormattedImage('Resampled');
+ if ($resampled->getAbsoluteSize() < $this->getAbsoluteSize()) {
+ return $resampled->getURL();
+ }
+ }
+ return $this->getSourceURL();
+ }
+
/**
* File names are filtered through {@link FileNameFilter}, see class documentation
* on how to influence this behaviour.
@@ -232,10 +259,10 @@ class Image extends File implements Flushable {
if( $widthRatio < $heightRatio ) {
// Target is higher aspect ratio than image, so check width
- if($this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')) return $this;
+ if($this->isWidth($width)) return $this;
} else {
// Target is wider or same aspect ratio as image, so check height
- if($this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')) return $this;
+ if($this->isHeight($height)) return $this;
}
// Item must be regenerated
@@ -281,7 +308,7 @@ class Image extends File implements Flushable {
* @return Image
*/
public function Fill($width, $height) {
- return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
+ return $this->isSize($width, $height)
? $this
: $this->getFormattedImage('Fill', $width, $height);
}
@@ -338,7 +365,7 @@ class Image extends File implements Flushable {
* @return Image
*/
public function Pad($width, $height, $backgroundColor='FFFFFF') {
- return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
+ return $this->isSize($width, $height)
? $this
: $this->getFormattedImage('Pad', $width, $height, $backgroundColor);
}
@@ -362,7 +389,7 @@ class Image extends File implements Flushable {
* @return Image
*/
public function ScaleWidth($width) {
- return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')
+ return $this->isWidth($width)
? $this
: $this->getFormattedImage('ScaleWidth', $width);
}
@@ -402,7 +429,7 @@ class Image extends File implements Flushable {
* @return Image
*/
public function ScaleHeight($height) {
- return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')
+ return $this->isHeight($height)
? $this
: $this->getFormattedImage('ScaleHeight', $height);
}
@@ -468,6 +495,26 @@ class Image extends File implements Flushable {
? $this->Fill($this->getWidth(), $height)
: $this;
}
+
+ /**
+ * Resample this Image to ensure quality preference is applied.
+ * Warning: it's possible this will produce a larger file of lower quality
+ *
+ * @return Image
+ */
+ public function Resampled() {
+ return $this->getFormattedImage('Resampled');
+ }
+
+ /**
+ * Resample this Image to apply quality preference
+ *
+ * @param Image_Backend $backend
+ * @return Image_Backend
+ */
+ public function generateResampled(Image_Backend $backend){
+ return $backend;
+ }
/**
* Resize the image by preserving aspect ratio, keeping the image inside the
@@ -768,7 +815,7 @@ class Image extends File implements Flushable {
* @return Image
*/
public function ResizedImage($width, $height) {
- return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
+ return $this->isSize($width, $height)
? $this
: $this->getFormattedImage('ResizedImage', $width, $height);
}
@@ -1028,7 +1075,11 @@ class Image_Cached extends Image {
$this->ID = -1;
$this->Filename = $filename;
}
-
+
+ public function getURL() {
+ return $this->getSourceURL();
+ }
+
public function getRelativePath() {
return $this->getField('Filename');
}
diff --git a/tests/model/ImageTest.php b/tests/model/ImageTest.php
index e9d87d8dc..5879dfee0 100644
--- a/tests/model/ImageTest.php
+++ b/tests/model/ImageTest.php
@@ -69,6 +69,8 @@ class ImageTest extends SapphireTest {
}
public function testGetTagWithTitle() {
+ Config::inst()->update('Image', 'force_resample', false);
+
$image = $this->objFromFixture('Image', 'imageWithTitle');
$expected = '';
@@ -78,6 +80,8 @@ class ImageTest extends SapphireTest {
}
public function testGetTagWithoutTitle() {
+ Config::inst()->update('Image', 'force_resample', false);
+
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
$expected = '';
$actual = $image->getTag();
@@ -86,6 +90,8 @@ class ImageTest extends SapphireTest {
}
public function testGetTagWithoutTitleContainingDots() {
+ Config::inst()->update('Image', 'force_resample', false);
+
$image = $this->objFromFixture('Image', 'imageWithoutTitleContainingDots');
$expected = '';
@@ -166,58 +172,27 @@ class ImageTest extends SapphireTest {
}
/**
- * Tests that image manipulations that do not affect the resulting dimensions
- * of the output image resample the file when force_resample is set to true.
+ * Tests that a URL to a resampled image is provided when force_resample is
+ * set to true, if the resampled file is smaller than the original.
*/
public function testForceResample() {
-
- $image = $this->objFromFixture('Image', 'imageWithoutTitle');
- $this->assertTrue($image->isSize(300, 300));
-
- $origForceResample = Config::inst()->get('Image', 'force_resample');
+ $imageHQ = $this->objFromFixture('Image', 'highQualityJPEG');
+ $imageHQR = $imageHQ->Resampled();
+ $imageLQ = $this->objFromFixture('Image', 'lowQualityJPEG');
+ $imageLQR = $imageLQ->Resampled();
+
+ // Test resampled file is served when force_resample = true
Config::inst()->update('Image', 'force_resample', true);
-
- // Set width to 300 pixels
- $imageScaleWidth = $image->ScaleWidth(300);
- $this->assertEquals($imageScaleWidth->getWidth(), 300);
- $this->assertNotEquals($image->Filename, $imageScaleWidth->Filename);
-
- // Set height to 300 pixels
- $imageScaleHeight = $image->ScaleHeight(300);
- $this->assertEquals($imageScaleHeight->getHeight(), 300);
- $this->assertNotEquals($image->Filename, $imageScaleHeight->Filename);
-
- // Crop image to 300 x 300
- $imageCropped = $image->Fill(300, 300);
- $this->assertTrue($imageCropped->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageCropped->Filename);
-
- // Resize (padded) to 300 x 300
- $imageSized = $image->Pad(300, 300);
- $this->assertTrue($imageSized->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageSized->Filename);
-
- // Padded image 300 x 300 (same as above)
- $imagePadded = $image->Pad(300, 300);
- $this->assertTrue($imagePadded->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imagePadded->Filename);
-
- // Resized (stretched) to 300 x 300
- $imageStretched = $image->ResizedImage(300, 300);
- $this->assertTrue($imageStretched->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageStretched->Filename);
-
- // Fit (various options)
- $imageFit = $image->Fit(300, 600);
- $this->assertTrue($imageFit->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageFit->Filename);
- $imageFit = $image->Fit(600, 300);
- $this->assertTrue($imageFit->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageFit->Filename);
- $imageFit = $image->Fit(300, 300);
- $this->assertTrue($imageFit->isSize(300, 300));
- $this->assertNotEquals($image->Filename, $imageFit->Filename);
- Config::inst()->update('Image', 'force_resample', $origForceResample);
+ $this->assertLessThan($imageHQ->getAbsoluteSize(), $imageHQR->getAbsoluteSize(), 'Resampled image is smaller than original');
+ $this->assertEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to a resampled image was returned by getURL()');
+
+ // Test original file is served when force_resample = true but original file is low quality
+ $this->assertGreaterThanOrEqual($imageLQ->getAbsoluteSize(), $imageLQR->getAbsoluteSize(), 'Resampled image is larger or same size as original');
+ $this->assertNotEquals($imageLQ->getURL(), $imageLQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
+
+ // Test original file is served when force_resample = false
+ Config::inst()->update('Image', 'force_resample', false);
+ $this->assertNotEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
}
public function testImageResize() {