问题
My web app checks the first four bytes against the file extension before accepting uploaded images. A coworker showed me images from his iPhone which are being rejected. These have a different fourth byte (e1 = 225 instead of the expected e0 = 224).
Is this usual for iPhones? Are there other possible magic byte strings used in JPG files?
Edit: found this useful list: http://www.garykessler.net/library/file_sigs.html
回答1:
They seem to indicate a sub category of JPEG in some way. What I have found out is that the FF D8 FF E0 magic indicates a "JFIF JPEG" whereas the FF D8 FF E1 indicates an "EXIF JPEG".
Edit: Found this one in a google cache: http://tinyurl.com/ydtjpjw (interesting because it indicates that Samsung has a few more variations)
回答2:
FF always identifies a "marker" - Since I am currently writing a javascript file identifier, I'll try to answer with my javascript object for JPEG...
The basic answer is already given (the accepted one) but this is more detailed about how to check the different App markers (with fallback). And btw: There are special APP0s so far for JFIF, EXIF, Adobe, Canon AND Samsung (but we don't know about the future). So the logic for the js object is:
If one of the SPECS[x].regex is matched it wins (first one wins). But if nothing is matched, the parent object (only FFd8) wins.
The SPECS object delivers according PRONOM identifiers - you can view them like so
'http://apps.nationalarchives.gov.uk/pronom/fmt/'.concat(PUID) [official] '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:
That does appear to be a perfectly valid JPEG variant, according to Google.
来源:https://stackoverflow.com/questions/1975172/iphone-jpg-image-has-non-standard-magic-bytes-ff-d8-ff-e1