Media: Work around `use-cropbox` bug in Ghostscript 8.70

Wraps `Imagick::readImage()` for PDFs with exception handling, trying again without `use-cropbox` if this fails.

Introduces `WP_Image_Editor_Imagick::pdf_load_source()`.

Works around a known issue in Ghostscript 8.70 (fixed in 8.71) that results in a stack underflow.
While it only affects this version, it remains a common version found on hosts, and prevented some PDF thumbnails from being generated.

See this Ghostscript bug for more details: https://bugs.ghostscript.com/show_bug.cgi?id=690676

Props azaozz, joseaneto, cranewest, dantahoua, n5hzr, mikeschroder.
Fixes #48853.

git-svn-id: https://develop.svn.wordpress.org/trunk@49174 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Mike Schroder 2020-10-16 10:46:58 +00:00
parent 46119b8367
commit 505fe2f0b8
1 changed files with 43 additions and 10 deletions

View File

@ -140,15 +140,16 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
try {
$this->image = new Imagick();
$file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
$filename = $this->file;
if ( 'pdf' === $file_extension ) {
$filename = $this->pdf_setup();
}
$pdf_loaded = $this->pdf_load_source();
// Reading image after Imagick instantiation because `setResolution`
// only applies correctly before the image is read.
$this->image->readImage( $filename );
if ( is_wp_error( $pdf_loaded ) ) {
return $pdf_loaded;
}
} else {
$this->image->readImage( $this->file );
}
if ( ! $this->image->valid() ) {
return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file );
@ -165,6 +166,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
}
$updated_size = $this->update_size();
if ( is_wp_error( $updated_size ) ) {
return $updated_size;
}
@ -795,10 +797,6 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
// We want the thumbnail to be readable, so increase the rendering DPI.
$this->image->setResolution( 128, 128 );
// When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped
// area (resulting in unnecessary whitespace) unless the following option is set.
$this->image->setOption( 'pdf:use-cropbox', true );
// Only load the first page.
return $this->file . '[0]';
} catch ( Exception $e ) {
@ -806,4 +804,39 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
}
}
/**
* Load the image produced by Ghostscript.
*
* Includes a workaround for a bug in Ghostscript 8.70 that prevents processing of some PDF files
* when `use-cropbox` is set.
*
* @since 5.6
*
* @return true|WP_error
*/
protected function pdf_load_source() {
$filename = $this->pdf_setup();
if ( is_wp_error( $filename ) ) {
return $filename;
}
try {
// When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped
// area (resulting in unnecessary whitespace) unless the following option is set.
$this->image->setOption( 'pdf:use-cropbox', true );
// Reading image after Imagick instantiation because `setResolution`
// only applies correctly before the image is read.
$this->image->readImage( $filename );
} catch ( Exception $e ) {
// Attempt to run `gs` without the `use-cropbox` option. See #48853.
$this->image->setOption( 'pdf:use-cropbox', false );
$this->image->readImage( $filename );
}
return true;
}
}