image-js
Version:
Image processing and manipulation in JavaScript
115 lines • 3.76 kB
JavaScript
import { decode } from 'tiff';
import { Image } from '../Image.js';
import { getMetadata } from './getMetadata.js';
/**
* Decode a TIFF. See the tiff module.
* @param buffer - The data to decode.
* @returns The decoded image.
*/
export function decodeTiff(buffer) {
const result = decode(buffer, { pages: [0] });
return getImageFromIFD(result[0]);
}
/**
* Create image from a single IFD.
* @param ifd - The IFD.
* @returns The decoded image.
*/
export function getImageFromIFD(ifd) {
if (ifd.data instanceof Float32Array || ifd.data instanceof Float64Array) {
throw new Error('Float TIFF data is not supported.');
}
const resolution = getTiffResolution(ifd);
if (ifd.type === 3) {
const hasAlpha = ifd.samplesPerPixel === 2;
const pixelLength = hasAlpha ? 4 : 3;
const data = new Uint16Array(pixelLength * ifd.width * ifd.height);
const palette = ifd.palette;
let ptr = 0;
if (hasAlpha) {
for (let index = 0; index < ifd.data.length; index += ifd.samplesPerPixel) {
const color = palette[ifd.data[index]];
data[ptr++] = color[0];
data[ptr++] = color[1];
data[ptr++] = color[2];
// To ensure that the value is 16 bits.
data[ptr++] = Math.round((ifd.data[index + 1] / 2 ** ifd.bitsPerSample) * 65535);
}
}
else {
for (let index = 0; index < ifd.data.length; index += ifd.samplesPerPixel) {
const color = palette[ifd.data[index]];
data[ptr++] = color[0];
data[ptr++] = color[1];
data[ptr++] = color[2];
}
}
return new Image(ifd.width, ifd.height, {
data,
colorModel: hasAlpha ? 'RGBA' : 'RGB',
bitDepth: 16,
meta: getMetadata(ifd),
resolution,
});
}
else if (ifd.type === 1 || ifd.type === 0) {
if (ifd.bitsPerSample !== 1) {
return new Image(ifd.width, ifd.height, {
data: ifd.data,
bitDepth: ifd.bitsPerSample,
colorModel: ifd.alpha ? 'GREYA' : 'GREY',
meta: getMetadata(ifd),
resolution,
});
}
else {
return new Image(ifd.width, ifd.height, {
data: ifd.data.map((pixel) => pixel * 255),
bitDepth: 8,
colorModel: 'GREY',
meta: getMetadata(ifd),
resolution,
});
}
}
else {
return new Image(ifd.width, ifd.height, {
data: ifd.data,
bitDepth: ifd.bitsPerSample,
colorModel: ifd.alpha ? 'RGBA' : 'RGB',
meta: getMetadata(ifd),
resolution,
});
}
}
/**
* Gets image resolution from its metadata and converts it into Pixels per meter, when it's possible. Also keeps original resolution values and units.
* @param ifd - Tiff metadata.
* @returns Resolution object.
*/
function getTiffResolution(ifd) {
if (!ifd.xResolution || !ifd.yResolution) {
return undefined;
}
switch (ifd.resolutionUnit) {
case 1:
return {
x: ifd.xResolution,
y: ifd.yResolution,
unit: 'unknown',
};
case 3:
return {
x: ifd.xResolution,
y: ifd.yResolution,
unit: 'centimeter',
};
default:
return {
x: ifd.xResolution,
y: ifd.yResolution,
unit: 'inch',
};
}
}
//# sourceMappingURL=decodeTiff.js.map