wp/wp-includes/class-wp-image-editor-gd.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
--- a/wp/wp-includes/class-wp-image-editor-gd.php	Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-includes/class-wp-image-editor-gd.php	Fri Sep 05 18:52:52 2025 +0200
@@ -103,20 +103,13 @@
 			return new WP_Error( 'error_loading_image', __( 'File does not exist?' ), $this->file );
 		}
 
-		// WebP may not work with imagecreatefromstring().
+		// Handle WebP and AVIF mime types explicitly, falling back to imagecreatefromstring.
 		if (
-			function_exists( 'imagecreatefromwebp' ) &&
-			( 'image/webp' === wp_get_image_mime( $this->file ) )
+			function_exists( 'imagecreatefromwebp' ) && ( 'image/webp' === wp_get_image_mime( $this->file ) )
 		) {
 			$this->image = @imagecreatefromwebp( $this->file );
-		} else {
-			$this->image = @imagecreatefromstring( $file_contents );
-		}
-
-		// AVIF may not work with imagecreatefromstring().
-		if (
-			function_exists( 'imagecreatefromavif' ) &&
-			( 'image/avif' === wp_get_image_mime( $this->file ) )
+		} elseif (
+			function_exists( 'imagecreatefromavif' ) && ( 'image/avif' === wp_get_image_mime( $this->file ) )
 		) {
 			$this->image = @imagecreatefromavif( $this->file );
 		} else {
@@ -182,7 +175,7 @@
 	 *     If true, image will be cropped to the specified dimensions using center positions.
 	 *     If an array, the image will be cropped using the array to specify the crop location:
 	 *
-	 *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
+	 *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
 	 *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
 	 * }
 	 * @return true|WP_Error
@@ -214,7 +207,7 @@
 	 *     If true, image will be cropped to the specified dimensions using center positions.
 	 *     If an array, the image will be cropped using the array to specify the crop location:
 	 *
-	 *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
+	 *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
 	 *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
 	 * }
 	 * @return resource|GdImage|WP_Error
@@ -228,6 +221,14 @@
 
 		list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
 
+		$this->set_quality(
+			null,
+			array(
+				'width'  => $dst_w,
+				'height' => $dst_h,
+			)
+		);
+
 		$resized = wp_imagecreatetruecolor( $dst_w, $dst_h );
 		imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
 
@@ -572,6 +573,40 @@
 	}
 
 	/**
+	 * Sets Image Compression quality on a 1-100% scale. Handles WebP lossless images.
+	 *
+	 * @since 6.7.0
+	 * @since 6.8.0 The `$dims` parameter was added.
+	 *
+	 * @param int   $quality Compression Quality. Range: [1,100]
+	 * @param array $dims    Optional. Image dimensions array with 'width' and 'height' keys.
+	 * @return true|WP_Error True if set successfully; WP_Error on failure.
+	 */
+	public function set_quality( $quality = null, $dims = array() ) {
+		$quality_result = parent::set_quality( $quality, $dims );
+		if ( is_wp_error( $quality_result ) ) {
+			return $quality_result;
+		} else {
+			$quality = $this->get_quality();
+		}
+
+		// Handle setting the quality for WebP lossless images, see https://php.watch/versions/8.1/gd-webp-lossless.
+		try {
+			if ( 'image/webp' === $this->mime_type && defined( 'IMG_WEBP_LOSSLESS' ) ) {
+				$webp_info = wp_get_webp_info( $this->file );
+				if ( ! empty( $webp_info['type'] ) && 'lossless' === $webp_info['type'] ) {
+					$quality = IMG_WEBP_LOSSLESS;
+					parent::set_quality( $quality, $dims );
+				}
+			}
+		} catch ( Exception $e ) {
+			return new WP_Error( 'image_quality_error', $e->getMessage() );
+		}
+		$this->quality = $quality;
+		return true;
+	}
+
+	/**
 	 * Returns stream of current image.
 	 *
 	 * @since 3.5.0