Обновление эскиза JFIF в файле JPEG
Я пытаюсь обновить встроенный эскиз JFIF в файле JPEG с помощью Python.
Это (немного хакерский) метод, который должен достичь этого:
def set_thumbnail(self, data):
# Data of the updated thumbnail
data = bytearray(data)
# Get offset of the old thumbnail data
offset = (self._exif_start +
self._unpack('I', self._get_tag_offset(0x201)+8))
# Get size of the old thumbnail
old_size = self._unpack('I', self._get_tag_offset(0x202)+8)
try:
# Strip everything between the JFIF APP1 and the quant table
jfif_start = data.index('\xff\xe0')
quant_start = data.index('\xff\xdb')
stripped_data = data[0:jfif_start] + data[quant_start:]
except ValueError:
stripped_data = data
# Writes the new length to the buffer
self._pack('I', self._get_tag_offset(0x202)+8, len(stripped_data))
# Writes the new data to the image buffer
self._buf[offset:offset+old_size] = stripped_data
Эта функция прекрасно работает, когда я переписываю старый эскиз, то есть размер данных миниатюры не изменяется. Однако после того, как я применил к нему какое-либо преобразование (например, обрезать или повернуть) и снова его сохранить, результирующий файл больше не является действительным.
Я загрузил исходное изображение и обновленное изображение для лучшего сравнения.
Ошибка, которую я получаю, например, identify
является следующим:
identify.im6: Invalid JPEG file structure: two SOI markers `/tmp/thumb_rotated.jpg' @ error/jpeg.c/JPEGErrorHandler/316.
Различая два изображения, значение в 0x202
Тег размера соответствует размеру встроенных миниатюрных данных, и файл также соответственно больше.
2 ответа
Я только что нашел ответ:
Проблема заключалась в том, что, хотя я обновил размер миниатюры в теге TIFF, я не обновил длину APP1. Как только это было обновлено, изображение загружено правильно.
Это структура вашего файла изображения. Обратите внимание, что после маркера APP1 есть второй маркер SOI.
{Начало изображения}
{APP0 Длина маркера: 16 Версия: 1.1 Единица плотности: (пикселей на дюйм) Плотность X: 72 Плотность: 72 Ширина миниатюры: 0 Высота миниатюры: 0}
{APP1 длина маркера: 7678 Exif}
{Начало изображения}
{Определить длину таблицы квантования: 67 Указатель таблицы: 0 Точность таблицы: 0 Значения таблицы: 8 6 6 7 6 5 8 7 7 7 9 9 8 10 12 20 13 12 11 11 12 25 18 19 15 20 29 26 31 30 29 26 28 28 32 36 46 39 32 34 44 35 28 28 40 55 41 44 48 49 52 52 52 31 39 57 61 56 50 60 46 51 52 50}
{Определить длину таблицы квантования: 67 Указатель таблицы: 1 Точность таблицы: 0 Значения таблицы: 9 9 9 12 11 12 24 13 13 24 50 33 28 33 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50}
{Начало Тип кадра: Базовая линия (Хаффман) Длина: 17 Точность: 8 Высота: 360 Ширина: 480 Количество компонентов: 3 Компонент 1 Частота по горизонтали: 2 Частота по вертикали: 2 Таблица квантования: 0 Компонент 2 Частота по горизонтали: 1 Частота по вертикали: 1 Таблица квантования: 1 компонент 3 Частота горизонтальной развертки: 1 Частота вертикальной развертки: 1 Таблица квантования: 1}
{Определить длину таблицы Хаффмана: 28 Индекс таблицы 0 Класс таблицы: число кодов DC: 0 1 5 1 1 1 0 0 0 0 0 0 0 0 0 0 Значения кода: 3 1 2 4 5 6 0 7 8}
{Определить длину таблицы Хаффмана: 65 Таблица указателей 0 Класс таблицы: счетчик кодов AC: 0 2 1 3 2 4 4 4 4 4 5 3 3 4 3 0 Значения кода: 1 2 3 0 4 11 12 21 5 31 41 51 13 22 61 71 6 32 81 91 14 42 a1 b1 23 52 c1 d1 7 15 33 62 e1 43 72 f0 24 92 f1 16 34 53 82 25 83 c2}
{Определить длину таблицы Хаффмана: 26 Таблица указателей 1 Класс таблицы: счетчик кодов DC: 0 3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 Значения кода: 0 1 2 3 4 5 6}
{Определить длину таблицы Хаффмана: 45 Таблица указателей 1 Класс таблицы: счетчик кодов AC: 0 2 2 1 4 1 4 2 2 2 1 5 0 0 0 0 Значения кода: 0 1 2 11 3 4 12 21 31 41 13 22 51 61 32 71 5 14 23 91 f0 33 42 81 a1 b1}
{Начало сканирования Длина: 12 ID компонента: 1 Таблица энтропии переменного тока: 0 Таблица энтропии постоянного тока: 0 ID компонента: 2 Таблица энтропии переменного тока: 1 Таблица энтропии постоянного тока: 1 ID компонента: 3 Таблица энтропии переменного тока: 1 Таблица энтропии постоянного тока: 1 Спектральный Начало выбора: 0 Конец выбора спектра: 63 Высокий уровень успешного приближения: 0 Низкий уровень достаточного приближения: 0}
{Конец изображения}