Являются ли 2-й и 3-й байты изображения JPEG всегда маркером APP0 или APP1? - PullRequest
6 голосов
/ 24 марта 2011

У меня есть несколько разных изображений JPEG, с которыми я тестировал. Насколько я видел, 0-й и первый байты всегда 0xFF и 0xD8.

Вторым и третьим обычно являются либо 0xFF и 0xE0 (APP0), указывающие либо сегмент JFIF, либо сегмент расширения JFIF, либо 0xFF и 0xE1 (APP1), указывающие сегмент EXIF.

Мой вопрос: это всегда так? 2-й и 3-й байты всегда APP0 или APP1?

Ответы [ 8 ]

9 голосов
/ 24 марта 2011

Нет.Например, есть несколько камер, которые создают JPEG без этих маркеров или с другими маркерами APP.Единственное, на что вы можете положиться - это последовательность SOI, FF D8, даже EOI не создается всеми камерами.Также имейте в виду, что существуют JPEG-файлы со встроенными JPEG-файлами - у вас может быть вложенный SOI / EOI в изображении.

Если вам нужно иметь дело со встроенными данными JPEG в необработанных изображениях камеры, некоторые модели создают данные в формате JPEG, которые могутразбираться только в том случае, если он немного слабоват со спецификацией jpeg - особенно в отношении экранированных FF байтов в данных.И затем у вас есть камеры, которые выдают проприетарные данные, которые на первый взгляд выглядят как данные JPEG (например, некоторые из «зашифрованных» необработанных форматов Sony)

2 голосов
/ 29 июня 2014

Здесь все сложно. Поскольку в настоящее время я пишу идентификатор файла javascript, я попытаюсь ответить с помощью моего объекта javascript для JPEG. Тем более, что у вопроса был тег "javascript".

Основной ответ уже дан (принятый), но более подробно о том, как проверить различные маркеры приложения (с отступлением).

На данный момент существуют специальные APP0 для JFIF, EXIF, Adobe, Canon и Samsung (но мы не знаем о будущем). Итак, логика для объекта js:

Если один из SPECS [x] .regex совпадает, он выигрывает (первый выигрывает). Но если ничего не найдено, родительский объект (только FFd8) побеждает.

Объект SPECS доставляет в соответствии с идентификаторами ПРОНОМ - вы можете просматривать их так

'http://apps.nationalarchives.gov.uk/pronom/fmt/'.concat(PUID) [официальный] 'http://apps.nationalarchives.gov.uk/pronom/x-fmt/'.concat(xPUID) [экспериментальный]

_FFD8: { 
    SPECS: [
        { 
            PUID: 112, 
            regex: /^FFD8FFE8(.{2})53504946460001/, 
            desc: 'jpeg: Still Picture Interchange Format file (SPIF)',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                version: '1.00'
            }
        }, 
        { 
            PUID: 44, 
            regex: /^FFD8FFE0(.{2})4A464946000102/, 
            desc: 'jpeg: JPEG File Interchange Format file (JFIF), v. 1.02',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                version: '1.02',
            }
        },
        { 
            PUID: 43, 
            regex: /^FFD8FFE0(.{2})4A464946000101/, 
            desc: 'jpeg: JPEG File Interchange Format file (JFIF), v. 1.01',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                version: '1.01',
            }
        },
        { 
            PUID: 42, 
            regex: /^FFD8FFE0(.{2})4A464946000100/, 
            desc: 'jpeg: JPEG File Interchange Format file (JFIF), v. 1.00',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                version: '1.00',
            }
        },          
        { 
            PUID: 41, 
            xPUID: 398,
            regex: /^FFD8FFE1(.{2})45786966000049492A00(.+)009007000400000030323030/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), little endian, v. 2.0',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'little',
                version: '2.0',
            }
        }, 
        { 
            PUID: 41, 
            xPUID: 398, 
            regex: /^FFD8FFE1(.{2})4578696600004D4D002A(.+)900000070000000430323030/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), big endian, v. 2.0',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'big',
                version: '2.0',
            }
        },              
        { 
            PUID: 41, 
            xPUID: 390,
            regex: /^FFD8FFE1(.{2})45786966000049492A00(.+)009007000400000030323130/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), little endian, v. 2.1',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'little',
                version: '2.1',
            }
        }, 
        { 
            PUID: 41, 
            xPUID: 390, 
            regex: /^FFD8FFE1(.{2})4578696600004D4D002A(.+)900000070000000430323130/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), big endian, v. 2.1',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'big',
                version: '2.1',
            }
        },          
        { 
            PUID: 41, 
            xPUID: 391,
            regex: /^FFD8FFE1(.{2})45786966000049492A00(.+)009007000400000030323230/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), little endian, v. 2.2',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'little',
                version: '2.2',
            }
        }, 
        { 
            PUID: 41, 
            xPUID: 391, 
            regex: /^FFD8FFE1(.{2})4578696600004D4D002A(.+)900000070000000430323230/, 
            desc: 'jpeg: JPG Image File, using Exchangeable Image File Format (Exif), big endian, v. 2.2',
            regexCapture: [
                { key: 'recordedSignature' }, 
                { key: 'segmentLength', fn: function(h){ return { value:parseInt(h, 16), _val:h.toString() }; } }
            ], 
            valueCapture: {
                endian: 'big',
                version: '2.2',
            }
        }, 
        // specific JPEG (all begin with FFD8FF, map them to PUID 41)
        { 
            PUID: 41, 
            regex: /^FFD8FFED/, 
            desc: 'jpeg: JPG Image File, Adobe JPEG, Photoshop CMYK buffer'
        }, 
        { 
            PUID: 41, 
            regex: /^FFD8FFE2/, 
            desc: 'jpeg: JPG Image File, Canon JPEG, Canon EOS-1D'
        }, 
        { 
            PUID: 41, 
            regex: /^FFD8FFE3/, 
            desc: 'jpeg: JPG Image File, Samsung JPEG, e.g. Samsung D500'
        }, 
        { 
            PUID: 41, 
            regex: /^FFD8FFDB/, 
            desc: 'jpeg: JPG Image File, Samsung JPEG, e.g. Samsung D807'
        }
    ],
    ext: ['JPG', 'JPE', 'JPEG', 'SPF', 'SPIFF'],
    signature: [ 255, 216 ],
    desc: 'jpeg: JPEG File Interchange Format file, App0 marker not known',
    mime: 'image/jpeg',
    specifications: [
        { text:'Specification for the JFIF file format', href:'http://www.w3.org/Graphics/JPEG/jfif3.pdf', type:'W3', format:'pdf' },
        { text:'The JPEG compression specification', href:'http://www.w3.org/Graphics/JPEG/itu-t81.pdf', type:'W3', format:'pdf' },
        { text:'Exchangeable image file format for digital still cameras', href:'http://home.jeita.or.jp/tsc/std-pdf/CP3451C.pdf', type:'vendor', format:'pdf' }
    ], 
    references: [
        { text:'JPEG JFIF W3 Info', href:'http://www.w3.org/Graphics/JPEG/', type:'W3', format:'html' },
        { text:'JPEG.org', href:'http://www.jpeg.org/', type:'info', format:'html' },
        { text:'JPEG Exif App markers', href:'http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html', type:'info', format:'html'}
    ]
}
2 голосов
/ 24 марта 2011

Нет, так не должно быть.Чтение Википедии .

Насколько я могу судить, сегменты APPn - это просто способы для приложений встраивать произвольные данные в файл изображения.Очевидно, что приложения обычно пользуются этим преимуществом и записывают 0xFF 0xEO или 0xFF 0xE1 байт в заголовок, но было бы вполне вероятно, что приложение не сделает это и просто продолжит работу с данными изображения.Первые два байта (0xFF и 0xD8) являются обязательными , поскольку они являются маркером SOI (начало изображения).

1 голос
/ 09 января 2014

Нет.Есть программы, которые удаляют некоторые маркеры.ImageOptim - такая программа.Вам нужны только некоторые маркеры.Эта программа также оптимизирует таблицы Хаффмана

1 голос
/ 24 марта 2011

Как правило, да, однако мое понимание JPEG таково, что за заголовком может следовать любой тип сегмента.

1 голос
/ 24 марта 2011

Эти первые два байта являются маркером SOI JPEG , поэтому присутствуют всегда.

Появляются 2-й и 3-й байты для хранения метаданных, которые, вероятно, отсутствуют в каждом JPEG.

Дополнительная литература .

0 голосов
/ 18 августа 2011

В теории да.Согласно спецификации JFIF (pdf) , ее раздел APP0 должен стоять первым в файле.И для Exif spec (pdf) требуется то же самое для своего раздела APP1.

Но вы не должны рассчитывать на порядок (или даже на существование) APPnсекции;есть сумасшедшие авторы JPEG там.Начните с SOI и читайте разделы по мере их поступления.

0 голосов
/ 28 марта 2011

Для файла JFIF заголовок JFIF должен следовать сразу после FFD8. Заголовок JFIF содержится в маркере APP0. Хотя в спецификации ничего не говорится о заполнении.

Без заголовка JFIF мы можем только догадываться, какой цветовой формат используется.

...