Make WordPress Core

Changeset 56271


Ignore:
Timestamp:
07/19/2023 10:33:47 PM (9 months ago)
Author:
antpb
Message:

Media: Adjust PDF upload handling to remove non-opaque alpha channels from previews.

Previously, Imagick uploads of PDF files with non-opaque alpha channels would result in a black background replacing alpha in the generated thumbnail. This patch adds a remove_pdf_alpha_channel() function in the Imagick classes to use a white background instead.

Props gitlost, joemcgill, joedolson, launchinteractive, emirpprime, mwtsn, ceer, maysi, madejackson, 6adminit, costdev, oglekler.
Fixes #39216.

Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r56250 r56271  
    169169            }
    170170
     171            if ( 'pdf' === $file_extension ) {
     172                $this->remove_pdf_alpha_channel();
     173            }
     174
    171175            $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
    172176        } catch ( Exception $e ) {
     
    753757
    754758    /**
     759     * Removes PDF alpha after it's been read.
     760     *
     761     * @since 6.4.0
     762     */
     763    protected function remove_pdf_alpha_channel() {
     764        $version = Imagick::getVersion();
     765        // Remove alpha channel if possible to avoid black backgrounds for Ghostscript >= 9.14. RemoveAlphaChannel added in ImageMagick 6.7.5.
     766        if ( $version['versionNumber'] >= 0x675 ) {
     767            try {
     768                // Imagick::ALPHACHANNEL_REMOVE mapped to RemoveAlphaChannel in PHP imagick 3.2.0b2.
     769                $this->image->setImageAlphaChannel( defined( 'Imagick::ALPHACHANNEL_REMOVE' ) ? Imagick::ALPHACHANNEL_REMOVE : 12 );
     770            } catch ( Exception $e ) {
     771                return new WP_Error( 'pdf_alpha_process_failed', $e->getMessage() );
     772            }
     773        }
     774    }
     775
     776    /**
    755777     * @since 3.5.0
    756778     * @since 6.0.0 The `$filesize` value was added to the returned array.
  • trunk/tests/phpunit/tests/image/editorImagick.php

    r54401 r56271  
    642642        $this->assertNotWPError( $saved );
    643643    }
     644
     645    /**
     646     * Tests that the alpha channel of PDFs is removed from PDF previews.
     647     *
     648     * Only affects systems with Ghostscript version >= 9.14.
     649     *
     650     * @ticket 39216
     651     *
     652     * @covers WP_Image_Editor_Imagick::remove_pdf_alpha_channel
     653     */
     654    public function test_remove_pdf_alpha_channel_should_remove_the_alpha_channel_in_preview() {
     655        if ( ! wp_image_editor_supports( array( 'mime_type' => 'application/pdf' ) ) ) {
     656            $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' );
     657        }
     658
     659        $test_file     = DIR_TESTDATA . '/images/test-alpha.pdf';
     660        $attachment_id = $this->factory->attachment->create_upload_object( $test_file );
     661        $this->assertNotEmpty( $attachment_id, 'The attachment was not created before testing.' );
     662
     663        $attached_file = get_attached_file( $attachment_id );
     664        $this->assertNotEmpty( $attached_file, 'The attached file was not returned.' );
     665
     666        $rgb = array(
     667            'r' => true,
     668            'g' => true,
     669            'b' => true,
     670        );
     671
     672        // White.
     673        $expected = array(
     674            'r' => 1,
     675            'g' => 1,
     676            'b' => 1,
     677        );
     678
     679        $check = image_get_intermediate_size( $attachment_id, 'full' );
     680        $this->assertIsArray( $check, 'The intermediate size could not be retrieved.' );
     681        $this->assertArrayHasKey( 'file', $check, 'The intermediate size file was not found.' );
     682
     683        $check_file = path_join( dirname( $attached_file ), $check['file'] );
     684        $imagick    = new Imagick( $check_file );
     685        $output     = array_map(
     686            static function( $value ) {
     687                return (int) round( $value );
     688            },
     689            array_intersect_key( $imagick->getImagePixelColor( 100, 100 )->getColor( true /* normalized */ ), $rgb )
     690        );
     691        $imagick->destroy();
     692        $this->assertSame( $expected, $output, 'The image color of the generated thumb does not match expected opaque background.' ); // Allow for floating point equivalence.
     693    }
    644694}
Note: See TracChangeset for help on using the changeset viewer.