Создать изображение большого пальца JPEG с общим фиксированным заголовком - PullRequest
6 голосов
/ 21 мая 2019

Я хочу создать превью для моих фотографий, например Предварительный просмотр на Facebook . Мой план:

  • Отправитель : создать масштабированный большой палец (с максимальным размером 30 пикселей) из исходной фотографии, вырезать весь фиксированный заголовок для отправки.
  • Receiver : из байтового массива "minified" добавить с фиксированным заголовком (жесткий код в коде клиента). Затем преобразуйте его в Bitmap для отображения.

Наконец-то я придумаю базу решений на Q42.ImagePreview .

Я разделил эти части как фиксированный заголовок:

  • Начало изображения (0xFFD8)
  • App0 (начать с 0xFFE0)
  • Определить таблицы (ы) квантования
  • Определить таблицы Хаффмана

Динамические части:

  • Начало кадра (начинается с 0xFFC0): потому что оно содержит байты ширины / высоты.
  • Начало сканирования (начало с 0xFFDA).
  • Сжатые данные изображения.
  • Конец изображения (0xFFD9)

Но он работает только на 1 из моих устройств и не работает на других.

Итак, как создать фиксированный, общий и стандартный заголовок JPEG , который можно использовать на устройствах Android и iOS?

Спасибо.


Подробнее:

Создание минимизированного потока данных:

  • Создание масштабированного растрового изображения из исходного изображения (максимальный размер 30 пикселей, сохранить соотношение сторон) с использованием BitmapFactory & Matrix

  • Сжатие масштабированного растрового изображения с качеством 64 с использованием Bitmap#compress() и сохранение в byte[] thumbData.

  • Подмассив thumbData выше от 0xFFDA до конца. (SOS, данные изображения и EOI) и сохранить в byte[] body.

  • Добавьте 4 байта, представляющих ширину и высоту body, преобразуйте в строку Base64 и отправьте.

В устройстве, работающем нормально, размер thumbData длиннее, чем в других устройствах, которые не работают. И различие в таблицах (таблицах) Хаффмана, SOS и изображениях, смотрите это: Проверка различий между двумя фотографиями

Ответы [ 2 ]

3 голосов
/ 31 мая 2019

Боюсь, вы не можете сделать это, используя встроенный метод каждой платформы. Проблема в фазе сжатия.

В сжатии JPEG имеется ряд переменных, включая тип и разбивку сканов, выборок, выбор DHT и выбор DQT. Если какой-либо из них отличается в используемом вами кодере, вы получите другой вывод .Это природа зверя.

Например: Таблица определения Хаффмана (DHT) определяет способ сжатия «данных изображения» (после сегмента SoS).И вы используете фиксированные таблицы Хаффмана только для декодирования , вот что вызвало проблему.


Таким образом, вы можете выбрать несколько вариантов:

  • Отправитьизображение высокого качества (без сжатия) после уменьшения до максимального размера 30px в качестве предварительного просмотра большого пальца.
  • Напишите собственный алгоритм сжатия или используйте кросс-платформенную библиотеку.
  • Загрузить весь оригинализображение на ваш сервер для обработки и отправки "минимизированных данных" на Android / iOS.

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

При получении на мобильном устройстве они декодируют «минимизированные данные» в растровое изображение, добавляя его с «фиксированным заголовком» ( Bitmaps.java # L111 ) и обновляя размер изображения в сегменте SoF.См. ImageLoader.java # L750 .

1 голос
/ 08 июня 2019

Точка 1:

"Если я не разделю фиксированный заголовок и не отправлю изображение максимум 30x30 с качеством 64 (также используя bitmap.compress()), он все еще отлично работает на обеих платформах (и размер составляет всего 1-2 Кб).

Но я хочу even smaller, поэтому мне нужно разделить DQT & DHT на фиксированный заголовок"

  • Создание изображения 30x30 (растровое изображение)
  • Сжатие растрового изображения в JPEG
  • Удаление DQT и DHT (необязательный шаг для еще меньшего размерабайт, но удаление может вызвать проблему)
  • Сжать оставшиеся данные JPEG с помощью алгоритма Deflate (в основном архивирование данных перед отправкой)

Точка 2:

Эти два изображения имеют размер 30x30 и используют одинаковые таблицы Хаффмана и таблицы квантования.

image image1
https://www.dropbox.com/s/qzptp9mmrhxxsq3/30x30_thumb_01.jpg?dl=1

image image2
https://www.dropbox.com/s/yrvsybb564mw2vv/30x30_thumb_02.jpg?dl=1

Проверьте, нормально ли они отображаются дляВы на iPhone и Android.Если да, то попробуйте эти таблицы DQT и DHT, представленные ниже, в ваших собственных файлах JPEG.

Таблицы: (общий размер = 570 байт) ...

Определение таблицы квантования (общий размер = 138 байт): существует двакаждый начинается с байтов FF DB:

FF DB 00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27 39 3D 38 32 3C 2E 33 34 32

FF DB 00 43 01 09 09 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32

Определение таблицы Хаффмана (общий размер = 432 байта): Их четыре, каждый начинается с байтов FF C4:

FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B

FF C4 00 B5 10 00 02 01 03 03 02 04 03 05 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12 21 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23 42 B1 C1 15 52 D1 F0 24 33 62 72 82 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA

FF C4 00 1F 01 00 03 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B

FF C4 00 B5 11 00 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77 00 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9 FA

Точка 3:

"Итак, как создать фиксированный, общий и стандартный заголовок JPEG, который можно использовать на устройствах Android и iOS?"

Попробуйте:

(1) Эти начальные байты одинаковы для изображений размером выше 30x30:

FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 60 00 60 00 00 FF DB 00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 FF C0 00 11 08 00 1E 00 1E 03 01 22 00 02 11 01 03 11 01 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03 05 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12 21 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23 42 B1 C1 15 52 D1 F0 24 33 62 72 82 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FF C4 00 1F 01 00 03 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 11 00 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77 00 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9 FA

(2) После вышепоследние четыре байта заголовка F7 F8 F9 FA идут с маркером начала сканирования (FF DA) с 14 байтами:

FF DA 00 0C 03 01 00 02 11 03 11 00 3F 00

(3) Теперь добавьте данные сканирования JPEG до конечных FF D9 байтов.

В основном в вашем .compress() выходном JPEG, Удалить все байты от FF D8 до to FF DA + 12 more following bytes.Таким образом, вы удалили заголовки и таблицы DHT / DQT.Отправьте эти меньшие данные, и на принимающей стороне ваше приложение просто помещает байты заголовка из шагов (1) и шага (2) в некоторый массив, а затем добавляет полученные байты после заголовка.

Попробуйте теперь загрузить повторнос фиксированным форматом JPEG.
(ваш массив должен быть полными данными JPEG с байтами, начинающимися с FF D8 и заканчивающимися FF D9).

...