Каков наименьший допустимый размер файла jpeg (в байтах)

Я хотел бы проверить некоторые jpeg-файлы на достоверность, прежде чем отправлять их по сети для более тщательной проверки. Достаточно легко проверить правильность верхнего и нижнего колонтитула, но каков наименьший размер (в байтах) допустимого jpeg?


person twk    schedule 12.02.2010    source источник
comment
libjpeg может выполнять быстрые тесты, попробуйте использовать его, а не гадать.   -  person Tronic    schedule 12.02.2010
comment
Я не хочу добавлять дополнительные библиотеки в свое приложение. Кроме того, он не угадывает, если кто-то скажет мне правильный ответ :)   -  person twk    schedule 12.02.2010
comment
Вероятно, вам следует изменить свой вопрос, чтобы проверить, допустимы ли некоторые jpeg, если только вы не собираетесь проводить множество других тестов, если тест на размер файла пройден. В противном случае довольно легко создать недействительный JPEG любого размера, превышающего минимальный размер допустимого JPEG.   -  person jball    schedule 12.02.2010
comment
@jball, хорошая идея - я прояснил вопрос.   -  person twk    schedule 12.02.2010


Ответы (7)


Серый пиксель 1x1 в 125 байтах с использованием арифметического кодирования, все еще в стандарте JPEG, даже если большинство декодеров не могут его декодировать:

ff d8 : SOI
ff e0 ; APP0
 00 10
 4a 46 49 46 00 01 01 01 00 48 00 48 00 00
ff db ; DQT
 00 43
 00
 03 02 02 02 02 02 03 02
 02 02 03 03 03 03 04 06
 04 04 04 04 04 08 06 06
 05 06 09 08 0a 0a 09 08
 09 09 0a 0c 0f 0c 0a 0b
 0e 0b 09 09 0d 11 0d 0e
 0f 10 10 11 10 0a 0c 12
 13 12 10 13 0f 10 10 10
ff c9 ; SOF
 00 0b
 08 00 01 00 01 01 01 11 00
ff cc ; DAC
 00 06 00 10 10 05
ff da ; SOS
 00 08
 01 01 00 00 3f 00 d2 cf 20
ff d9 ; EOI

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

Этот файл можно создать с помощью:

#!/usr/bin/env bash
printf '\xff\xd8' # SOI
printf '\xff\xe0' # APP0
printf  '\x00\x10'
printf  '\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00'
printf '\xff\xdb' # DQT
printf  '\x00\x43'
printf  '\x00'
printf  '\x03\x02\x02\x02\x02\x02\x03\x02'
printf  '\x02\x02\x03\x03\x03\x03\x04\x06'
printf  '\x04\x04\x04\x04\x04\x08\x06\x06'
printf  '\x05\x06\x09\x08\x0a\x0a\x09\x08'
printf  '\x09\x09\x0a\x0c\x0f\x0c\x0a\x0b'
printf  '\x0e\x0b\x09\x09\x0d\x11\x0d\x0e'
printf  '\x0f\x10\x10\x11\x10\x0a\x0c\x12'
printf  '\x13\x12\x10\x13\x0f\x10\x10\x10'
printf '\xff\xc9' # SOF
printf  '\x00\x0b'
printf  '\x08\x00\x01\x00\x01\x01\x01\x11\x00'
printf '\xff\xcc' # DAC
printf  '\x00\x06\x00\x10\x10\x05'
printf '\xff\xda' # SOS
printf  '\x00\x08'
printf  '\x01\x01\x00\x00\x3f\x00\xd2\xcf\x20'
printf '\xff\xd9' # EOI

и отлично открылся с помощью GNOME Image Viewer 3.38.0 и GIMP 2.10.18 в Ubuntu 20.10.

Вот загрузка на Imgur. Обратите внимание, что Imgur обрабатывает файл, увеличивая его, однако, если вы загружаете его для проверки, и, как показано ниже, изображение width=100 показывает белый цвет на Chromium 87:

Ширина

person matja    schedule 28.02.2010
comment
Какие из этих байтов безопасно увеличивать для создания серии небольших, но разных JPEG-файлов? - person Quolonel Questions; 14.07.2013
comment
@Qulonel Вопросы. «Квадрат» байтов 8x8 в сегменте DQT по сути является коэффициентом масштабирования, любой из которых может принимать значения 1-255. Я думаю, что единственное значение, которое используется в сегменте DAC этого примера, — это первое значение в верхнем левом углу блока 8x8. - person matja; 27.01.2015

Мне пришло в голову, что вы можете сделать прогрессивный jpeg только с коэффициентами DC, чтобы один серый пиксель мог быть закодирован в 119 байтах. Это прекрасно читается в нескольких программах, в которых я пробовал (Photoshop, GNOME Image Viewer 3.38.0, GIMP 2.10.18 и другие).

ff d8 : SOI
ff db ; DQT
 00 43
 00
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01
ff c2 ; SOF
 00 0b
 08 00 01 00 01 01 01 11 00
ff c4 ; DHT
 00 14
 00
 01 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
 03
ff da ; SOS
 00 08
 01 01 00 00 00 01 3F
ff d9 ; EOI

Основная экономия пространства заключается в наличии только одной таблицы Хаффмана. Хотя это немного меньше, чем 125-байтовая арифметическая кодировка, указанная в другом ответе, арифметическая кодировка без заголовка JFIF будет еще меньше (107 байт), поэтому ее все равно следует считать наименьшей из известных.

Вышеупомянутый файл может быть сгенерирован с помощью:

#!/usr/bin/env bash
printf '\xff\xd8' # SOI
printf '\xff\xdb' # DQT
printf  '\x00\x43'
printf  '\x00'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf  '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\xff\xc2' # SOF
printf  '\x00\x0b'
printf  '\x08\x00\x01\x00\x01\x01\x01\x11\x00'
printf '\xff\xc4' # DHT
printf  '\x00\x14'
printf  '\x00'
printf  '\x01\x00\x00\x00\x00\x00\x00\x00'
printf  '\x00\x00\x00\x00\x00\x00\x00\x00'
printf  '\x03'
printf '\xff\xda' # SOS
printf  '\x00\x08'
printf  '\x01\x01\x00\x00\x00\x01\x3F'
printf '\xff\xd9' # EOI
person garlon4    schedule 09.06.2014
comment
Для любопытных, при попытке прочитать это с помощью iOS' [UIImage imageWithData:] выводится: ImageIO: JPEG Corrupt JPEG data: 2 extraneous bytes before marker 0xda. - person Ricardo Sanchez-Saez; 31.07.2014

Попробуйте следующее (134 байта):

FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 48 00 48 00 00
FF DB 00 43 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF C2 00 0B 08 00 01 00 01 01 01
11 00 FF C4 00 14 10 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 FF DA 00 08 01 01 00 01 3F 10

Источник: Самый маленький в мире, допустимый JPEG? от Jesse_hz

person kenorb    schedule 17.05.2015

Найден "самый маленький GIF-файл" всего с 26 байт.

47 49 46 38 39 61 01 00 01 00 
00 ff 00 2c 00 00 00 00 01 00 
01 00 00 02 00 3b

Литерал Python:

b'GIF89a\x01\x00\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x00;'
person Henrique Bastos    schedule 13.04.2016
comment
Есть ли формальная связь между GIF и JPG? - person Ciro Santilli 新疆再教育营六四事件ۍ 10.01.2021
comment
@CiroSantilliTRUMPBANISBAD Питон. - person Nakilon; 17.01.2021

Вот процедура C++, которую я написал для этого:

bool is_jpeg(const unsigned char* img_data, size_t size)
{           
    return img_data &&
           (size >= 10) &&
           (img_data[0] == 0xFF) &&
           (img_data[1] == 0xD8) &&
           ((memcmp(img_data + 6, "JFIF", 4) == 0) ||
            (memcmp(img_data + 6, "Exif", 4) == 0));
}

img_data указывает на буфер, содержащий данные JPEG.

Я уверен, что вам нужно больше байтов, чтобы иметь JPEG, который будет декодирован в полезное изображение, но справедливо поспорить, что если первые 10 байтов пройдут этот тест, буфер, вероятно, содержит JPEG.

РЕДАКТИРОВАНИЕ: вы можете, конечно, заменить 10 выше на более высокое значение, как только вы решите один. 134, как, например, предложено в другом ответе.

person Warren Young    schedule 12.02.2010

Хотя я понимаю, что это далеко не самый маленький допустимый jpeg и имеет мало или вообще никакого отношения к вашему фактическому вопросу, я чувствовал, что должен поделиться этим, так как я искал очень маленький JPEG, который на самом деле выглядел как что-то, с чем можно было бы провести некоторое тестирование. когда я нашел ваш вопрос. Я делюсь ею здесь, потому что она действительна, мала и делает меня ROFL.

Вот изображение JPEG размером 384 байта, которое я сделал в фотошопе. Это буквы ROFL, нарисованные мной вручную, а затем сохраненные с максимальными настройками сжатия, но все еще читаемые.

Шестнадцатеричные последовательности:

my @image_hex = qw{
 FF D8 FF E0 00 10 4A 46 49 46 00 01 02 00 00 64
 00 64 00 00 FF EC 00 11 44 75 63 6B 79 00 01 00
 04 00 00 00 00 00 00 FF EE 00 0E 41 64 6F 62 65
 00 64 C0 00 00 00 01 FF DB 00 84 00 1B 1A 1A 29
 1D 29 41 26 26 41 42 2F 2F 2F 42 47 3F 3E 3E 3F
 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
 47 47 47 47 47 47 47 47 47 47 47 47 01 1D 29 29
 34 26 34 3F 28 28 3F 47 3F 35 3F 47 47 47 47 47
 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
 47 47 47 47 47 47 47 47 47 47 47 47 47 FF C0 00
 11 08 00 08 00 19 03 01 22 00 02 11 01 03 11 01
 FF C4 00 61 00 01 01 01 01 00 00 00 00 00 00 00
 00 00 00 00 00 00 04 02 05 01 01 01 01 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 02 04 10 00 02
 02 02 02 03 01 00 00 00 00 00 00 00 00 00 01 02
 11 03 00 41 21 12 F0 13 04 31 11 00 01 04 03 00
 00 00 00 00 00 00 00 00 00 00 00 00 21 31 61 71
 B1 12 22 FF DA 00 0C 03 01 00 02 11 03 11 00 3F
 00 A1 7E 6B AD 4E B6 4B 30 EA E0 19 82 39 91 3A
 6E 63 5F 99 8A 68 B6 E3 EA 70 08 A8 00 55 98 EE
 48 22 37 1C 63 19 AF A5 68 B8 05 24 9A 7E 99 F5
 B3 22 20 55 EA 27 CD 8C EB 4E 31 91 9D 41 FF D9
}; #this is a very tiny jpeg. it is a image representaion of the letters "ROFL" hand drawn by me in photoshop and then saved at the lowest possible quality settings where the letters could still be made out :)

my $image_data = pack('H2' x scalar(@image_hex), @image_hex);
my $url_escaped_image = uri_escape( $image_data );

Данные бинарного изображения, экранированные URL (можно вставить прямо в URL)

%FF%D8%FF%E0%00%10JFIF%00%01%02%00%00d%00d%00%00%FF%EC%00%11Ducky%00%01%00%04%00%00%00%00%00%00%FF%EE%00%0EAdobe%00d%C0%00%00%00%01%FF%DB%00%84%00%1B%1A%1A)%1D)A%26%26AB%2F%2F%2FBG%3F%3E%3E%3FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG%01%1D))4%264%3F((%3FG%3F5%3FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG%FF%C0%00%11%08%00%08%00%19%03%01%22%00%02%11%01%03%11%01%FF%C4%00a%00%01%01%01%01%00%00%00%00%00%00%00%00%00%00%00%00%00%04%02%05%01%01%01%01%00%00%00%00%00%00%00%00%00%00%00%00%00%00%02%04%10%00%02%02%02%02%03%01%00%00%00%00%00%00%00%00%00%01%02%11%03%00A!%12%F0%13%041%11%00%01%04%03%00%00%00%00%00%00%00%00%00%00%00%00%00!1aq%B1%12%22%FF%DA%00%0C%03%01%00%02%11%03%11%00%3F%00%A1~k%ADN%B6K0%EA%E0%19%829%91%3Anc_%99%8Ah%B6%E3%EAp%08%A8%00U%98%EEH%227%1Cc%19%AF%A5h%B8%05%24%9A~%99%F5%B3%22%20U%EA'%CD%8C%EBN1%91%9DA%FF%D9
person BladeMcCool    schedule 25.10.2010

Не требуется, чтобы файлы JPEG содержали маркер JFIF или Exif. Но они должны начинаться с FF D8, и за ними должен следовать маркер, чтобы вы могли проверить наличие FF D8 FF.

person jsam    schedule 20.06.2010
comment
Это отличный комментарий, но он не отвечает на вопрос ОП. Рассмотрите возможность размещения его под другим ответом. - person Brent Faust; 02.09.2015