Суффикс «-rotated» у картинки, или что WP делает с ориентаций изображения

С версии WordPress 5.3 при загрузке картинок, ВП проверяет метаданные ориентации картинки. Если в метаданных указано, что у картинки ориентация отличается от стандартной (стандартно индекс ориентации должен быть равен единице - 1 или просто не должен быть указан), то ВП изменяет ориентацию оригинала так, чтобы в итоге получилась базовая ориентация.

Для изменения ориентации ВП, перед созданием промежуточных размеров, поворачивает картинку опираясь на мета-данные об ориентации и сохраняет результат с суффиксом -rotated.

Новая «-rotated» картинка, теперь считается оригинальной картинкой и путь до неё записан в метаполе _wp_attached_file. И теперь функция, которая обычно возвращает оригинальный путь get_attached_file() или оригинальный URL wp_get_attachment_url() и другие функции, которые должны вернуть оригинальную картинку, будут возвращать новый -rotated путь/URL.

Файл исходной картинки не удаляется и находится в папке uploads. Метка о том что есть оригинал, добавляется в метаданные вложения ВП, в ключ массива: original_image. Путь или URL к исходнику можно получить через функции:

Рассмотрим на примере:

Допустим мы загрузили картинку Landscape_2.jpg у которой в exif данных указано [Orientation] => 2. Тогда ВП создаст еще один файл Landscape_2-rotated.jpg, положит его рядом с оригиналом в папку uploads и сделает его основным файлом, а имя оригинального файла добавит в метаданные

'original_image' => 'Landscape_2.jpg',

Данные из таблицы wp_postmeta:

+---------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| post_id | meta_key                | meta_value                                                                                                                                             |
+---------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1863    | _wp_attached_file       | 2022/06/Landscape_2-rotated.jpg                                                                                                                        |
| 1863    | _wp_attachment_metadata | a:7:{s:5:"width";i:1800;s:6:"height";i:1200;s:4:"file";s:31:"2022/06/Landscape_2-rotated.jpg";s:8:"filesize";i:400881;s:5:"sizes";a:6:{s:6:"medium";a: |
|         |                         | 5:{s:4:"file";s:23:"Landscape_2-300x200.jpg";s:5:"width";i:300;s:6:"height";i:200;s:9:"mime-type";s:10:"image/jpeg";s:8:"filesize";i:14295;}s:5:"large |
|         |                         | ";a:5:{s:4:"file";s:24:"Landscape_2-1024x683.jpg";s:5:"width";i:1024;s:6:"height";i:683;s:9:"mime-type";s:10:"image/jpeg";s:8:"filesize";i:130033;}s:9 |
|         |                         | :"thumbnail";a:5:{s:4:"file";s:23:"Landscape_2-150x150.jpg";s:5:"width";i:150;s:6:"height";i:150;s:9:"mime-type";s:10:"image/jpeg";s:8:"filesize";i:60 |
|         |                         | 50;}s:12:"medium_large";a:5:{s:4:"file";s:23:"Landscape_2-768x512.jpg";s:5:"width";i:768;s:6:"height";i:512;s:9:"mime-type";s:10:"image/jpeg";s:8:"fil |
|         |                         | esize";i:75295;}s:9:"1536x1536";a:5:{s:4:"file";s:25:"Landscape_2-1536x1024.jpg";s:5:"width";i:1536;s:6:"height";i:1024;s:9:"mime-type";s:10:"image/jp |
|         |                         | eg";s:8:"filesize";i:283925;}s:14:"post-thumbnail";a:5:{s:4:"file";s:25:"Landscape_2-1568x1045.jpg";s:5:"width";i:1568;s:6:"height";i:1045;s:9:"mime-t |
|         |                         | ype";s:10:"image/jpeg";s:8:"filesize";i:295929;}}s:10:"image_meta";a:12:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption"; |
|         |                         | s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title"; |
|         |                         | s:0:"";s:11:"orientation";i:1;s:8:"keywords";a:0:{}}s:14:"original_image";s:15:"Landscape_2.jpg";}                                                     |
| 1863    | _edit_lock              | 1656265849:1                                                                                                                                           |
+---------+-------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+

Массив: _wp_attachment_metadata:

[
	'width' => 1800,
	'height' => 1200,
	'file' => '2022/06/Landscape_2-rotated.jpg',
	'filesize' => 400881,
	'sizes' =>
		[
			'medium'         =>
				[
					'file'      => 'Landscape_2-300x200.jpg',
					'width'     => 300,
					'height'    => 200,
					'mime-type' => 'image/jpeg',
					'filesize'  => 14295,
				],
			'large'          =>
				[
					'file'      => 'Landscape_2-1024x683.jpg',
					'width'     => 1024,
					'height'    => 683,
					'mime-type' => 'image/jpeg',
					'filesize'  => 130033,
				],
			'thumbnail'      =>
				[
					'file'      => 'Landscape_2-150x150.jpg',
					'width'     => 150,
					'height'    => 150,
					'mime-type' => 'image/jpeg',
					'filesize'  => 6050,
				],
			'medium_large'   =>
				[
					'file'      => 'Landscape_2-768x512.jpg',
					'width'     => 768,
					'height'    => 512,
					'mime-type' => 'image/jpeg',
					'filesize'  => 75295,
				],
			'1536x1536'      =>
				[
					'file'      => 'Landscape_2-1536x1024.jpg',
					'width'     => 1536,
					'height'    => 1024,
					'mime-type' => 'image/jpeg',
					'filesize'  => 283925,
				],
			'post-thumbnail' =>
				[
					'file'      => 'Landscape_2-1568x1045.jpg',
					'width'     => 1568,
					'height'    => 1045,
					'mime-type' => 'image/jpeg',
					'filesize'  => 295929,
				],
		],
	'image_meta' =>
		[
			'aperture'          => '0',
			'credit'            => '',
			'camera'            => '',
			'caption'           => '',
			'created_timestamp' => '0',
			'copyright'         => '',
			'focal_length'      => '0',
			'iso'               => '0',
			'shutter_speed'     => '0',
			'title'             => '',
			'orientation'       => 1,
			'keywords'          =>
				[
				],
		],
	'original_image' => 'Landscape_2.jpg',
]

WP не всегда правильно изменяет ориентацию картинки, чтобы все работало правильно есть мини-плагин https://github.com/gagan0123/fix-image-rotation Этот плагин пожалуй я бы рекомендовал к установке на все сайты, особенно если на сайте много картинок, который загружаются с телефонов.

Общая информация об ориентации картинок

При просмотре изображения, браузер или любой другой вьювер считывает Exif мета-данные картинки об ориентации (Orientation) и автоматически поварачивает картинку так как указано в данных, чтобы мы всегда видели картинку правильно, даже если оригинальный файл например, перевернут.

Например. Мы сделали фото с телефона, телефон сохранил картинку в перевернутом виде (видимо чтобы не делать лишних операций), и добавил в метаданные метку об орриентации, например Orientation=3. Теперь при просмотре картинки, допустим, в браузере, браузер прочитает эту информацию и прежде чем её отобразить повернет картинку как нужно. В результате мы видим нормальную картинку, ничего не подозревая о том что в действительности картинка записанная на диске, например, в перевернутом виде.

Флаг ориентации Exif (мета-информация об ориентации)

Когда мы делаем фотографии с помощью камеры, мы не всегда держим камеру так, чтобы верх камеры соответствовал верху сцены.

Иллюстрация идеи поворота камеры

Неважно, как вы держите камеру, когда вы просматриваете изображение на компьютере, изображение отображается в правильной ориентации. Это связано с флагом ориентации Exif. Если вы держите камеру не в вертикальном положении, исходная фотография, которую вы делаете, хранится в виде повернутого изображения. Цифровое устройство (будь то смартфон или цифровая камера) имеет датчик для записи ориентации камеры и записывает эту информацию в флаг ориентации в Exif.

Флаг ориентации Exif может иметь девять различных значений от 1 до 9.

8 значений для Exif параметра ориентации

Для цифровых фотографий обычно используются только флаги: 1, 8, 3, 6. Флаги 2, 7, 4, 5 представляют зеркальные и повернутые версии изображений.

Зачем это нужно WP?

Базовая ориентация важна при создании миниатюр изображения. Чтобы не нужно было проверять еще и ориентацию сходного файла, а можно было просто работать с исходником в стандартном виде.

Например, если создавать миниатюру из исходника, который имеет нестандартную ориентацию, например перевернут, то и миниатюра получится перевернутая. В этом случае чтобы миниатюра получилась нормальной, нужно указать ей EXIF данные об ориентации или заранее поправить оригинал и только потом создать миниатюру.

Чтобы не обрабатывать отдельно нестандартную ориентацию WP приводит оригинальную картинку к стандартному виду, чтобы затем работать с ней как обычно.

Как Отключить функцию преобразования ориентации в WP?

Для этого можно использовать фильтр wp_image_maybe_exif_rotate - вставьте его в functions.php темы:

add_action( 'wp_image_maybe_exif_rotate', '__return_false' );

Совсем отключать эту функцию я бы не рекомендовал. Потому что это полезная фитча. Однако, чтобы не создавался дубль в виде оставленной исходной картинки, рекомендую установить мини-плагин: https://wordpress.org/plugins/fix-image-rotation/ Он поправляет некоторые баги преобразования самого WP, а также заменяет оригинальную картинку на новую (с базовой ориентацией). Таким образом не создается новый файл с суффиксом -rotated, а просто изменяется оригинал.

Как это работает:

При создании картинки срабатывает следующая цепочка функций:

  • media_handle_upload()

    • wp_generate_attachment_metadata()

      • wp_create_image_subsizes()

        • wp_get_image_editor()

          // проверяется ориентация и исправляется если нужно
          $editor = wp_get_image_editor( $file );
          $rotated = $editor->maybe_exif_rotate();
          
          if ( true === $rotated ) {
          	$saved = $editor->save( $editor->generate_filename( 'rotated' ) );
          	$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
          }
          
          wp_update_attachment_metadata( $attachment_id, $image_meta );
          
          // создаются промежуточные размеры
          _wp_make_subsizes();

--