WordPress.org

Make WordPress Core

Changeset 38949


Ignore:
Timestamp:
10/26/16 07:27:51 (4 months ago)
Author:
mikeschroder
Message:

Media: Add support for rendering PDF thumbnails.

When support for PDFs is available, on upload,
render 'Thumbnail', 'Medium', 'Large', and 'Full' sizes of
the first page, and save them in attachment meta.

Use these renders within Add Media, Media Gallery and List views,
Attachment Details, Post/Attachment Edit screens, and Attachment pages.

Support available by default via Imagick -> ImageMagick -> Ghostscript,
but can be provided by any WP_Image_Editor that supports PDFs.

Props adamsilverstein, azaozz, celloexpressions, desrosj, dglingren, ericlewis, ipstenu, joemcgill, joyously, markoheijnen, melchoyce, mikeschroder, tomauger.
Fixes #31050.

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/image.php

    r38333 r38949  
    7777    $metadata = array(); 
    7878    $support = false; 
    79     if ( preg_match('!^image/!', get_post_mime_type( $attachment )) && file_is_displayable_image($file) ) { 
     79    $mime_type = get_post_mime_type( $attachment ); 
     80 
     81    if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) { 
    8082        $imagesize = getimagesize( $file ); 
    8183        $metadata['width'] = $imagesize[0]; 
     
    202204        } 
    203205    } 
     206    // Try to create image thumbnails for PDFs 
     207    else if ( 'application/pdf' === $mime_type ) { 
     208        $editor = wp_get_image_editor( $file ); 
     209 
     210        $fallback_sizes = array( 
     211            'thumbnail', 
     212            'medium', 
     213            'large', 
     214        ); 
     215 
     216        $sizes = array(); 
     217 
     218        foreach ( $fallback_sizes as $s ) { 
     219            $sizes[$s]['width']  = get_option( "{$s}_size_w" ); 
     220            $sizes[$s]['height'] = get_option( "{$s}_size_h" ); 
     221 
     222            // Force thumbnails to be soft crops. 
     223            if ( ! 'thumbnail' === $s ) { 
     224                $sizes[$s]['crop'] = get_option( "{$s}_crop" ); 
     225            } 
     226        } 
     227 
     228        if ( ! is_wp_error( $editor ) ) { // No support for this type of file 
     229            $uploaded = $editor->save( $file, 'image/jpeg' ); 
     230            unset( $editor ); 
     231 
     232            // Resize based on the full size image, rather than the source. 
     233            if ( ! is_wp_error( $uploaded ) ) { 
     234                $editor = wp_get_image_editor( $uploaded['path'] ); 
     235                unset( $uploaded['path'] ); 
     236 
     237                if ( ! is_wp_error( $editor ) ) { 
     238                    $metadata['sizes'] = $editor->multi_resize( $sizes ); 
     239                    $metadata['sizes']['full'] = $uploaded; 
     240                } 
     241            } 
     242        } 
     243    } 
    204244 
    205245    // Remove the blob of binary data from the array. 
  • trunk/src/wp-admin/includes/media.php

    r38734 r38949  
    27672767        echo wp_video_shortcode( $attr ); 
    27682768 
    2769     else : 
     2769    elseif ( isset( $thumb_url[0] ) ): 
     2770 
     2771        ?> 
     2772        <div class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>"> 
     2773            <p id="thumbnail-head-<?php echo $attachment_id; ?>"> 
     2774                <img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" /> 
     2775            </p> 
     2776        </div> 
     2777        <?php 
     2778 
     2779    else: 
    27702780 
    27712781        /** 
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r38015 r38949  
    7474            'flipimage', 
    7575            'flopimage', 
     76            'readimage', 
    7677        ); 
    7778 
     
    145146 
    146147        try { 
    147             $this->image = new Imagick( $this->file ); 
     148            $this->image = new Imagick(); 
     149            $file_parts = pathinfo( $this->file ); 
     150 
     151            // By default, PDFs are rendered in a very low resolution. 
     152            // We want the thumbnail to be readable, so increase the rendering dpi. 
     153            if ( 'pdf' == strtolower( $file_parts['extension'] ) ) { 
     154                $this->image->setResolution( 128, 128 ); 
     155            } 
     156 
     157            // Reading image after Imagick instantiation because `setResolution` 
     158            // only applies correctly before the image is read. 
     159            $this->image->readImage( $this->file ); 
    148160 
    149161            if ( ! $this->image->valid() ) 
  • trunk/src/wp-includes/media-template.php

    r38468 r38949  
    291291                <# if ( data.uploading ) { #> 
    292292                    <div class="media-progress-bar"><div></div></div> 
    293                 <# } else if ( 'image' === data.type && data.sizes && data.sizes.large ) { #> 
     293                <# } else if ( data.sizes && data.sizes.large ) { #> 
    294294                    <img class="details-image" src="{{ data.sizes.large.url }}" draggable="false" alt="" /> 
    295                 <# } else if ( 'image' === data.type && data.sizes && data.sizes.full ) { #> 
     295                <# } else if ( data.sizes && data.sizes.full ) { #> 
    296296                    <img class="details-image" src="{{ data.sizes.full.url }}" draggable="false" alt="" /> 
    297297                <# } else if ( -1 === jQuery.inArray( data.type, [ 'audio', 'video' ] ) ) { #> 
     
    455455                        <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #> 
    456456                            <img src="{{ data.image.src }}" class="thumbnail" draggable="false" alt="" /> 
     457                        <# } else if ( data.sizes && data.sizes.medium ) { #> 
     458                            <img src="{{ data.sizes.medium.url }}" class="thumbnail" draggable="false" alt="" /> 
    457459                        <# } else { #> 
    458460                            <img src="{{ data.icon }}" class="icon" draggable="false" alt="" /> 
  • trunk/src/wp-includes/media.php

    r38812 r38949  
    184184 */ 
    185185function image_downsize( $id, $size = 'medium' ) { 
    186  
    187     if ( !wp_attachment_is_image($id) ) 
    188         return false; 
     186    $is_image = wp_attachment_is_image( $id ); 
    189187 
    190188    /** 
     
    210208    $is_intermediate = false; 
    211209    $img_url_basename = wp_basename($img_url); 
     210 
     211    // If the file isn't an image, attempt to replace its URL with a rendered image from its meta. 
     212    // Otherwise, a non-image type could be returned. 
     213    if ( ! $is_image ) { 
     214        if ( ! empty( $meta['sizes'] ) ) { 
     215            $img_url = str_replace( $img_url_basename, $meta['sizes']['full']['file'], $img_url ); 
     216            $img_url_basename = $meta['sizes']['full']['file']; 
     217            $width = $meta['sizes']['full']['width']; 
     218            $height = $meta['sizes']['full']['height']; 
     219        } else { 
     220            return false; 
     221        } 
     222    } 
    212223 
    213224    // try for a new style intermediate size 
     
    685696    if ( is_array( $size ) ) { 
    686697        $candidates = array(); 
     698 
     699        if ( ! isset( $imagedata['file'] ) && isset( $imagedata['sizes']['full'] ) ) { 
     700            $imagedata['height'] = $imagedata['sizes']['full']['height']; 
     701            $imagedata['width']  = $imagedata['sizes']['full']['width']; 
     702        } 
    687703 
    688704        foreach ( $imagedata['sizes'] as $_size => $data ) { 
     
    739755 
    740756    // include the full filesystem path of the intermediate file 
    741     if ( empty($data['path']) && !empty($data['file']) ) { 
     757    if ( empty( $data['path'] ) && ! empty( $data['file'] ) && ! empty( $imagedata['file'] ) ) { 
    742758        $file_url = wp_get_attachment_url($post_id); 
    743759        $data['path'] = path_join( dirname($imagedata['file']), $data['file'] ); 
     
    31243140        $response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID ); 
    31253141 
    3126     if ( $meta && 'image' === $type ) { 
     3142    if ( $meta && ! empty( $meta['sizes'] ) ) { 
    31273143        $sizes = array(); 
    31283144 
     
    31723188        } 
    31733189 
    3174         $sizes['full'] = array( 'url' => $attachment_url ); 
    3175  
    3176         if ( isset( $meta['height'], $meta['width'] ) ) { 
    3177             $sizes['full']['height'] = $meta['height']; 
    3178             $sizes['full']['width'] = $meta['width']; 
    3179             $sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape'; 
    3180         } 
    3181  
    3182         $response = array_merge( $response, array( 'sizes' => $sizes ), $sizes['full'] ); 
    3183     } elseif ( $meta && 'video' === $type ) { 
     3190        if ( 'image' === $type ) { 
     3191            $sizes['full'] = array( 'url' => $attachment_url ); 
     3192 
     3193            if ( isset( $meta['height'], $meta['width'] ) ) { 
     3194                $sizes['full']['height'] = $meta['height']; 
     3195                $sizes['full']['width'] = $meta['width']; 
     3196                $sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape'; 
     3197            } 
     3198 
     3199            $response = array_merge( $response, $sizes['full'] ); 
     3200        } elseif ( $meta['sizes']['full']['file'] ) { 
     3201            $sizes['full'] = array( 
     3202                'url'         => $base_url . $meta['sizes']['full']['file'], 
     3203                'height'      => $meta['sizes']['full']['height'], 
     3204                'width'       => $meta['sizes']['full']['width'], 
     3205                'orientation' => $meta['sizes']['full']['height'] > $meta['sizes']['full']['width'] ? 'portrait' : 'landscape' 
     3206            ); 
     3207        } 
     3208 
     3209        $response = array_merge( $response, array( 'sizes' => $sizes ) ); 
     3210    } 
     3211 
     3212    if ( $meta && 'video' === $type ) { 
    31843213        if ( isset( $meta['width'] ) ) 
    31853214            $response['width'] = (int) $meta['width']; 
  • trunk/tests/phpunit/tests/image/functions.php

    r38762 r38949  
    352352        WP_Image_Editor_Mock::$save_return = array(); 
    353353    } 
     354 
     355    /** 
     356     * @ticket 31050 
     357     */ 
     358    public function test_wp_generate_attachment_metadata_pdf() { 
     359        if ( ! wp_image_editor_supports( array( 'mime_type' => 'application/pdf' ) ) ) { 
     360            $this->markTestSkipped( 'Rendering PDFs is not supported on this system.' ); 
     361        } 
     362 
     363        $orig_file = DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf'; 
     364        $test_file = '/tmp/wordpress-gsoc-flyer.pdf'; 
     365        copy( $orig_file, $test_file ); 
     366 
     367        $attachment_id = $this->factory->attachment->create_object( $test_file, 0, array( 
     368            'post_mime_type' => 'application/pdf', 
     369        ) ); 
     370 
     371        $this->assertNotEmpty( $attachment_id ); 
     372 
     373        $expected = array( 
     374            'sizes' => array( 
     375                'thumbnail' => array( 
     376                    'file'      => "wordpress-gsoc-flyer-116x150.jpg", 
     377                    'width'     => 116, 
     378                    'height'    => 150, 
     379                    'mime-type' => "image/jpeg", 
     380                ), 
     381                'medium'    => array( 
     382                    'file'      => "wordpress-gsoc-flyer-232x300.jpg", 
     383                    'width'     => 232, 
     384                    'height'    => 300, 
     385                    'mime-type' => "image/jpeg", 
     386                ), 
     387                'large'     => array( 
     388                    'file'      => "wordpress-gsoc-flyer-791x1024.jpg", 
     389                    'width'     => 791, 
     390                    'height'    => 1024, 
     391                    'mime-type' => "image/jpeg", 
     392                ), 
     393                'full'      => array( 
     394                    'file'      => "wordpress-gsoc-flyer.jpg", 
     395                    'width'     => 1088, 
     396                    'height'    => 1408, 
     397                    'mime-type' => "image/jpeg", 
     398                ), 
     399            ), 
     400        ); 
     401 
     402        $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); 
     403        $this->assertSame( $expected, $metadata ); 
     404 
     405        unlink( $test_file ); 
     406    } 
    354407} 
Note: See TracChangeset for help on using the changeset viewer.