Skip to content

Commit 245c84f

Browse files
SebastianBossepi0
andauthored
feat: add tiff size detection support (#3)
Co-authored-by: Pooya Parsa <[email protected]>
1 parent 869dbf2 commit 245c84f

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

src/types/tiff.ts

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,101 @@
11
// based on http://www.compix.com/fileformattif.htm
2+
// TO-DO: support big-endian as well
3+
import { readUInt, toHexString, toUTF8String } from "./utils";
24
import type { IImage } from "./interface";
3-
import { toHexString } from "./utils";
5+
6+
// Read IFD (image-file-directory) into a buffer
7+
function readIFD(buffer: Uint8Array, isBigEndian: boolean) {
8+
const ifdOffset = readUInt(buffer, 32, 4, isBigEndian);
9+
10+
// read only till the end of the file
11+
let bufferSize = 1024;
12+
const fileSize = buffer.length;
13+
if (ifdOffset + bufferSize > fileSize) {
14+
bufferSize = fileSize - ifdOffset - 10;
15+
}
16+
17+
return buffer.slice(ifdOffset + 2, ifdOffset + 2 + bufferSize);
18+
}
19+
20+
// TIFF values seem to be messed up on Big-Endian, this helps
21+
function readValue(buffer: Uint8Array, isBigEndian: boolean): number {
22+
const low = readUInt(buffer, 16, 8, isBigEndian);
23+
const high = readUInt(buffer, 16, 10, isBigEndian);
24+
return (high << 16) + low;
25+
}
26+
27+
// move to the next tag
28+
function nextTag(buffer: Uint8Array) {
29+
if (buffer.length > 24) {
30+
return buffer.slice(12);
31+
}
32+
}
33+
34+
// Extract IFD tags from TIFF metadata
35+
function extractTags(buffer: Uint8Array, isBigEndian: boolean) {
36+
const tags: { [key: number]: number } = {};
37+
38+
let temp: Uint8Array | undefined = buffer;
39+
while (temp && temp.length > 0) {
40+
const code = readUInt(temp, 16, 0, isBigEndian);
41+
const type = readUInt(temp, 16, 2, isBigEndian);
42+
const length = readUInt(temp, 32, 4, isBigEndian);
43+
44+
// 0 means end of IFD
45+
if (code === 0) {
46+
break;
47+
} else {
48+
// 256 is width, 257 is height
49+
// if (code === 256 || code === 257) {
50+
if (length === 1 && (type === 3 || type === 4)) {
51+
tags[code] = readValue(temp, isBigEndian);
52+
}
53+
54+
// move to the next tag
55+
temp = nextTag(temp);
56+
}
57+
}
58+
59+
return tags;
60+
}
61+
62+
// Test if the TIFF is Big Endian or Little Endian
63+
function determineEndianness(input: Uint8Array) {
64+
const signature = toUTF8String(input, 0, 2);
65+
if (signature === "II") {
66+
return "LE";
67+
} else if (signature === "MM") {
68+
return "BE";
69+
}
70+
}
471

572
const signatures = new Set([
6-
"492049", // ?
73+
// '492049', // currently not supported
774
"49492a00", // Little endian
875
"4d4d002a", // Big Endian
9-
"4d4d002a", // BigTIFF > 4GB. currently not supported
76+
// '4d4d002a', // BigTIFF > 4GB. currently not supported
1077
]);
1178

1279
export const TIFF: IImage = {
1380
validate: (input) => signatures.has(toHexString(input, 0, 4)),
14-
calculate: () => ({ width: undefined, height: undefined }),
81+
82+
calculate(input) {
83+
// Determine BE/LE
84+
const isBigEndian = determineEndianness(input) === "BE";
85+
86+
// read the IFD
87+
const ifdBuffer = readIFD(input, isBigEndian);
88+
89+
// extract the tags from the IFD
90+
const tags = extractTags(ifdBuffer, isBigEndian);
91+
92+
const width = tags[256];
93+
const height = tags[257];
94+
95+
if (!width || !height) {
96+
throw new TypeError("Invalid Tiff. Missing tags");
97+
}
98+
99+
return { height, width };
100+
},
15101
};
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"height": undefined,
2+
"height": 456,
33
"type": "tiff",
4-
"width": undefined,
4+
"width": 123,
55
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"height": undefined,
2+
"height": 456,
33
"type": "tiff",
4-
"width": undefined,
4+
"width": 123,
55
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"height": undefined,
2+
"height": 456,
33
"type": "tiff",
4-
"width": undefined,
4+
"width": 123,
55
}

0 commit comments

Comments
 (0)