Skip to content

Commit

Permalink
Improve parsing TIFF files
Browse files Browse the repository at this point in the history
Detect DNG files in a reliable matter.

Fixes: #480
  • Loading branch information
Borewit committed Aug 13, 2021
1 parent c037ba7 commit 8861872
Showing 1 changed file with 48 additions and 41 deletions.
89 changes: 48 additions & 41 deletions core.js
Expand Up @@ -68,7 +68,7 @@ export async function fileTypeFromTokenizer(tokenizer) {
}

async function _fromTokenizer(tokenizer) {
let buffer = Buffer.alloc(minimumBytes);
const buffer = Buffer.alloc(minimumBytes);
const bytesRead = 12;
const check = (header, options) => _check(buffer, header, options);
const checkString = (header, options) => check(stringToBytes(header), options);
Expand Down Expand Up @@ -617,58 +617,65 @@ async function _fromTokenizer(tokenizer) {
};
}

// TIFF, little-endian type
if (check([0x49, 0x49, 0x2A, 0x0])) {
if (checkString('CR', {offset: 8})) {
async function readTiffTag() {
const tagId = await tokenizer.readToken(Token.UINT16_LE);
await tokenizer.readToken(Token.UINT16_LE); // Tag data
await tokenizer.readToken(Token.UINT32_LE); // Nr of values
if (tagId === 50_706) { // Tag = DNGVersion
return {
ext: 'cr2',
mime: 'image/x-canon-cr2',
ext: 'dng',
mime: 'image/x-adobe-dng',
};
}
}

if (check([0x1C, 0x00, 0xFE, 0x00], {offset: 8}) || check([0x1F, 0x00, 0x0B, 0x00], {offset: 8})) {
return {
ext: 'nef',
mime: 'image/x-nikon-nef',
};
async function readTiffIFD() {
const numberOfTags = await tokenizer.readToken(Token.UINT16_LE);
for (let n = 0; n < numberOfTags; ++n) {
const fileType = await readTiffTag();
if (fileType) {
return fileType;
}
}
}

if (
check([0x08, 0x00, 0x00, 0x00], {offset: 4})
&& (check([0x2D, 0x00, 0xFE, 0x00], {offset: 8})
|| check([0x27, 0x00, 0xFE, 0x00], {offset: 8}))
) {
return {
ext: 'dng',
mime: 'image/x-adobe-dng',
// TIFF, little-endian type
if (check([0x49, 0x49])) {
const version = Token.UINT16_LE.get(buffer, 2);

if (version === 42) {
// TIFF file header

if (checkString('CR', {offset: 8})) {
return {
ext: 'cr2',
mime: 'image/x-canon-cr2',
};
}

if (check([0x1C, 0x00, 0xFE, 0x00], {offset: 8}) || check([0x1F, 0x00, 0x0B, 0x00], {offset: 8})) {
return {
ext: 'nef',
mime: 'image/x-nikon-nef',
};
}

const ifdOffset = Token.UINT16_LE.get(buffer, 4);
await tokenizer.ignore(ifdOffset);
const fileType = await readTiffIFD();
return fileType ? fileType : {
ext: 'tif',
mime: 'image/tiff',
};
}

buffer = Buffer.alloc(24);
await tokenizer.peekBuffer(buffer);
if (
(check([0x10, 0xFB, 0x86, 0x01], {offset: 4}) || check([0x08, 0x00, 0x00, 0x00], {offset: 4}))
// This pattern differentiates ARW from other TIFF-ish file types:
&& check([0x00, 0xFE, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x01], {offset: 9})
) {
if (version === 43) {
// Big TIFF file header
return {
ext: 'arw',
mime: 'image/x-sony-arw',
ext: 'tif',
mime: 'image/tiff',
};
}

return {
ext: 'tif',
mime: 'image/tiff',
};
}

// TIFF, big-endian type
if (check([0x4D, 0x4D, 0x0, 0x2A])) {
return {
ext: 'tif',
mime: 'image/tiff',
};
}

if (checkString('MAC ')) {
Expand Down

0 comments on commit 8861872

Please sign in to comment.