JPEG图像的第2个和第3个字节是否始终是APP0或APP1标记?

时间:2011-03-23 23:39:49

标签: jpeg exif

我有一些不同的JPEG图像,我一直在测试。据我所见,第0个和第一个字节始终是0xFF0xD8

第二个和第三个通常是0xFF0xE0(APP0),表示JFIF段或JFIF扩展段或0xFF0xE1(APP1)表示EXIF细分。

我的问题:这种情况总是如此吗?第2和第3个字节总是APP0还是APP1?

8 个答案:

答案 0 :(得分:9)

没有。例如有几个没有这些标记或其他APP标记创建JPEG的相机。您唯一可以依赖的是SOI序列,FF D8,甚至EOI都不是由所有摄像机生成的。另请注意,存在嵌入JPEG的JPEG - 您可以在图像中嵌套SOI / EOI。

如果你需要在原始相机图像中处理嵌入的JPEG数据,那么几个模型会产生类似JPEG的数据,这些数据只能通过jpeg规范稍微松散来解析 - 特别是与转义的FF字节有关在数据中。然后你有相机产生专有数据,乍一看看起来像jpeg数据(例如索尼的一些“加密”原始格式)

答案 1 :(得分:2)

不,它肯定不一定是这样。阅读Wikipedia

据我所知,APPn段只是应用程序将任意数据嵌入图像文件的方法。显然,应用程序通常会利用这一点并将0xFF 0xEO0xFF 0xE1字节写入标题中,但对于的应用程序来说,完全可行并且继续与图像数据。前两个字节(0xFF和0xD8)必需的,因为它们是SOI(图像起始)标记。

答案 2 :(得分:2)

这里的事情很复杂。由于我目前正在编写一个javascript文件标识符,因此我将尝试使用我的javascript对象来回答JPEG。 特别是因为这个问题有一个“javascript”标签。

已经给出了基本答案(已接受的答案),但这更详细地说明了如何检查不同的App标记(使用后备)。

到目前为止,JFIF,EXIF,Adobe,佳能和三星都有特殊的APP0(但我们不知道未来)。所以js对象的逻辑是:

如果其中一个SPECS [x] .regex匹配,则获胜(第一个获胜)。但如果没有匹配,父对象(仅FFd8)将获胜。

SPECS对象提供根据PRONOM标识符 - 您可以像这样查看

'http://apps.nationalarchives.gov.uk/pronom/fmt/'。concat(PUID)[官方] 'http://apps.nationalarchives.gov.uk/pronom/x-fmt/'。concat(xPUID)[experimental]

_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'}
    ]
}

答案 3 :(得分:1)

前两个字节是 JPEG SOI标记,因此始终存在。

第2个和第3个字节似乎存储元数据,这可能不存在于每个JPEG中。

Further Reading

答案 4 :(得分:1)

通常是的,但是我对JPEG的理解是任何段类型都可以跟随标题。

答案 5 :(得分:1)

没有。有一些程序可以删除一些标记。 ImageOptim就是这样一个程序。你只需要一些标记。该程序还将优化霍夫曼表

答案 6 :(得分:0)

对于JFIF文件,在FFD8之后,JFIF头立即跟随。 JFIF标头包含在APP0标记内。该规范没有提及任何关于填充的内容。

如果没有JFIF标题,我们只能猜测使用的颜色格式。

答案 7 :(得分:0)

理论上,是的。根据{{​​3}} (pdf),其APP0部分应该位于文件的第一位。 JFIF spec (pdf)对其APP1部分要求相同。

但你不应指望APPn部分的顺序(甚至存在);那里有疯狂的JPEG作家。从SOI开始,阅读各部分。