private function timber_generate_sizes( $attachment_id ) {
		$sizes      = [];
		$img_sizes  = Helper::get_image_sizes();
		$attachment = get_post( $attachment_id );

		/**
		 * Never automatically generate image sizes on upload for SVG and GIF images.
		 * SVG and GIF images will still be resized when requested on the fly.
		 */
		if ( in_array( $attachment->post_mime_type, array(
			'image/svg+xml',
			'image/gif',
		), true ) ) {
			return $sizes;
		}

		// Timber needs the file src as an URL
		$file_src  = wp_get_attachment_url( $attachment_id );
		$meta_data = wp_get_attachment_metadata( $attachment_id );

		/**
		 * Delete all existing image sizes for that file.
		 *
		 * This way, when Regenerate Thumbnails will be used, all non-registered image sizes will be
		 * deleted as well. Because Timber creates image sizes when they’re needed, we can safely do
		 * this.
		 */
		Timber\ImageHelper::delete_generated_files( $file_src );

		foreach ( $img_sizes as $key => $img_size ) {
			if ( ! $this->timber_should_resize( $attachment->post_parent, $img_size ) ) {
				continue;
			}

			// Create downsized version of the image
			$downsized = image_downsize( $attachment_id, $key );

			// Bail out if there was an error while downsizing the image.
			if ( ! is_array( $downsized ) ) {
				continue;
			}

			list( $file_src, $file_width, $file_height ) = $downsized;

			/**
			 * Create an image definition array that will be used for attachment metadata.
			 *
			 * WordPress saves an array with the file src, the width, the height and the mime type
			 * of an attachment in the postmeta database table. By generating this array and saving
			 * it in the database, we can improve the compatibility with the core image
			 * functionality.
			 *
			 * Correct width and height values of '0' by calculating them from the original image
			 * ratio, if meta data is available.
			 */
			if ( ! empty( $meta_data['height'] ) && ! empty( $meta_data['width'] ) ) {
				if ( 0 === (int) $file_width && ! empty( $meta_data['height'] ) ) {
					$file_width = round( $file_height / $meta_data['height'] * $meta_data['width'] );
				} elseif ( 0 === (int) $file_height ) {
					$file_height = round( $file_width / $meta_data['width'] * $meta_data['height'] );
				}
			}

			if ( is_numeric( $file_width ) && is_numeric( $file_height ) ) {
				$sizes[ $key ] = [
					'file'      => wp_basename( $file_src ),
					'width'     => $file_width,
					'height'    => $file_height,
					'mime-type' => wp_check_filetype( $file_src )['type'],
				];
			}

			/**
			 * Filters whether srcset sizes should be generated when an image is uploaded.
			 *
			 * @since 0.13.0
			 *
			 * @param bool     $generate_srcset_sizes Whether to generate srcset sizes. Passing false will prevent
			 *                                        srcset sizes to generated when an image is uploaded. Default false.
			 * @param string   $key                   The image size key.
			 * @param array    $img_size              The image size configuration array.
			 * @param \WP_Post $attachment            The attachment post.
			 */
			$generate_srcset_sizes = apply_filters( 'timmy/generate_srcset_sizes', false, $key, $img_size, $attachment );

			// Get setting from image configuration.
			$generate_srcset_sizes = isset( $img_size['generate_srcset_sizes'] )
				? $img_size['generate_srcset_sizes']
				: $generate_srcset_sizes;

			if ( false === $generate_srcset_sizes ) {
				continue;
			}

			// Get values for the default image
			$crop  = Helper::get_crop_for_size( $img_size );
			$force = Helper::get_force_for_size( $img_size );

			// Generate additional image sizes used for srcset
			if ( isset( $img_size['srcset'] ) ) {
				foreach ( $img_size['srcset'] as $srcset_size ) {
					list( $width, $height ) = Helper::get_dimensions_for_srcset_size( $img_size['resize'], $srcset_size );

					// For the new source, we use the same $crop and $force values as the default image
					self::resize( $img_size, $file_src, $width, $height, $crop, $force );
				}
			}
		}

		return $sizes;
	}