diff --git src/js/_enqueues/vendor/plupload/handlers.js src/js/_enqueues/vendor/plupload/handlers.js
index fa602daf43..c7e3c253d3 100644
--- src/js/_enqueues/vendor/plupload/handlers.js
+++ src/js/_enqueues/vendor/plupload/handlers.js
@@ -486,7 +486,7 @@ jQuery( document ).ready( function( $ ) {
 
 		times = tryAgainCount[ file.id ];
 
-		if ( times && times > 4 ) {
+		if ( times && times > 8 ) {
 			/*
 			 * The file may have been uploaded and attachment post created,
 			 * but post-processing and resizing failed...
diff --git src/js/_enqueues/vendor/plupload/wp-plupload.js src/js/_enqueues/vendor/plupload/wp-plupload.js
index 0fdebf77d1..217b3c09e2 100644
--- src/js/_enqueues/vendor/plupload/wp-plupload.js
+++ src/js/_enqueues/vendor/plupload/wp-plupload.js
@@ -138,7 +138,7 @@ window.wp = window.wp || {};
 
 			times = tryAgainCount[ file.id ];
 
-			if ( times && times > 4 ) {
+			if ( times && times > 8 ) {
 				/*
 				 * The file may have been uploaded and attachment post created,
 				 * but post-processing and resizing failed...
diff --git src/wp-admin/includes/image.php src/wp-admin/includes/image.php
index 2818b3dd5d..854ba08ce1 100644
--- src/wp-admin/includes/image.php
+++ src/wp-admin/includes/image.php
@@ -217,12 +217,13 @@ function _wp_image_meta_replace_original( $saved_data, $original_file, $image_me
 }
 
 /**
- * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
+ * Creates image mime variations and sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
  *
  * Intended for use after an image is uploaded. Saves/updates the image metadata after each
  * sub-size is created. If there was an error, it is added to the returned image metadata array.
  *
  * @since 5.3.0
+ * @since 6.0.0 Generates sub-sizes in alternate mime types based on the `wp_image_mime_transforms` filter.
  *
  * @param string $file          Full path to the image file.
  * @param int    $attachment_id Attachment ID to process.
@@ -243,6 +244,7 @@ function wp_create_image_subsizes( $file, $attachment_id ) {
 		'file'     => _wp_relative_upload_path( $file ),
 		'filesize' => wp_filesize( $file ),
 		'sizes'    => array(),
+		'sources'  => array(),
 	);
 
 	// Fetch additional metadata from EXIF/IPTC.
@@ -252,106 +254,133 @@ function wp_create_image_subsizes( $file, $attachment_id ) {
 		$image_meta['image_meta'] = $exif_meta;
 	}
 
-	// Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736.
-	if ( 'image/png' !== $imagesize['mime'] ) {
-
-		/**
-		 * Filters the "BIG image" threshold value.
-		 *
-		 * If the original image width or height is above the threshold, it will be scaled down. The threshold is
-		 * used as max width and max height. The scaled down image will be used as the largest available size, including
-		 * the `_wp_attached_file` post meta value.
-		 *
-		 * Returning `false` from the filter callback will disable the scaling.
-		 *
-		 * @since 5.3.0
-		 *
-		 * @param int    $threshold     The threshold value in pixels. Default 2560.
-		 * @param array  $imagesize     {
-		 *     Indexed array of the image width and height in pixels.
-		 *
-		 *     @type int $0 The image width.
-		 *     @type int $1 The image height.
-		 * }
-		 * @param string $file          Full path to the uploaded image file.
-		 * @param int    $attachment_id Attachment post ID.
-		 */
-		$threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
-
-		// If the original image's dimensions are over the threshold,
-		// scale the image and use it as the "full" size.
-		if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
-			$editor = wp_get_image_editor( $file );
+	// Calculate the primary (first) and additional mime types to generate.
+	$mime_types_to_generate = _wp_get_primary_and_additional_mime_types( $file, $attachment_id );
+	foreach ( $mime_types_to_generate as $output_index => $output_mime_type ) {
+		// Populate the top level primary mime type data.
+		if ( 0 === $output_index ) {
+			$image_meta['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $image_meta );
+			wp_update_attachment_metadata( $attachment_id, $image_meta );
+		}
 
-			if ( is_wp_error( $editor ) ) {
-				// This image cannot be edited.
-				return $image_meta;
-			}
+		// Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736.
+		if ( 'image/png' !== $imagesize['mime'] ) {
+			/**
+			 * Filters the "BIG image" threshold value.
+			 *
+			 * If the original image width or height is above the threshold, it will be scaled down. The threshold is
+			 * used as max width and max height. The scaled down image will be used as the largest available size, including
+			 * the `_wp_attached_file` post meta value.
+			 *
+			 * Returning `false` from the filter callback will disable the scaling.
+			 *
+			 * @since 5.3.0
+			 *
+			 * @param int    $threshold     The threshold value in pixels. Default 2560.
+			 * @param array  $imagesize     {
+			 *     Indexed array of the image width and height in pixels.
+			 *
+			 *     @type int $0 The image width.
+			 *     @type int $1 The image height.
+			 * }
+			 * @param string $file          Full path to the uploaded image file.
+			 * @param int    $attachment_id Attachment post ID.
+			 */
+			$threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );
 
-			// Resize the image.
-			$resized = $editor->resize( $threshold, $threshold );
-			$rotated = null;
+			// If the original image's dimensions are over the threshold,
+			// scale the image and use it as the "full" size.
+			if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
+				$editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) );
 
-			// If there is EXIF data, rotate according to EXIF Orientation.
-			if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
-				$resized = $editor->maybe_exif_rotate();
-				$rotated = $resized;
-			}
+				if ( is_wp_error( $editor ) ) {
+					// This image cannot be edited.
+					return $image_meta;
+				}
+				$editor->set_mime_type( $output_mime_type );
 
-			if ( ! is_wp_error( $resized ) ) {
-				// Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
-				// This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
-				$saved = $editor->save( $editor->generate_filename( 'scaled' ) );
+				// Resize the image.
+				$resized = $editor->resize( $threshold, $threshold );
+				$rotated = null;
 
-				if ( ! is_wp_error( $saved ) ) {
-					$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
+				// If there is EXIF data, rotate according to EXIF Orientation.
+				if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
+					$resized = $editor->maybe_exif_rotate();
+					$rotated = $resized;
+				}
 
-					// If the image was rotated update the stored EXIF data.
-					if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
-						$image_meta['image_meta']['orientation'] = 1;
+				if ( ! is_wp_error( $resized ) ) {
+					// Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
+					// This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
+					$saved = $editor->save( $editor->generate_filename( 'scaled' ), $output_mime_type );
+
+					if ( ! is_wp_error( $saved ) ) {
+						if ( 0 === $output_index ) {
+							$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
+						}
+						// If the image was rotated update the stored EXIF data.
+						if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
+							$image_meta['image_meta']['orientation'] = 1;
+						}
+					} else {
+						// TODO: Log errors.
 					}
 				} else {
 					// TODO: Log errors.
 				}
 			} else {
-				// TODO: Log errors.
-			}
-		} elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) {
-			// Rotate the whole original image if there is EXIF data and "orientation" is not 1.
+				// Generate additional full sized images.
+				if ( $output_index > 0 ) {
+					if ( empty( $image_meta['sources'][ $output_mime_type ] ) ) {
+						$extension = wp_get_default_extension_for_mime_type( $output_mime_type );
+						$saved     = $editor->save( $editor->generate_filename( '', null, $extension ) );
+						if ( ! is_wp_error( $saved ) ) {
+							$image_meta['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $saved );
+							wp_update_attachment_metadata( $attachment_id, $image_meta );
+						}
+					}
+				}
 
-			$editor = wp_get_image_editor( $file );
+				if ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) {
+					// Rotate the whole original image if there is EXIF data and "orientation" is not 1.
 
-			if ( is_wp_error( $editor ) ) {
-				// This image cannot be edited.
-				return $image_meta;
-			}
+					$editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) );
 
-			// Rotate the image.
-			$rotated = $editor->maybe_exif_rotate();
+					if ( is_wp_error( $editor ) ) {
+						// This image cannot be edited.
+						return $image_meta;
+					}
+
+					$editor->set_mime_type( $output_mime_type );
+
+					// Rotate the image.
+					$rotated = $editor->maybe_exif_rotate();
 
-			if ( true === $rotated ) {
-				// Append `-rotated` to the image file name.
-				$saved = $editor->save( $editor->generate_filename( 'rotated' ) );
+					if ( true === $rotated ) {
+						// Append `-rotated` to the image file name.
+						$saved = $editor->save( $editor->generate_filename( 'rotated' ), $output_mime_type );
 
-				if ( ! is_wp_error( $saved ) ) {
-					$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
+						if ( ! is_wp_error( $saved ) ) {
+							$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
 
-					// Update the stored EXIF data.
-					if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
-						$image_meta['image_meta']['orientation'] = 1;
+							// Update the stored EXIF data.
+							if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
+								$image_meta['image_meta']['orientation'] = 1;
+							}
+						} else {
+							// TODO: Log errors.
+						}
 					}
-				} else {
-					// TODO: Log errors.
 				}
 			}
 		}
 	}
 
 	/*
-	 * Initial save of the new metadata.
-	 * At this point the file was uploaded and moved to the uploads directory
-	 * but the image sub-sizes haven't been created yet and the `sizes` array is empty.
-	 */
+	* Initial save of the new metadata.
+	* At this point the file was uploaded and moved to the uploads directory
+	* but the image sub-sizes haven't been created yet and the `sizes` array is empty.
+	*/
 	wp_update_attachment_metadata( $attachment_id, $image_meta );
 
 	$new_sizes = wp_get_registered_image_subsizes();
@@ -372,6 +401,22 @@ function wp_create_image_subsizes( $file, $attachment_id ) {
 	return _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id );
 }
 
+/**
+ * Gets a sources array element from a meta.
+ *
+ * @since 6.0.0
+ * @access private
+ *
+ * @param array $meta The meta to get the source from.
+ * @return array The source array element.
+ */
+function _wp_get_sources_from_meta( $meta ) {
+	return array(
+		'file'     => wp_basename( $meta['file'] ),
+		'filesize' => isset( $meta['filesize'] ) ? $meta['filesize'] : wp_filesize( $meta['path'] ),
+	);
+}
+
 /**
  * Low-level function to create image sub-sizes.
  *
@@ -379,6 +424,7 @@ function wp_create_image_subsizes( $file, $attachment_id ) {
  * Errors are stored in the returned image metadata array.
  *
  * @since 5.3.0
+ * @since 6.0.0 Support for generating multiple mime type sub-sizes was added.
  * @access private
  *
  * @param array  $new_sizes     Array defining what sizes to create.
@@ -392,77 +438,91 @@ function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
 		// Not an image attachment.
 		return array();
 	}
-
-	// Check if any of the new sizes already exist.
-	if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
-		foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
-			/*
-			 * Only checks "size name" so we don't override existing images even if the dimensions
-			 * don't match the currently defined size with the same name.
-			 * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta.
-			 */
-			if ( array_key_exists( $size_name, $new_sizes ) ) {
-				unset( $new_sizes[ $size_name ] );
+	// Calculate the primary (first) and additional mime types to generate.
+	$mime_types_to_generate = _wp_get_primary_and_additional_mime_types( $file, $attachment_id );
+	foreach ( $mime_types_to_generate as $output_index => $output_mime_type ) {
+		// For the primary image, check if any of the new sizes already exist.
+		if ( 0 === $output_index && isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
+			foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
+				/*
+				* Only checks "size name" so we don't override existing images even if the dimensions
+				* don't match the currently defined size with the same name.
+				* To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta.
+				*/
+				if ( array_key_exists( $size_name, $new_sizes ) ) {
+					unset( $new_sizes[ $size_name ] );
+				}
 			}
+		} else {
+			$image_meta['sizes'] = array();
 		}
-	} else {
-		$image_meta['sizes'] = array();
-	}
 
-	if ( empty( $new_sizes ) ) {
-		// Nothing to do...
-		return $image_meta;
-	}
-
-	/*
-	 * Sort the image sub-sizes in order of priority when creating them.
-	 * This ensures there is an appropriate sub-size the user can access immediately
-	 * even when there was an error and not all sub-sizes were created.
-	 */
-	$priority = array(
-		'medium'       => null,
-		'large'        => null,
-		'thumbnail'    => null,
-		'medium_large' => null,
-	);
-
-	$new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
+		if ( empty( $new_sizes ) ) {
+			// Nothing to do...
+			return $image_meta;
+		}
 
-	$editor = wp_get_image_editor( $file );
+		/*
+		* Sort the image sub-sizes in order of priority when creating them.
+		* This ensures there is an appropriate sub-size the user can access immediately
+		* even when there was an error and not all sub-sizes were created.
+		*/
+		$priority = array(
+			'medium'       => null,
+			'large'        => null,
+			'thumbnail'    => null,
+			'medium_large' => null,
+		);
 
-	if ( is_wp_error( $editor ) ) {
-		// The image cannot be edited.
-		return $image_meta;
-	}
+		$new_sizes = array_filter( array_merge( $priority, $new_sizes ) );
 
-	// If stored EXIF data exists, rotate the source image before creating sub-sizes.
-	if ( ! empty( $image_meta['image_meta'] ) ) {
-		$rotated = $editor->maybe_exif_rotate();
+		$editor = wp_get_image_editor( $file, array( 'mime_type' => $output_mime_type ) );
 
-		if ( is_wp_error( $rotated ) ) {
-			// TODO: Log errors.
+		if ( is_wp_error( $editor ) ) {
+			// The image cannot be edited.
+			return $image_meta;
 		}
-	}
 
-	if ( method_exists( $editor, 'make_subsize' ) ) {
-		foreach ( $new_sizes as $new_size_name => $new_size_data ) {
-			$new_size_meta = $editor->make_subsize( $new_size_data );
+		$editor->set_mime_type( $output_mime_type );
 
-			if ( is_wp_error( $new_size_meta ) ) {
+		// If stored EXIF data exists, rotate the source image before creating sub-sizes.
+		if ( ! empty( $image_meta['image_meta'] ) ) {
+			$rotated = $editor->maybe_exif_rotate();
+
+			if ( is_wp_error( $rotated ) ) {
 				// TODO: Log errors.
-			} else {
-				// Save the size meta value.
-				$image_meta['sizes'][ $new_size_name ] = $new_size_meta;
-				wp_update_attachment_metadata( $attachment_id, $image_meta );
 			}
 		}
-	} else {
-		// Fall back to `$editor->multi_resize()`.
-		$created_sizes = $editor->multi_resize( $new_sizes );
 
-		if ( ! empty( $created_sizes ) ) {
-			$image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
-			wp_update_attachment_metadata( $attachment_id, $image_meta );
+		if ( method_exists( $editor, 'make_subsize' ) ) {
+			foreach ( $new_sizes as $new_size_name => $new_size_data ) {
+				$new_size_meta = $editor->make_subsize( $new_size_data );
+
+				if ( is_wp_error( $new_size_meta ) ) {
+					// TODO: Log errors.
+				} else {
+					// Save the primary mime type sizes meta value.
+					if ( 0 === $output_index ) {
+						$image_meta['sizes'][ $new_size_name ] = $new_size_meta;
+					}
+					// Update the sources array with the new sub-size.
+					$image_meta['sizes'][ $new_size_name ]['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $new_size_meta );
+					wp_update_attachment_metadata( $attachment_id, $image_meta );
+				}
+			}
+		} else {
+			// Fall back to `$editor->multi_resize()`.
+			$created_sizes = $editor->multi_resize( $new_sizes );
+
+			if ( ! empty( $created_sizes ) ) {
+				// Save the primary mime type sizes meta value.
+				if ( 0 === $output_index ) {
+					$image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
+				}
+				// Update the sources array with the new sub-size.
+				$image_meta['sizes'][ $new_size_name ]['sources'][ $output_mime_type ] = _wp_get_sources_from_meta( $new_size_meta );
+				wp_update_attachment_metadata( $attachment_id, $image_meta );
+			}
 		}
 	}
 
@@ -651,7 +711,6 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
 	 */
 	return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'create' );
 }
-
 /**
  * Convert a fraction string to a decimal.
  *
@@ -1143,3 +1202,78 @@ function _copy_image_file( $attachment_id ) {
 
 	return $dst_file;
 }
+
+/**
+ * Returns an array with the list of valid mime types that a specific mime type should be converted into.
+ * For example an `image/jpeg` should be converted into an `image/jpeg` and `image/webp`. The first type
+ * is considered the primary output type for this image.
+ *
+ * @since 6.0.0
+ *
+ * @param $attachment_id int The attachment ID.
+ * @return array<string, array<string>> An array of valid mime types, where the key is the source file mime type and the
+ *                                      value is one or more mime file types to generate.
+ */
+function wp_upload_image_mime_transforms( $attachment_id ) {
+	$image_mime_transforms = array(
+		'image/jpeg' => array( 'image/jpeg', 'image/webp' ),
+		'image/webp' => array( 'image/webp', 'image/jpeg' ),
+	);
+
+	/**
+	 * Filter to the output mime types for a given input mime type.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type
+	 *                                     and the value is one or more mime file types to generate.
+	 * @param int   $attachment_id         The ID of the attachment where the hook was dispatched.
+	 */
+	return (array) apply_filters( 'wp_upload_image_mime_transforms', $image_mime_transforms, $attachment_id );
+}
+
+/**
+ * Extract the primary and additional mime output types for an image from the $image_mime_transforms.
+ *
+ * @since 6.0.0
+ * @access private
+ *
+ * @param string $file          Full path to the image file.
+ * @param int    $attachment_id Attachment ID to process.
+ * @return array<string, array<string>> An array with the primary mime type and the additional mime types.
+ */
+function _wp_get_primary_and_additional_mime_types( $file, $attachment_id ) {
+	$image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id );
+	$original_mime_type    = wp_get_image_mime( $file );
+	$output_mime_types     = isset( $image_mime_transforms[ $original_mime_type ] ) ? $image_mime_transforms[ $original_mime_type ] : array( $original_mime_type );
+
+	// Exclude any output mime types that the system doesn't support.
+	$output_mime_types = array_filter(
+		$output_mime_types,
+		function( $mime_type ) {
+			return wp_image_editor_supports(
+				array(
+					'mime_type' => $mime_type,
+				)
+			);
+		}
+	);
+
+	// Use original mime type as primary mime type, or alternatively the first one.
+	$primary_mime_type_key = array_search( $original_mime_type, $output_mime_types, true );
+	if ( false === $primary_mime_type_key ) {
+		$primary_mime_type_key = 0;
+	}
+	// Split output mime types into primary mime type and additional mime types.
+	$additional_mime_types     = $output_mime_types;
+	list( $primary_mime_type ) = array_splice( $additional_mime_types, $primary_mime_type_key, 1 );
+
+	// Ensure $primary_mime_type is set.
+	if ( empty( $primary_mime_type ) ) {
+		$primary_mime_type = $original_mime_type;
+	}
+	return array_merge(
+		array( $primary_mime_type ),
+		$additional_mime_types
+	);
+}
diff --git src/wp-includes/class-wp-image-editor.php src/wp-includes/class-wp-image-editor.php
index 823501eb46..b85f558ec5 100644
--- src/wp-includes/class-wp-image-editor.php
+++ src/wp-includes/class-wp-image-editor.php
@@ -15,6 +15,7 @@ abstract class WP_Image_Editor {
 	protected $file              = null;
 	protected $size              = null;
 	protected $mime_type         = null;
+	protected $mime_type_set     = false;
 	protected $output_mime_type  = null;
 	protected $default_mime_type = 'image/jpeg';
 	protected $quality           = false;
@@ -336,11 +337,17 @@ abstract class WP_Image_Editor {
 			// If no file specified, grab editor's current extension and mime-type.
 			$file_ext  = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
 			$file_mime = $this->mime_type;
+			// Favor the file mime extension.
+			$ext = $this->get_extension( $file_mime );
+			if ( $this->mime_type_set && $ext !== $file_ext ) {
+				$new_ext = $ext;
+				$mime_type = $file_mime;
+			}
 		}
 
 		// Check to see if specified mime-type is the same as type implied by
 		// file extension. If so, prefer extension from file.
-		if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
+		if ( ! $this->mime_type_set && ( ! $mime_type || ( $file_mime == $mime_type ) ) ) {
 			$mime_type = $file_mime;
 			$new_ext   = $file_ext;
 		}
@@ -426,7 +433,7 @@ abstract class WP_Image_Editor {
 	 */
 	public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
 		// $suffix will be appended to the destination filename, just before the extension.
-		if ( ! $suffix ) {
+		if ( null === $suffix ) {
 			$suffix = $this->get_suffix();
 		}
 
@@ -627,5 +634,28 @@ abstract class WP_Image_Editor {
 
 		return wp_get_default_extension_for_mime_type( $mime_type );
 	}
-}
 
+	/**
+	 * Set the editor mime type, useful when outputting alternate mime types.
+	 *
+	 * Track that the mime type is set with the mime type set flag.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param string $mime_type The mime type to set.
+	 */
+	public function set_mime_type( $mime_type ) {
+		$this->mime_type     = $mime_type;
+		$this->mime_type_set = true;
+	}
+
+	/**
+	 * Reset the mime type to the original file mime type.
+	 *
+	 * Reset the mime type set flag.
+	 */
+	public function reset_mime_type() {
+		$this->mime_type     = wp_get_image_mime( $this->file );
+		$this->mime_type_set = false;
+	}
+}
diff --git src/wp-includes/media.php src/wp-includes/media.php
index a0e7ef9c6c..ab72f8fc8c 100644
--- src/wp-includes/media.php
+++ src/wp-includes/media.php
@@ -1843,6 +1843,11 @@ function wp_filter_content_tags( $content, $context = null ) {
 				$filtered_image = wp_img_tag_add_loading_attr( $filtered_image, $context );
 			}
 
+			// Use alternate mime types when specified and available.
+			if ( $attachment_id > 0 ) {
+				$filtered_image = wp_image_use_alternate_mime_types( $filtered_image, $context, $attachment_id );
+			}
+
 			if ( $filtered_image !== $match[0] ) {
 				$content = str_replace( $match[0], $filtered_image, $content );
 			}
@@ -1866,6 +1871,92 @@ function wp_filter_content_tags( $content, $context = null ) {
 	return $content;
 }
 
+/**
+ * Use alternate mime type images in the content output when available.
+ *
+ * @since 6.0.0
+ *
+ * @param string $image         The HTML `img` tag where the attribute should be added.
+ * @param string $context       Additional context to pass to the filters.
+ * @param int    $attachment_id The attachment ID.
+ * @return string Converted `img` tag with `loading` attribute added.
+ */
+function wp_image_use_alternate_mime_types( $image, $context, $attachment_id ) {
+	$metadata = wp_get_attachment_metadata( $attachment_id );
+	if ( empty( $metadata['file'] ) ) {
+		return $image;
+	}
+
+	// Only alter images with a `sources` attribute
+	if ( empty( $metadata['sources'] ) ) {
+		return $image;
+	};
+
+	$target_mimes = array( 'image/webp', 'image/jpeg' );
+
+	/**
+	 * Filter the content image mime type output selection and order.
+	 *
+	 * When outputting images in the content, the first mime type available will be used.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param array  $target_mimes  The image output mime type and order. Default is array( 'image/webp', 'image/jpeg' ).
+	 * @param int    $attachment_id The attachment ID.
+	 * @param string $context       Additional context to pass to the filters.
+	 * @return array The filtered output mime type and order. Return an empty array to skip mime type substitution.
+	 */
+	$target_mimes = apply_filters( 'wp_content_image_mimes', $target_mimes, $attachment_id, $context );
+
+	if ( false === $target_mimes ) {
+		return $image;
+	}
+
+	// Find the appropriate size for the provided URL in the first available mime type.
+	foreach ( $target_mimes as $target_mime ) {
+		if ( ! isset( $metadata['sources'][ $target_mime ] ) || empty( $metadata['sources'][ $target_mime ]['file'] ) ) {
+			continue;
+		}
+
+		// Go through each image and replace with the first available mime type version.
+		foreach ( $metadata['sizes'] as $name => $size_data ) {
+			// Check if size has a file.
+			if ( empty( $size_data['file'] ) ) {
+				continue;
+			}
+
+			// Check if size has a source in the desired mime type.
+			if ( empty( $size_data['sources'][ $target_mime ]['file'] ) ) {
+				continue;
+			}
+			$target_file = $size_data['sources'][ $target_mime ]['file'];
+
+			// Replace the existing output image for this size.
+			$src_filename = wp_basename( $size_data['file'] );
+
+			// This is the same as the file we want to replace nothing to do here.
+			if ( $target_file === $src_filename ) {
+				continue;
+			}
+
+			// Found a match, replace with the new filename and stop searching.
+			$image = str_replace( $src_filename, $size_data['sources'][ $target_mime ]['file'], $image );
+			continue;
+		}
+
+		// Handle full size image replacement.
+		$src_filename = wp_basename( $metadata['file'] );
+
+		// This is the same as the file we want to replace nothing else to do here.
+		if ( $metadata['sources'][ $target_mime ]['file'] === $src_filename ) {
+			return $image;
+		}
+
+		$image = str_replace( $src_filename, $metadata['sources'][ $target_mime ]['file'], $image );
+	}
+	return $image;
+}
+
 /**
  * Adds `loading` attribute to an `img` HTML tag.
  *
diff --git src/wp-includes/post.php src/wp-includes/post.php
index 3906e21f7c..4c1aa0327b 100644
--- src/wp-includes/post.php
+++ src/wp-includes/post.php
@@ -6480,6 +6480,21 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) {
 					$deleted = false;
 				}
 			}
+			// Check for alternate size mime types in the sizeinfo['sources'] array to delete.
+			if ( isset( $sizeinfo['sources'] ) && is_array( $sizeinfo['sources'] ) && count( $sizeinfo['sources'] ) > 1 ) {
+				$sources = $sizeinfo['sources'];
+				array_shift( $sources );
+				foreach ( $sources as $mime => $properties ) {
+					if ( ! is_array( $properties ) || empty( $properties['file'] ) ) {
+						continue;
+					}
+
+					$intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file );
+					if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
+						$deleted = false;
+					}
+				}
+			}
 		}
 	}
 
@@ -6499,6 +6514,22 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) {
 		}
 	}
 
+	// Check for alternate full size mime types in the root sources array to delete.
+	if ( isset( $meta['sources'] ) && is_array( $meta['sources'] ) ) {
+		$sources = $meta['sources'];
+		array_shift( $sources );
+		foreach ( $sources as $mime => $properties ) {
+			if ( ! is_array( $properties ) || empty( $properties['file'] ) ) {
+				continue;
+			}
+
+			$intermediate_file = str_replace( wp_basename( $file ), $properties['file'], $file );
+			if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
+				$deleted = false;
+			}
+		}
+	}
+
 	if ( is_array( $backup_sizes ) ) {
 		$del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
 
diff --git tests/phpunit/data/images/test-image.jpeg tests/phpunit/data/images/test-image.jpeg
new file mode 100644
index 0000000000..534aac1d6b
Binary files /dev/null and tests/phpunit/data/images/test-image.jpeg differ
diff --git tests/phpunit/tests/image/editor.php tests/phpunit/tests/image/editor.php
index 487dad0664..06d31e83f1 100644
--- tests/phpunit/tests/image/editor.php
+++ tests/phpunit/tests/image/editor.php
@@ -361,5 +361,411 @@ class Tests_Image_Editor extends WP_Image_UnitTestCase {
 			),
 		);
 	}
+	/**
+	 * Create the original image mime type when the image is uploaded
+	 *
+	 * @dataProvider provider_image_with_default_behaviors_during_upload
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_create_the_original_image_mime_type_when_the_image_is_uploaded( $file_location, $expected_mime, $targeted_mime ) {
+		$attachment_id = $this->factory->attachment->create_upload_object( $file_location );
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertIsArray( $metadata );
+		foreach ( $metadata['sizes'] as $size_name => $properties ) {
+			$this->assertArrayHasKey( 'sources', $properties );
+			$this->assertIsArray( $properties['sources'] );
+			$this->assertArrayHasKey( $expected_mime, $properties['sources'] );
+			$this->assertArrayHasKey( 'filesize', $properties['sources'][ $expected_mime ] );
+			$this->assertArrayHasKey( 'file', $properties['sources'][ $expected_mime ] );
+			$this->assertArrayHasKey( $targeted_mime, $properties['sources'] );
+			$this->assertArrayHasKey( 'filesize', $properties['sources'][ $targeted_mime ] );
+			$this->assertArrayHasKey( 'file', $properties['sources'][ $targeted_mime ] );
+		}
+	}
+
+	public function provider_image_with_default_behaviors_during_upload() {
+		yield 'JPEG image' => array(
+			DIR_TESTDATA . '/images/test-image.jpg',
+			'image/jpeg',
+			'image/webp',
+		);
+
+		yield 'WebP image' => array(
+			DIR_TESTDATA . '/images/webp-lossy.webp',
+			'image/webp',
+			'image/jpeg',
+		);
+	}
+
+	/**
+	 * Not create the sources property if no transform is provided
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_not_create_the_sources_property_if_no_transform_is_provided() {
+		add_filter( 'webp_uploads_supported_image_mime_transforms', '__return_empty_array' );
+
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertIsArray( $metadata );
+		foreach ( $metadata['sizes'] as $size_name => $properties ) {
+			$this->assertArrayNotHasKey( 'sources', $properties );
+		}
+	}
+
+	/**
+	 * Create the sources property when no transform is available
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_create_the_sources_property_when_no_transform_is_available() {
+		add_filter(
+			'webp_uploads_supported_image_mime_transforms',
+			function () {
+				return array( 'image/jpeg' => array() );
+			}
+		);
+
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertIsArray( $metadata );
+		foreach ( $metadata['sizes'] as $size_name => $properties ) {
+			$this->assertArrayHasKey( 'sources', $properties );
+			$this->assertIsArray( $properties['sources'] );
+			$this->assertArrayHasKey( 'image/jpeg', $properties['sources'] );
+			$this->assertArrayHasKey( 'filesize', $properties['sources']['image/jpeg'] );
+			$this->assertArrayHasKey( 'file', $properties['sources']['image/jpeg'] );
+			$this->assertArrayNotHasKey( 'image/webp', $properties['sources'] );
+		}
+	}
+
+	/**
+	 * Not create the sources property if the mime is not specified on the transforms images
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_not_create_the_sources_property_if_the_mime_is_not_specified_on_the_transforms_images() {
+		add_filter(
+			'webp_uploads_supported_image_mime_transforms',
+			function () {
+				return array( 'image/jpeg' => array() );
+			}
+		);
+
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/webp-lossy.webp'
+		);
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertIsArray( $metadata );
+		foreach ( $metadata['sizes'] as $size_name => $properties ) {
+			$this->assertArrayNotHasKey( 'sources', $properties );
+		}
+	}
+
+	/**
+	 * Create a WebP version with all the required properties
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_create_a_webp_version_with_all_the_required_properties() {
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+		$this->assertArrayHasKey( 'sources', $metadata['sizes']['thumbnail'] );
+		$this->assertArrayHasKey( 'image/jpeg', $metadata['sizes']['thumbnail']['sources'] );
+		$this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] );
+		$this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/jpeg'] );
+		$this->assertArrayHasKey( 'image/webp', $metadata['sizes']['thumbnail']['sources'] );
+		$this->assertArrayHasKey( 'filesize', $metadata['sizes']['thumbnail']['sources']['image/webp'] );
+		$this->assertArrayHasKey( 'file', $metadata['sizes']['thumbnail']['sources']['image/webp'] );
+		$this->assertStringEndsNotWith( '.jpeg', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] );
+		$this->assertStringEndsWith( '.webp', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] );
+	}
+
+	/**
+	 * Remove `scaled` suffix from the generated filename
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_remove_scaled_suffix_from_the_generated_filename() {
+		// The leafs image is 1080 pixels wide with this filter we ensure a -scaled version is created.
+		add_filter(
+			'big_image_size_threshold',
+			function () {
+				return 850;
+			}
+		);
+
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+		$metadata      = wp_get_attachment_metadata( $attachment_id );
+		$this->assertStringEndsWith( '-scaled.jpg', get_attached_file( $attachment_id ) );
+		$this->assertArrayHasKey( 'image/webp', $metadata['sizes']['medium']['sources'] );
+		$this->assertStringEndsNotWith( '-scaled.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] );
+		$this->assertStringEndsWith( '-300x200.webp', $metadata['sizes']['medium']['sources']['image/webp']['file'] );
+	}
+
+	/**
+	 * Remove the generated webp images when the attachment is deleted
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_remove_the_generated_webp_images_when_the_attachment_is_deleted() {
+		// Make sure no editor is available.
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$file    = get_attached_file( $attachment_id, true );
+		$dirname = pathinfo( $file, PATHINFO_DIRNAME );
+
+		$this->assertIsString( $file );
+		$this->assertFileExists( $file );
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+		$sizes    = array( 'thumbnail', 'medium' );
+
+		foreach ( $sizes as $size_name ) {
+			$this->assertArrayHasKey( 'image/webp', $metadata['sizes'][ $size_name ]['sources'] );
+			$this->assertArrayHasKey( 'file', $metadata['sizes'][ $size_name ]['sources']['image/webp'] );
+			$this->assertFileExists(
+				path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] )
+			);
+		}
+
+		wp_delete_attachment( $attachment_id );
+
+		foreach ( $sizes as $size_name ) {
+			$this->assertFileDoesNotExist(
+				path_join( $dirname, $metadata['sizes'][ $size_name ]['sources']['image/webp']['file'] )
+			);
+		}
+	}
+
+	/**
+	 * Remove the attached WebP version if the attachment is force deleted but empty trash day is not defined
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_remove_the_attached_webp_version_if_the_attachment_is_force_deleted_but_empty_trash_day_is_not_defined() {
+		// Make sure no editor is available.
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$file    = get_attached_file( $attachment_id, true );
+		$dirname = pathinfo( $file, PATHINFO_DIRNAME );
+
+		$this->assertIsString( $file );
+		$this->assertFileExists( $file );
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertFileExists(
+			path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
+		);
+
+		wp_delete_attachment( $attachment_id, true );
+
+		$this->assertFileDoesNotExist(
+			path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
+		);
+	}
+
+	/**
+	 * Remove the WebP version of the image if the image is force deleted and empty trash days is set to zero
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_remove_the_webp_version_of_the_image_if_the_image_is_force_deleted_and_empty_trash_days_is_set_to_zero() {
+		// Make sure no editor is available.
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$file    = get_attached_file( $attachment_id, true );
+		$dirname = pathinfo( $file, PATHINFO_DIRNAME );
+
+		$this->assertIsString( $file );
+		$this->assertFileExists( $file );
+
+		$metadata = wp_get_attachment_metadata( $attachment_id );
+
+		$this->assertFileExists(
+			path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
+		);
+
+		define( 'EMPTY_TRASH_DAYS', 0 );
+
+		wp_delete_attachment( $attachment_id, true );
+
+		$this->assertFileDoesNotExist(
+			path_join( $dirname, $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] )
+		);
+	}
+
+	/**
+	 * Avoid the change of URLs of images that are not part of the media library
+	 *
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_avoid_the_change_of_urls_of_images_that_are_not_part_of_the_media_library() {
+		$paragraph = '<p>Donec accumsan, sapien et <img src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>';
+
+		$this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) );
+	}
+
+	/**
+	 * Avoid replacing not existing attachment IDs
+	 *
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_avoid_replacing_not_existing_attachment_i_ds() {
+		$paragraph = '<p>Donec accumsan, sapien et <img class="wp-image-0" src="https://ia600200.us.archive.org/16/items/SPD-SLRSY-1867/hubblesite_2001_06.jpg">, id commodo nisi sapien et est. Mauris nisl odio, iaculis vitae pellentesque nec.</p>';
+
+		$this->assertSame( $paragraph, webp_uploads_update_image_references( $paragraph ) );
+	}
+
+	/**
+	 * Prevent replacing a WebP image
+	 *
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_prevent_replacing_a_webp_image() {
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/webp-lossy.webp'
+		);
+
+		$tag = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+
+		$this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+	}
+
+	/**
+	 * Prevent replacing a jpg image if the image does not have the target class name
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_prevent_replacing_a_jpg_image_if_the_image_does_not_have_the_target_class_name() {
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$tag = wp_get_attachment_image( $attachment_id, 'medium' );
+
+		$this->assertSame( $tag, webp_uploads_update_image_references( $tag ) );
+	}
+
+	/**
+	 * Replace the references to a JPG image to a WebP version
+	 *
+	 * @dataProvider provider_replace_images_with_different_extensions
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_replace_the_references_to_a_jpg_image_to_a_webp_version( $image_path ) {
+		$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
+
+		$tag          = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+		$expected_tag = $tag;
+		$metadata     = wp_get_attachment_metadata( $attachment_id );
+		foreach ( $metadata['sizes'] as $size => $properties ) {
+			$expected_tag = str_replace( $properties['sources']['image/jpeg']['file'], $properties['sources']['image/webp']['file'], $expected_tag );
+		}
+
+		$this->assertNotEmpty( $expected_tag );
+		$this->assertNotSame( $tag, $expected_tag );
+		$this->assertSame( $expected_tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+	}
+
+	public function provider_replace_images_with_different_extensions() {
+		yield 'An image with a .jpg extension' => array( DIR_TESTDATA . '/images/test-image.jpg' );
+		yield 'An image with a .jpeg extension' => array( DIR_TESTDATA . '/images/test-image.jpeg' );
+	}
+
+	/**
+	 * Contain the full image size from the original mime
+	 *
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_contain_the_full_image_size_from_the_original_mime() {
+		$attachment_id = $this->factory->attachment->create_upload_object(
+			DIR_TESTDATA . '/images/test-image.jpg'
+		);
+
+		$tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+
+		$expected = array(
+			'ext'  => 'jpg',
+			'type' => 'image/jpeg',
+		);
+		$this->assertSame( $expected, wp_check_filetype( get_attached_file( $attachment_id ) ) );
+		$this->assertContains( wp_basename( get_attached_file( $attachment_id ) ), webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+	}
+
+	/**
+	 * Prevent replacing an image with no available sources
+	 *
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_prevent_replacing_an_image_with_no_available_sources() {
+		add_filter( 'webp_uploads_supported_image_mime_transforms', '__return_empty_array' );
+
+		$attachment_id = $this->factory->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' );
+
+		$tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+		$this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+	}
+
+	/**
+	 * Prevent update not supported images with no available sources
+	 *
+	 * @dataProvider data_provider_not_supported_webp_images
+	 * @group webp_uploads_update_image_references
+	 *
+	 * @since 6.0.0
+	 */
+	public function it_should_prevent_update_not_supported_images_with_no_available_sources( $image_path ) {
+		$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
+
+		$this->assertIsNumeric( $attachment_id );
+		$tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+
+		$this->assertSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+	}
+
+	public function data_provider_not_supported_webp_images() {
+		yield 'PNG image' => array( DIR_TESTDATA . '/images/test-image.png' );
+		yield 'GIFT image' => array( DIR_TESTDATA . '/images/test-image.gif' );
+	}
+
+
 
 }
diff --git tests/phpunit/tests/image/functions.php tests/phpunit/tests/image/functions.php
index c02862b3e7..39bf09cf0c 100644
--- tests/phpunit/tests/image/functions.php
+++ tests/phpunit/tests/image/functions.php
@@ -480,7 +480,6 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 		$this->assertNotEmpty( $attachment_id );
 
 		$temp_dir = get_temp_dir();
-
 		$metadata = wp_generate_attachment_metadata( $attachment_id, $test_file );
 
 		$expected = array(
@@ -498,6 +497,13 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 300,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-232x300.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ),
+
+						),
+					),
 				),
 				'large'     => array(
 					'file'      => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
@@ -505,6 +511,12 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 1024,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
+						),
+					),
 				),
 				'thumbnail' => array(
 					'file'      => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
@@ -512,6 +524,12 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 150,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
+						),
+					),
 				),
 			),
 			'filesize' => wp_filesize( $test_file ),
@@ -557,7 +575,6 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 		$this->assertNotEmpty( $attachment_id );
 
 		$temp_dir = get_temp_dir();
-
 		$metadata = wp_generate_attachment_metadata( $attachment_id, $test_file );
 
 		$expected = array(
@@ -575,6 +592,12 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 300,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-300x300.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ),
+						),
+					),
 				),
 				'large'     => array(
 					'file'      => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
@@ -582,6 +605,13 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 1024,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-791x1024.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ),
+						),
+					),
+
 				),
 				'thumbnail' => array(
 					'file'      => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
@@ -589,6 +619,12 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 					'height'    => 150,
 					'mime-type' => 'image/jpeg',
 					'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
+					'sources'   => array(
+						'image/jpeg' => array(
+							'file'     => 'wordpress-gsoc-flyer-pdf-116x150.jpg',
+							'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ),
+						),
+					),
 				),
 			),
 			'filesize' => wp_filesize( $test_file ),
@@ -642,6 +678,12 @@ class Tests_Image_Functions extends WP_UnitTestCase {
 			'height'    => 100,
 			'mime-type' => 'image/jpeg',
 			'filesize'  => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ),
+			'sources'   => array(
+				'image/jpeg' => array(
+					'file'     => 'wordpress-gsoc-flyer-pdf-77x100.jpg',
+					'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ),
+				),
+			),
 		);
 
 		// Different environments produce slightly different filesize results.
diff --git tests/phpunit/tests/media.php tests/phpunit/tests/media.php
index 5d92d9718b..2e9e2173bc 100644
--- tests/phpunit/tests/media.php
+++ tests/phpunit/tests/media.php
@@ -2252,11 +2252,14 @@ EOF;
 		// Do not add width, height, and loading.
 		add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
 		add_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		$this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
 
 		remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
 		remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
+
 	}
 
 	/**
@@ -2288,9 +2291,12 @@ EOF;
 		$img = get_image_tag( self::$large_id, '', '', '', 'medium' );
 		$img = wp_img_tag_add_loading_attr( $img, 'test' );
 		$img = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $img );
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		// The content filter should return the image unchanged.
 		$this->assertSame( $img, wp_filter_content_tags( $img ) );
+
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 	}
 
 	/**
@@ -2343,6 +2349,7 @@ EOF;
 	 * @requires function imagejpeg
 	 */
 	public function test_wp_filter_content_tags_schemes() {
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 		$image_meta = wp_get_attachment_metadata( self::$large_id );
 		$size_array = $this->get_image_size_array_from_meta( $image_meta, 'medium' );
 
@@ -2387,6 +2394,7 @@ EOF;
 		$actual = wp_filter_content_tags( $unfiltered );
 
 		$this->assertSame( $expected, $actual );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 	}
 
 	/**
@@ -2804,6 +2812,8 @@ EOF;
 	 * @requires function imagejpeg
 	 */
 	public function test_wp_filter_content_tags_width_height() {
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
+
 		$image_meta = wp_get_attachment_metadata( self::$large_id );
 		$size_array = $this->get_image_size_array_from_meta( $image_meta, 'medium' );
 
@@ -2837,11 +2847,13 @@ EOF;
 		// Do not add loading, srcset, and sizes.
 		add_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
 		add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		$this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
 
 		remove_filter( 'wp_img_tag_add_loading_attr', '__return_false' );
 		remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 	}
 
 	/**
@@ -2895,11 +2907,13 @@ EOF;
 		// Do not add width, height, srcset, and sizes.
 		add_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
 		add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		$this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
 
 		remove_filter( 'wp_img_tag_add_width_and_height_attr', '__return_false' );
 		remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 	}
 
 	/**
@@ -2927,9 +2941,13 @@ EOF;
 		// Enable globally for all tags.
 		add_filter( 'wp_lazy_loading_enabled', '__return_true' );
 
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
+
 		$this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
 		remove_filter( 'wp_lazy_loading_enabled', '__return_true' );
 		remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
+
 	}
 
 	/**
@@ -2953,9 +2971,12 @@ EOF;
 		// Disable globally for all tags.
 		add_filter( 'wp_lazy_loading_enabled', '__return_false' );
 
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
+
 		$this->assertSame( $content, wp_filter_content_tags( $content ) );
 		remove_filter( 'wp_lazy_loading_enabled', '__return_false' );
 		remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 	}
 
 	/**
@@ -3381,6 +3402,7 @@ EOF;
 	 */
 	function test_wp_filter_content_tags_with_wp_get_loading_attr_default() {
 		global $wp_query, $wp_the_query;
+		add_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		$img1         = get_image_tag( self::$large_id, '', '', '', 'large' );
 		$iframe1      = '<iframe src="https://www.example.com" width="640" height="360"></iframe>';
@@ -3415,6 +3437,7 @@ EOF;
 			$content_filtered = wp_filter_content_tags( $content_unfiltered, 'the_content' );
 			remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
 		}
+		remove_filter( 'wp_content_image_mimes', '__return_empty_array' );
 
 		// After filtering, the first image should not be lazy-loaded while the other ones should be.
 		$this->assertSame( $content_expected, $content_filtered );
