diff --git src/wp-admin/includes/image.php src/wp-admin/includes/image.php
index 84e4c4c..6058197 100644
--- src/wp-admin/includes/image.php
+++ src/wp-admin/includes/image.php
@@ -76,7 +76,18 @@ 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 );
+
+	/**
+	 * Filter attachment mime-types that support thumbnail fallback.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @param array $mime_types An array of mime-types.
+	 */
+	$attachment_fallback_mimetypes = apply_filters( 'attachment_fallback_mimetypes', array( 'application/pdf' ) );
+
+	if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) {
 		$imagesize = getimagesize( $file );
 		$metadata['width'] = $imagesize[0];
 		$metadata['height'] = $imagesize[1];
@@ -201,6 +212,40 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
 			}
 		}
 	}
+	// Check to see if we support a fallback thumbnail for this mime-type.
+	else if ( in_array( $mime_type, $attachment_fallback_mimetypes ) ) {
+		$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" );
+			$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 ) {
diff --git src/wp-admin/includes/media.php src/wp-admin/includes/media.php
index 1ccb998..c79e312 100644
--- src/wp-admin/includes/media.php
+++ src/wp-admin/includes/media.php
@@ -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.
diff --git src/wp-includes/class-wp-image-editor-imagick.php src/wp-includes/class-wp-image-editor-imagick.php
index 82b872d..fb56eb1 100644
--- src/wp-includes/class-wp-image-editor-imagick.php
+++ src/wp-includes/class-wp-image-editor-imagick.php
@@ -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);
diff --git src/wp-includes/media-template.php src/wp-includes/media-template.php
index c669921..95fbb9a 100644
--- src/wp-includes/media-template.php
+++ src/wp-includes/media-template.php
@@ -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="" />
 						<# } #>
diff --git src/wp-includes/media.php src/wp-includes/media.php
index f6c5f0f..3633e4f 100644
--- src/wp-includes/media.php
+++ src/wp-includes/media.php
@@ -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,11 @@ function image_downsize( $id, $size = 'medium' ) {
 	$is_intermediate = false;
 	$img_url_basename = wp_basename($img_url);
 
+	// Bail early if the attachment isn't an image and doens't contain sizes metadata.
+	if ( ! $is_image && ! isset( $meta['sizes']) ) {
+		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 +688,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 +746,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 +3131,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 +3179,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'] ) )
