Permalink
Browse files

Allow compress to be invoked directly (#600)

* Allow compress to be invoked directly when not registered as event listener

Since the implementation of the Transformation Manager framework, we're
not registered as an event listener by default. This allows the
compress statement to be executed at the current location in the chain
as necessary.

* Apply and track requested output compression in image model

Since the output converters now has the final say in how an image should
be rendered, and the old compress transformation was borked by the
introduction of the transformationManager, we now explicitly track the
requested compression quality on the image model.

This allows to apply the compression quality selectively on output
instead of having to try to work around when the different classes are
created and registered for transformations and events.

* Remove 'compress' method call from Compress tests
  • Loading branch information...
matslindh authored and christeredvartsen committed Dec 17, 2018
1 parent 1a0a968 commit 22125d1c477d67e8308b9eae604d029d79fe7d1f
@@ -275,6 +275,13 @@ public function format(EventInterface $event) {
$outputConverterManager->supportsExtension($this->formatter)
) {
$outputConverterManager->convert($model, $this->formatter);
// for clarity - if we just have a requested compression / quality value, we still have to invoke the
// conversion / writer for the existing format
} else if (
$model->getOutputQualityCompression() &&
$outputConverterManager->supportsExtension($this->formatter)
) {
$outputConverterManager->convert($model, $this->formatter);
}
// Finished transforming the image
@@ -39,6 +39,14 @@ public function getSupportedMimeTypes() {
public function convert(Imagick $imagick, Image $image, $extension, $mimeType) {
try {
$imagick->setImageFormat($extension);
// Levels from 0 - 100 will work for both JPEG and PNG, although the level has different
// meaning for these two image types. For PNG's a high level will mean more compression,
// which usually results in a smaller file size, as for JPEG's, a high level means a
// higher quality, resulting in a larger file size.
if ($image->getOutputQualityCompression() !== null && ($mimeType !== 'image/gif')) {
$imagick->setImageCompressionQuality($image->getOutputQualityCompression());
}
} catch (ImagickException $e) {
throw new OutputConverterException($e->getMessage(), 400, $e);
}
@@ -21,52 +21,12 @@
* @author Christer Edvartsen <cogo@starzinger.net>
* @package Image\Transformations
*/
class Compress extends Transformation implements ListenerInterface {
class Compress extends Transformation {
/**
* @var int
*/
private $level;
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
'image.transformed' => 'compress',
];
}
/**
* Apply the compression
*
* @param EventInterface $event The event instance
*/
public function compress(EventInterface $event) {
if ($this->level === null) {
return;
}
$image = $this->image;
$mimeType = $image->getMimeType();
if ($mimeType === 'image/gif') {
// No need to do anything if the image is a GIF
return;
}
try {
// Levels from 0 - 100 will work for both JPEG and PNG, although the level has different
// meaning for these two image types. For PNG's a high level will mean more compression,
// which usually results in a smaller file size, as for JPEG's, a high level means a
// higher quality, resulting in a larger file size.
$this->imagick->setImageCompressionQuality($this->level);
} catch (ImagickException $e) {
throw new TransformationException($e->getMessage(), 400, $e);
}
$image->hasBeenTransformed(true);
}
/**
* {@inheritdoc}
*/
@@ -81,6 +41,7 @@ public function transform(array $params) {
throw new TransformationException('level must be between 0 and 100', 400);
}
$this->image->setOutputQualityCompression($this->level);
return $this;
}
}
@@ -128,6 +128,11 @@ class Image implements ModelInterface {
*/
private $hasBeenTransformed = false;
/**
* Track requested output quality compression
*/
private $outputQualityCompression;
/**
* Get the size of the image data in bytes
*
@@ -424,6 +429,26 @@ public function hasBeenTransformed($flag = null) {
return $this;
}
/**
* Get the requested output quality compression or quality value
*
* @return null|int
*/
public function getOutputQualityCompression() {
return $this->outputQualityCompression;
}
/**
* Request a specific output quality compression or quality value. The output converter for the file type must still
* make use of the value.
*
* @param int $outputQualityCompression The requested compression or quality value
* @return null
*/
public function setOutputQualityCompression($outputQualityCompression) {
$this->outputQualityCompression = $outputQualityCompression;
}
/**
* {@inheritdoc}
*/
@@ -28,9 +28,7 @@ protected function getTransformation() {
public function testCanTransformTheImage() {
$image = $this->createMock('Imbo\Model\Image');
$image->expects($this->once())->method('hasBeenTransformed')->with(true);
$image->expects($this->once())->method('getMimeType')->will($this->returnValue('image/jpeg'));
$image->expects($this->once())->method('setOutputQualityCompression')->with(50);
$event = $this->createMock('Imbo\EventManager\Event');
$imagick = new Imagick();
@@ -41,7 +39,6 @@ public function testCanTransformTheImage() {
->setImagick($imagick)
->setImage($image)
->setEvent($event)
->transform(['level' => 50]) // Set the correct level parameter
->compress($event); // Perform the actual compression
->transform(['level' => 50]);
}
}
@@ -46,26 +46,6 @@ public function testThrowsExceptionOnMissingLevelParameter() {
$this->transformation->transform([]);
}
public function testDoesNotApplyCompressionToGifImages() {
$image = $this->createMock('Imbo\Model\Image');
$image->expects($this->once())->method('getMimeType')->will($this->returnValue('image/gif'));
$imagick = $this->createMock('Imagick');
$imagick->expects($this->never())->method('setImageCompressionQuality');
$this->transformation->setImagick($imagick)->setImage($image)->transform(['level' => 40]);
$this->transformation->compress($this->createMock('Imbo\EventManager\EventInterface'));
}
public function testDoesNotApplyCompressionWhenLevelIsNotSet() {
$imagick = $this->createMock('Imagick');
$imagick->expects($this->never())->method('setImageCompressionQuality');
$this->transformation->setImagick($imagick)->compress(
$this->createMock('Imbo\EventManager\Event')
);
}
/**
* @expectedException Imbo\Exception\TransformationException
* @expectedExceptionMessage level must be between 0 and 100

0 comments on commit 22125d1

Please sign in to comment.