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.
Built from https://develop.svn.wordpress.org/trunk@38949


git-svn-id: http://core.svn.wordpress.org/trunk@38892 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Mike Schroder 2016-10-26 07:28:32 +00:00
parent a86496aea4
commit a8e304ec8e
6 changed files with 111 additions and 18 deletions

View File

@ -76,7 +76,9 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
$metadata = array();
$support = false;
if ( preg_match('!^image/!', get_post_mime_type( $attachment )) && file_is_displayable_image($file) ) {
$mime_type = get_post_mime_type( $attachment );
if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
$imagesize = getimagesize( $file );
$metadata['width'] = $imagesize[0];
$metadata['height'] = $imagesize[1];
@ -201,6 +203,44 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
}
}
}
// Try to create image thumbnails for PDFs
else if ( 'application/pdf' === $mime_type ) {
$editor = wp_get_image_editor( $file );
$fallback_sizes = array(
'thumbnail',
'medium',
'large',
);
$sizes = array();
foreach ( $fallback_sizes as $s ) {
$sizes[$s]['width'] = get_option( "{$s}_size_w" );
$sizes[$s]['height'] = get_option( "{$s}_size_h" );
// Force thumbnails to be soft crops.
if ( ! 'thumbnail' === $s ) {
$sizes[$s]['crop'] = get_option( "{$s}_crop" );
}
}
if ( ! is_wp_error( $editor ) ) { // No support for this type of file
$uploaded = $editor->save( $file, 'image/jpeg' );
unset( $editor );
// Resize based on the full size image, rather than the source.
if ( ! is_wp_error( $uploaded ) ) {
$editor = wp_get_image_editor( $uploaded['path'] );
unset( $uploaded['path'] );
if ( ! is_wp_error( $editor ) ) {
$metadata['sizes'] = $editor->multi_resize( $sizes );
$metadata['sizes']['full'] = $uploaded;
}
}
}
}
// Remove the blob of binary data from the array.
if ( $metadata ) {

View File

@ -2766,7 +2766,17 @@ function edit_form_image_editor( $post ) {
echo wp_video_shortcode( $attr );
else :
elseif ( isset( $thumb_url[0] ) ):
?>
<div class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>">
<p id="thumbnail-head-<?php echo $attachment_id; ?>">
<img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" />
</p>
</div>
<?php
else:
/**
* Fires when an attachment type can't be rendered in the edit form.

View File

@ -73,6 +73,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
'rotateimage',
'flipimage',
'flopimage',
'readimage',
);
// Now, test for deep requirements within Imagick.
@ -144,7 +145,18 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
wp_raise_memory_limit( 'image' );
try {
$this->image = new Imagick( $this->file );
$this->image = new Imagick();
$file_parts = pathinfo( $this->file );
// By default, PDFs are rendered in a very low resolution.
// We want the thumbnail to be readable, so increase the rendering dpi.
if ( 'pdf' == strtolower( $file_parts['extension'] ) ) {
$this->image->setResolution( 128, 128 );
}
// Reading image after Imagick instantiation because `setResolution`
// only applies correctly before the image is read.
$this->image->readImage( $this->file );
if ( ! $this->image->valid() )
return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file);

View File

@ -290,9 +290,9 @@ function wp_print_media_templates() {
<div class="thumbnail thumbnail-{{ data.type }}">
<# if ( data.uploading ) { #>
<div class="media-progress-bar"><div></div></div>
<# } else if ( 'image' === data.type && data.sizes && data.sizes.large ) { #>
<# } else if ( data.sizes && data.sizes.large ) { #>
<img class="details-image" src="{{ data.sizes.large.url }}" draggable="false" alt="" />
<# } else if ( 'image' === data.type && data.sizes && data.sizes.full ) { #>
<# } else if ( data.sizes && data.sizes.full ) { #>
<img class="details-image" src="{{ data.sizes.full.url }}" draggable="false" alt="" />
<# } else if ( -1 === jQuery.inArray( data.type, [ 'audio', 'video' ] ) ) { #>
<img class="details-image icon" src="{{ data.icon }}" draggable="false" alt="" />
@ -454,6 +454,8 @@ function wp_print_media_templates() {
<div class="centered">
<# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
<img src="{{ data.image.src }}" class="thumbnail" draggable="false" alt="" />
<# } else if ( data.sizes && data.sizes.medium ) { #>
<img src="{{ data.sizes.medium.url }}" class="thumbnail" draggable="false" alt="" />
<# } else { #>
<img src="{{ data.icon }}" class="icon" draggable="false" alt="" />
<# } #>

View File

@ -183,9 +183,7 @@ function image_hwstring( $width, $height ) {
* the image is an intermediate size. False on failure.
*/
function image_downsize( $id, $size = 'medium' ) {
if ( !wp_attachment_is_image($id) )
return false;
$is_image = wp_attachment_is_image( $id );
/**
* Filters whether to preempt the output of image_downsize().
@ -210,6 +208,19 @@ function image_downsize( $id, $size = 'medium' ) {
$is_intermediate = false;
$img_url_basename = wp_basename($img_url);
// If the file isn't an image, attempt to replace its URL with a rendered image from its meta.
// Otherwise, a non-image type could be returned.
if ( ! $is_image ) {
if ( ! empty( $meta['sizes'] ) ) {
$img_url = str_replace( $img_url_basename, $meta['sizes']['full']['file'], $img_url );
$img_url_basename = $meta['sizes']['full']['file'];
$width = $meta['sizes']['full']['width'];
$height = $meta['sizes']['full']['height'];
} else {
return false;
}
}
// try for a new style intermediate size
if ( $intermediate = image_get_intermediate_size($id, $size) ) {
$img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
@ -685,6 +696,11 @@ function image_get_intermediate_size( $post_id, $size = 'thumbnail' ) {
if ( is_array( $size ) ) {
$candidates = array();
if ( ! isset( $imagedata['file'] ) && isset( $imagedata['sizes']['full'] ) ) {
$imagedata['height'] = $imagedata['sizes']['full']['height'];
$imagedata['width'] = $imagedata['sizes']['full']['width'];
}
foreach ( $imagedata['sizes'] as $_size => $data ) {
// If there's an exact match to an existing image size, short circuit.
if ( $data['width'] == $size[0] && $data['height'] == $size[1] ) {
@ -738,7 +754,7 @@ function image_get_intermediate_size( $post_id, $size = 'thumbnail' ) {
}
// include the full filesystem path of the intermediate file
if ( empty($data['path']) && !empty($data['file']) ) {
if ( empty( $data['path'] ) && ! empty( $data['file'] ) && ! empty( $imagedata['file'] ) ) {
$file_url = wp_get_attachment_url($post_id);
$data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
$data['url'] = path_join( dirname($file_url), $data['file'] );
@ -3123,7 +3139,7 @@ function wp_prepare_attachment_for_js( $attachment ) {
if ( current_user_can( 'delete_post', $attachment->ID ) )
$response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID );
if ( $meta && 'image' === $type ) {
if ( $meta && ! empty( $meta['sizes'] ) ) {
$sizes = array();
/** This filter is documented in wp-admin/includes/media.php */
@ -3171,16 +3187,29 @@ function wp_prepare_attachment_for_js( $attachment ) {
}
}
$sizes['full'] = array( 'url' => $attachment_url );
if ( 'image' === $type ) {
$sizes['full'] = array( 'url' => $attachment_url );
if ( isset( $meta['height'], $meta['width'] ) ) {
$sizes['full']['height'] = $meta['height'];
$sizes['full']['width'] = $meta['width'];
$sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape';
if ( isset( $meta['height'], $meta['width'] ) ) {
$sizes['full']['height'] = $meta['height'];
$sizes['full']['width'] = $meta['width'];
$sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape';
}
$response = array_merge( $response, $sizes['full'] );
} elseif ( $meta['sizes']['full']['file'] ) {
$sizes['full'] = array(
'url' => $base_url . $meta['sizes']['full']['file'],
'height' => $meta['sizes']['full']['height'],
'width' => $meta['sizes']['full']['width'],
'orientation' => $meta['sizes']['full']['height'] > $meta['sizes']['full']['width'] ? 'portrait' : 'landscape'
);
}
$response = array_merge( $response, array( 'sizes' => $sizes ), $sizes['full'] );
} elseif ( $meta && 'video' === $type ) {
$response = array_merge( $response, array( 'sizes' => $sizes ) );
}
if ( $meta && 'video' === $type ) {
if ( isset( $meta['width'] ) )
$response['width'] = (int) $meta['width'];
if ( isset( $meta['height'] ) )

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.7-alpha-38948';
$wp_version = '4.7-alpha-38949';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.