Я должен сказать, что я мало знаю о том, как работают форматы файлов.
Мой вопрос в том, что у меня есть файл jpeg, который равен 200 px на 200 px, как можно вычислить, какой максимальный размер этого файла может быть в мегабайтах/байтах?
Я думаю, что аргументация, которая привела к вопросу, поможет мне ответить. У меня есть Java-апплет, который загружает изображения, которые люди рисуют с ним на моем сервере. Мне нужно знать, какой максимальный размер может достичь этот файл. Он всегда будет 200x200.
Звучит глупо, но есть ли цвета, которые занимают больше байтов, чем другие, и если да, то что является самым дорогим?
Ответ 2
Существует много способов сделать "патологический" JPEG/JFIF файл необычно большим.
В крайнем конце спектра нет предела размеру, поскольку стандарт не ограничивает некоторые типы маркеров, появляющихся более одного раза - например, файл JFIF, заполненный множеством GB DRI (определить интервал перезапуска), а затем MCU 8x8 пикселей в конце технически обоснован.
Если мы ограничимся "нормальным" использованием маркера, мы найдем верхний предел следующим образом:
Некоторые фон -
-
JPEG кодирует пиксели в виде MCU (группы) блоков 8x8 пикселей (блоки DCT), один блок DCT для каждого компонента (Y, Cb, Cr).
-
Чтобы получить наилучшее сжатие (и наименьший размер), используется схема выборочной обработки цветности 4: 2: 0, когда 75% информации о цветности опущено. Чтобы получить лучшее качество (и самый большой размер), файл имеет 2/3-х цветов, 1/3-мерную информацию яркости.
-
Символы битового потока Huffman используются для кодирования DCT-компонентов, из которых до 65 на блок DCT (64 AC + 1 DC).
-
Символы Хаффмана могут варьироваться от 1 до 16 бит и выбираются кодировщиком как можно меньше; Тем не менее, можно указать длину символа.
-
Конечная кодировка потока данных huffman должна быть выполнена так, чтобы маркеры могли быть идентифицированы однозначно. I.e, любое появление байта 0xff на выходе должно быть заменено двумя байтами - 0xff, 0x00.
Используя всю эту информацию, мы можем построить патологический, но действительный файл JPEG, который libjpeg (наиболее распространенная реализация декодера JPEG) рад декодировать.
Во-первых, нам нужны самые длинные символы хаффмана. Сначала мысль, определяющая символ хаффмана максимальной длины (16 бит) всех 1, будет использовать большинство пробелов, однако libjpeg отказывается обрабатывать символ Хаффмана, который является всего 1, это, похоже, не исключает стандарт - как он по-прежнему является уникальным символом, поскольку размер уже известен как 16 бит, в отличие от других символов переменной длины, и даже некоторые декодеры могут обрабатывать его (JPEGSnoop).
Итак, мы определяем таблицу huffman, которая устанавливает последние два символа следующим образом:
11111111_1111110 -> (0,0) (EOB - end of block value)
11111111_11111110 -> (0,15)
Такая таблица huffman появится в файле JPEG как:
0xFF, 0xC4 ; DHT - define huffman table
0x00, 35 ; length
0x00 ; DC 0
1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1, 1, 1 ; histogram
1,2,3,4,5,6,7,8,9,10,11,12,13,14,0,15 ; symbols
Теперь для кодирования блока DCT максимальной длины:
1 x DC of 31 bits ( 11111111 11111110 11111111 1111111 )
64 x AC of 31 bits ( 11111111 11111110 11111111 1111111 )
= 2015 bits
Поскольку MCU будет 3 DCT-блоками (по одному для каждого компонента), размер MCU будет
6045 бит.
Большинство из этих байтов будет 0xff, которые заменяются 0xff, 0x00 в выходном потоке, в соответствии со стандартом, чтобы отличать поток битов от допустимых маркеров.
Выполните это сопоставление, и полный DCT представлен 8 повторами следующего шаблона байта:
0xff,0x00,0xfe,0xff,0x00,0xff,0x00
0xff,0x00,0xfd,0xff,0x00,0xff,0x00
0xff,0x00,0xfb,0xff,0x00,0xff,0x00
0xff,0x00,0xf7,0xff,0x00,0xff,0x00
0xff,0x00,0xef,0xff,0x00,0xff,0x00
0xff,0x00,0xdf,0xff,0x00,0xff,0x00
0xff,0x00,0xbf,0xff,0x00,0xff,0x00
0xff,0x00,0x7f,0xff,0x00
который составляет 8 * 54 = 432 байта
Добавив все это, мы имеем:
3 компонента * (432 байта на компонент)
= 1296 байт на 8x8 пикселей
для сегментов SOI/DHT/DQT/SOS для заголовков SOI/DHT/DQT/SOS требуется заголовок в 339 байт, для завершения изображения изображения и таблиц huffman требуется 2-байтовый маркер EOI.
Поскольку образ 200x200 будет 25x25 MCU, мы имеем конечный размер:
339 + (25 * 25 * 1296) + 2
= 810341 байт
который работает как чуть более 20,25 байт на пиксель, в 6 раз больше, чем несжатый BMP/TGA.