tiff
Version:
TIFF image decoder written entirely in JavaScript
153 lines (138 loc) • 4.21 kB
text/typescript
import type TIFFDecoder from './tiff_decoder.ts';
const types = new Map<
number,
[number, (decoder: TIFFDecoder, count: number) => any]
>([
[1, [1, readByte]], // BYTE
[2, [1, readASCII]], // ASCII
[3, [2, readShort]], // SHORT
[4, [4, readLong]], // LONG
[5, [8, readRational]], // RATIONAL
[6, [1, readSByte]], // SBYTE
[7, [1, readByte]], // UNDEFINED
[8, [2, readSShort]], // SSHORT
[9, [4, readSLong]], // SLONG
[10, [8, readSRational]], // SRATIONAL
[11, [4, readFloat]], // FLOAT
[12, [8, readDouble]], // DOUBLE
]);
export function getByteLength(type: number, count: number): number {
const val = types.get(type);
if (!val) throw new Error(`type not found: ${type}`);
return val[0] * count;
}
export function readData(
decoder: TIFFDecoder,
type: number,
count: number,
): any {
const val = types.get(type);
if (!val) throw new Error(`type not found: ${type}`);
return val[1](decoder, count);
}
function readByte(decoder: TIFFDecoder, count: number): number | Uint8Array {
if (count === 1) return decoder.readUint8();
const array = new Uint8Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readUint8();
}
return array;
}
function readASCII(decoder: TIFFDecoder, count: number): string | string[] {
const strings = [];
let currentString = '';
for (let i = 0; i < count; i++) {
// eslint-disable-next-line unicorn/prefer-code-point
const char = String.fromCharCode(decoder.readUint8());
if (char === '\0') {
strings.push(currentString);
currentString = '';
} else {
currentString += char;
}
}
if (strings.length === 1) {
return strings[0];
} else {
return strings;
}
}
function readShort(decoder: TIFFDecoder, count: number): number | Uint16Array {
if (count === 1) return decoder.readUint16();
const array = new Uint16Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readUint16();
}
return array;
}
function readLong(decoder: TIFFDecoder, count: number): number | Uint32Array {
if (count === 1) return decoder.readUint32();
const array = new Uint32Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readUint32();
}
return array;
}
function readRational(decoder: TIFFDecoder, count: number): number | number[] {
if (count === 1) {
return decoder.readUint32() / decoder.readUint32();
}
const rationals = new Array(count);
for (let i = 0; i < count; i++) {
rationals[i] = decoder.readUint32() / decoder.readUint32();
}
return rationals;
}
function readSByte(decoder: TIFFDecoder, count: number): number | Int8Array {
if (count === 1) return decoder.readInt8();
const array = new Int8Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readInt8();
}
return array;
}
function readSShort(decoder: TIFFDecoder, count: number): number | Int16Array {
if (count === 1) return decoder.readInt16();
const array = new Int16Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readInt16();
}
return array;
}
function readSLong(decoder: TIFFDecoder, count: number): number | Int32Array {
if (count === 1) return decoder.readInt32();
const array = new Int32Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readInt32();
}
return array;
}
function readSRational(decoder: TIFFDecoder, count: number): number | number[] {
if (count === 1) {
return decoder.readInt32() / decoder.readInt32();
}
const rationals = new Array(count);
for (let i = 0; i < count; i++) {
rationals[i] = decoder.readInt32() / decoder.readInt32();
}
return rationals;
}
function readFloat(decoder: TIFFDecoder, count: number): number | Float32Array {
if (count === 1) return decoder.readFloat32();
const array = new Float32Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readFloat32();
}
return array;
}
function readDouble(
decoder: TIFFDecoder,
count: number,
): number | Float64Array {
if (count === 1) return decoder.readFloat64();
const array = new Float64Array(count);
for (let i = 0; i < count; i++) {
array[i] = decoder.readFloat64();
}
return array;
}