1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-08 15:57:01 +02:00

Add support for interlaced jpeg images per @horst-n and processwire/processwire-requests#134

This commit is contained in:
Ryan Cramer
2017-12-11 11:09:57 -05:00
parent 67cdf1d456
commit bac60dc340
5 changed files with 64 additions and 12 deletions

View File

@@ -554,7 +554,8 @@ $config->fileContentTypes = array(
*
* #property bool upscaling Upscale if necessary to reach target size? (1=true, 0=false)
* #property bool cropping Crop if necessary to reach target size? (1=true, 0=false)
* #property bool autoRotation Automatically correct orientation?
* #property bool autoRotation Automatically correct orientation? (1=true, 0=false)
* #property bool interlace Use interlaced JPEGs by default? Recommended. (1=true, 0=false)
* #property string sharpening Sharpening mode, enter one of: none, soft, medium, strong
* #property int quality Image quality, enter a value between 1 and 100, where 100 is highest quality (and largest files)
* #property float defaultGamma Default gamma of 0.5 to 4.0 or -1 to disable gamma correction (default=2.0)
@@ -566,6 +567,7 @@ $config->imageSizerOptions = array(
'upscaling' => true, // upscale if necessary to reach target size?
'cropping' => true, // crop if necessary to reach target size?
'autoRotation' => true, // automatically correct orientation?
'interlace' => false, // use interlaced JPEGs by default? (recommended)
'sharpening' => 'soft', // sharpening: none | soft | medium | strong
'quality' => 90, // quality: 1-100 where higher is better but bigger
'hidpiQuality' => 60, // Same as above quality setting, but specific to hidpi images

View File

@@ -8,6 +8,7 @@
*
* @property bool $autoRotation
* @property bool $upscaling
* @property bool $interlace
* @property array|string|bool $cropping
* @property int $quality
* @property string $sharpening
@@ -59,6 +60,14 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable
*/
protected $quality = 90;
/**
* Image interlace setting, false or true
*
* @var bool
*
*/
protected $interlace = false;
/**
* Information about the image (width/height)
*
@@ -206,6 +215,7 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable
'autoRotation',
'upscaling',
'cropping',
'interlace',
'quality',
'sharpening',
'defaultGamma',
@@ -910,6 +920,19 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable
$this->upscaling = $this->getBooleanValue($value);
return $this;
}
/**
* Turn on/off interlace
*
* @param bool $value Whether to upscale or not (default = true)
*
* @return $this
*
*/
public function setInterlace($value = true) {
$this->interlace = $this->getBooleanValue($value);
return $this;
}
/**
* Set default gamma value: 0.5 - 4.0 | -1
@@ -1059,6 +1082,9 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable
case 'upscaling':
$this->setUpscaling($value);
break;
case 'interlace':
$this->setInterlace($value);
break;
case 'sharpening':
$this->setSharpening($value);
break;
@@ -1126,6 +1152,7 @@ abstract class ImageSizerEngine extends WireData implements Module, Configurable
'quality' => $this->quality,
'cropping' => $this->cropping,
'upscaling' => $this->upscaling,
'interlace' => $this->interlace,
'autoRotation' => $this->autoRotation,
'sharpening' => $this->sharpening,
'defaultGamma' => $this->defaultGamma,

View File

@@ -185,6 +185,7 @@ class ImageSizerEngineGD extends ImageSizerEngine {
// now release the intermediate image and update settings
imagedestroy($imageTemp);
$imageTemp = null;
$this->setImageInfo(imagesx($image), imagesy($image));
// $this->cropping = false; // ?? set this to prevent overhead with the following manipulation ??
}
@@ -202,12 +203,19 @@ class ImageSizerEngineGD extends ImageSizerEngine {
// this is the case if the original size is requested or a greater size but upscaling is set to false
// the current version is allready the desired result, we only may have to apply compression where possible
$this->sharpening = 'none'; // we set sharpening to none
// current version is already the desired result, we only may have to compress JPEGs but leave GIF and PNG as is:
if($this->imageType == \IMAGETYPE_PNG || $this->imageType == \IMAGETYPE_GIF) {
$result = @copy($srcFilename, $dstFilename);
if(isset($image) && is_resource($image)) @imagedestroy($image); // clean up
if(isset($image)) $image = null;
return $result; // early return !
}
// process JPEGs
if(self::checkMemoryForImage(array(imagesx($image), imagesy($image), 3)) === false) {
throw new WireException(basename($srcFilename) . " - not enough memory to copy the final image");
}
$this->sharpening = 'none'; // we set sharpening to none, as the image only gets compressed, but not resized
$thumb = imagecreatetruecolor(imagesx($image), imagesy($image)); // create the final memory image
$this->prepareImageLayer($thumb, $image);
imagecopy($thumb, $image, 0, 0, 0, 0, imagesx($image), imagesy($image)); // copy our intermediate image into the final one
@@ -273,6 +281,15 @@ class ImageSizerEngineGD extends ImageSizerEngine {
}
}
// optionally apply interlace bit to the final image.
// this will result in progressive JPEGs
if($this->interlace && \IMAGETYPE_JPEG == $this->imageType) {
if(0 == imageinterlace($thumb, 1)) {
// log that setting the interlace bit has failed ?
// ...
}
}
// write to file
$result = false;
switch($this->imageType) {

View File

@@ -436,6 +436,7 @@ class Pageimage extends Pagefile {
$defaultOptions = array(
'upscaling' => true,
'cropping' => true,
'interlace' => false,
'sharpening' => 'soft',
'quality' => 90,
'hidpiQuality' => 40,

View File

@@ -181,7 +181,7 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
$this->im = new \IMagick();
// set the working colorspace: COLORSPACE_RGB or COLORSPACE_SRGB ( whats about COLORSPACE_GRAY ??)
$this->workspaceColorspace = \IMagick::COLORSPACE_SRGB;
$this->workspaceColorspace = \Imagick::COLORSPACE_SRGB;
$this->im->setColorspace($this->workspaceColorspace);
if(!$this->im->readImage($srcFilename)) { // actually we get a filecopy from origFilename to destFilename from PageImage
@@ -192,7 +192,7 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
// check validity against image magick
if(!$this->im->valid()) {
$this->release();
throw new WireException(sprintf($this->_("loaded file '%s' is not a valid image", basename($srcFilename))));
throw new WireException(sprintf($this->_("loaded file '%s' is not a valid image"), basename($srcFilename)));
}
// get image format
@@ -207,12 +207,12 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
// check validity against PW
if(!in_array($this->imageFormat, $this->validSourceImageFormats())) {
$this->release();
throw new WireException(sprintf($this->_("loaded file '%s' is not in the list of valid images", basename($dstFilename))));
throw new WireException(sprintf($this->_("loaded file '%s' is not in the list of valid images"), basename($dstFilename)));
}
// check and retrieve different image parts and information: ICC, Colorspace, Colordepth, Metadata, etc
$this->imageColorspace = $this->im->getImageColorspace();
$this->workspaceColorspace = \IMagick::COLORSPACE_GRAY == $this->imageColorspace ? \IMagick::COLORSPACE_GRAY : $this->workspaceColorspace;
$this->workspaceColorspace = \Imagick::COLORSPACE_GRAY == $this->imageColorspace ? \Imagick::COLORSPACE_GRAY : $this->workspaceColorspace;
$this->im->setColorspace($this->workspaceColorspace);
$this->imageMetadata = $this->im->getImageProfiles('*');
if(!is_array($this->imageMetadata)) $this->imageMetadata = array();
@@ -311,14 +311,14 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
#return true;
} else if(2 == $resizemethod) { // 2 = resize with aspect ratio
if(!$this->im->resizeImage($finalWidth, $finalHeight, \IMagick::FILTER_LANCZOS, 1)) {
if(!$this->im->resizeImage($finalWidth, $finalHeight, \Imagick::FILTER_LANCZOS, 1)) {
$this->release();
return false;
}
$this->setImageInfo($this->im->getImageWidth(), $this->im->getImageHeight());
} else if(4 == $resizemethod) { // 4 = resize and crop from center with aspect ratio
if(!$this->im->resizeImage($bgWidth, $bgHeight, \IMagick::FILTER_LANCZOS, 1)) {
if(!$this->im->resizeImage($bgWidth, $bgHeight, \Imagick::FILTER_LANCZOS, 1)) {
$this->release();
return false;
}
@@ -335,6 +335,11 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
$this->imSharpen($this->sharpening);
}
// optionally apply interlace bit to the final image. This will result in progressive JPEGs
if($this->interlace && in_array(strtoupper($this->imageFormat), array('JPG', 'JPEG'))) {
$this->im->setInterlaceScheme(\Imagick::INTERLACE_JPEG);
}
if(isset($resetGamma) && $this->imageGamma && $this->imageGamma != 1) {
$this->im->gammaImage(1 / $this->imageGamma);
}
@@ -345,13 +350,13 @@ class ImageSizerEngineIMagick extends ImageSizerEngine {
$this->im->setImageFormat($this->imageFormat);
$this->im->setImageType($this->imageType);
if(in_array(strtoupper($this->imageFormat), array('JPG', 'JPEG'))) {
$this->im->setImageCompression(\IMagick::COMPRESSION_JPEG);
$this->im->setImageCompression(\Imagick::COMPRESSION_JPEG);
$this->im->setImageCompressionQuality($this->quality);
} else if(in_array(strtoupper($this->imageFormat), array('PNG', 'PNG8', 'PNG24'))) {
$this->im->setImageCompression(\IMagick::COMPRESSION_ZIP);
$this->im->setImageCompression(\Imagick::COMPRESSION_ZIP);
$this->im->setImageCompressionQuality($this->quality);
} else {
$this->im->setImageCompression(\IMagick::COMPRESSION_UNDEFINED);
$this->im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$this->im->setImageCompressionQuality($this->quality);
}