Make WordPress Core


Ignore:
Timestamp:
12/01/2019 06:24:30 PM (4 years ago)
Author:
azaozz
Message:

Upload: Exclude PNG images from scaling after uploading. Fixes a case where resizing a very large PNG may create a scaled image that has smaller dimensions but larger file size than the original.

Fixes #48736.

File:
1 edited

Legend:

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

    r46677 r46809  
    245245    }
    246246
    247     /**
    248      * Filters the "BIG image" threshold value.
    249      *
    250      * If the original image width or height is above the threshold, it will be scaled down. The threshold is
    251      * used as max width and max height. The scaled down image will be used as the largest available size, including
    252      * the `_wp_attached_file` post meta value.
    253      *
    254      * Returning `false` from the filter callback will disable the scaling.
    255      *
    256      * @since 5.3.0
    257      *
    258      * @param int    $threshold     The threshold value in pixels. Default 2560.
    259      * @param array  $imagesize     {
    260      *     Indexed array of the image width and height in pixels.
    261      *
    262      *     @type int $0 The image width.
    263      *     @type int $1 The image height.
    264      * }
    265      * @param string $file          Full path to the uploaded image file.
    266      * @param int    $attachment_id Attachment post ID.
    267      */
    268     $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
    269 
    270     // If the original image's dimensions are over the threshold, scale the image
    271     // and use it as the "full" size.
    272     if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
    273         $editor = wp_get_image_editor( $file );
    274 
    275         if ( is_wp_error( $editor ) ) {
    276             // This image cannot be edited.
    277             return $image_meta;
    278         }
    279 
    280         // Resize the image
    281         $resized = $editor->resize( $threshold, $threshold );
    282         $rotated = null;
    283 
    284         // If there is EXIF data, rotate according to EXIF Orientation.
    285         if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
    286             $resized = $editor->maybe_exif_rotate();
    287             $rotated = $resized;
    288         }
    289 
    290         if ( ! is_wp_error( $resized ) ) {
    291             // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
    292             // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
    293             $saved = $editor->save( $editor->generate_filename( 'scaled' ) );
    294 
    295             if ( ! is_wp_error( $saved ) ) {
    296                 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
    297 
    298                 // If the image was rotated update the stored EXIF data.
    299                 if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
    300                     $image_meta['image_meta']['orientation'] = 1;
     247    // Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736.
     248    if ( $imagesize['mime'] !== 'image/png' ) {
     249
     250        /**
     251         * Filters the "BIG image" threshold value.
     252         *
     253         * If the original image width or height is above the threshold, it will be scaled down. The threshold is
     254         * used as max width and max height. The scaled down image will be used as the largest available size, including
     255         * the `_wp_attached_file` post meta value.
     256         *
     257         * Returning `false` from the filter callback will disable the scaling.
     258         *
     259         * @since 5.3.0
     260         *
     261         * @param int    $threshold     The threshold value in pixels. Default 2560.
     262         * @param array  $imagesize     {
     263         *     Indexed array of the image width and height in pixels.
     264         *
     265         *     @type int $0 The image width.
     266         *     @type int $1 The image height.
     267         * }
     268         * @param string $file          Full path to the uploaded image file.
     269         * @param int    $attachment_id Attachment post ID.
     270         */
     271        $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
     272
     273        // If the original image's dimensions are over the threshold, scale the image
     274        // and use it as the "full" size.
     275        if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
     276            $editor = wp_get_image_editor( $file );
     277
     278            if ( is_wp_error( $editor ) ) {
     279                // This image cannot be edited.
     280                return $image_meta;
     281            }
     282
     283            // Resize the image
     284            $resized = $editor->resize( $threshold, $threshold );
     285            $rotated = null;
     286
     287            // If there is EXIF data, rotate according to EXIF Orientation.
     288            if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
     289                $resized = $editor->maybe_exif_rotate();
     290                $rotated = $resized;
     291            }
     292
     293            if ( ! is_wp_error( $resized ) ) {
     294                // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
     295                // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
     296                $saved = $editor->save( $editor->generate_filename( 'scaled' ) );
     297
     298                if ( ! is_wp_error( $saved ) ) {
     299                    $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
     300
     301                    // If the image was rotated update the stored EXIF data.
     302                    if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
     303                        $image_meta['image_meta']['orientation'] = 1;
     304                    }
     305                } else {
     306                    // TODO: log errors.
    301307                }
    302308            } else {
    303309                // TODO: log errors.
    304310            }
    305         } else {
    306             // TODO: log errors.
    307         }
    308     } elseif ( ! empty( $exif_meta['orientation'] ) && (int) $exif_meta['orientation'] !== 1 ) {
    309         // Rotate the whole original image if there is EXIF data and "orientation" is not 1.
    310 
    311         $editor = wp_get_image_editor( $file );
    312 
    313         if ( is_wp_error( $editor ) ) {
    314             // This image cannot be edited.
    315             return $image_meta;
    316         }
    317 
    318         // Rotate the image
    319         $rotated = $editor->maybe_exif_rotate();
    320 
    321         if ( true === $rotated ) {
    322             // Append `-rotated` to the image file name.
    323             $saved = $editor->save( $editor->generate_filename( 'rotated' ) );
    324 
    325             if ( ! is_wp_error( $saved ) ) {
    326                 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
    327 
    328                 // Update the stored EXIF data.
    329                 if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
    330                     $image_meta['image_meta']['orientation'] = 1;
     311        } elseif ( ! empty( $exif_meta['orientation'] ) && (int) $exif_meta['orientation'] !== 1 ) {
     312            // Rotate the whole original image if there is EXIF data and "orientation" is not 1.
     313
     314            $editor = wp_get_image_editor( $file );
     315
     316            if ( is_wp_error( $editor ) ) {
     317                // This image cannot be edited.
     318                return $image_meta;
     319            }
     320
     321            // Rotate the image
     322            $rotated = $editor->maybe_exif_rotate();
     323
     324            if ( true === $rotated ) {
     325                // Append `-rotated` to the image file name.
     326                $saved = $editor->save( $editor->generate_filename( 'rotated' ) );
     327
     328                if ( ! is_wp_error( $saved ) ) {
     329                    $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
     330
     331                    // Update the stored EXIF data.
     332                    if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
     333                        $image_meta['image_meta']['orientation'] = 1;
     334                    }
     335                } else {
     336                    // TODO: log errors.
    331337                }
    332             } else {
    333                 // TODO: log errors.
    334338            }
    335339        }
Note: See TracChangeset for help on using the changeset viewer.