Skip to content

Commit

Permalink
Implement decodeStack (#422)
Browse files Browse the repository at this point in the history
* feat(stack): decode stack from tiff

Closes: #421

* chore: run prettier

* fix: export decodeStack
  • Loading branch information
opatiny authored Dec 15, 2023
1 parent f37d4e4 commit 69f1649
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/load/decodeTiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ type TiffIfd = ReturnType<typeof decode>[number];
export function decodeTiff(buffer: Uint8Array): Image {
const result = decode(buffer);
return getImageFromIFD(result[0]);
// TODO: handle stacks (many IFDs)
// TODO: optimize not to decode whole file
}

/**
* Create image from a single IFD.
* @param ifd - The IFD.
* @returns The decoded image.
*/
function getImageFromIFD(ifd: TiffIfd): Image {
export function getImageFromIFD(ifd: TiffIfd): Image {
if (ifd.type === 3) {
// Palette
const data = new Uint16Array(3 * ifd.width * ifd.height);
Expand Down
6 changes: 0 additions & 6 deletions src/stack/compute/index.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/stack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './compute/histogram';
export * from './compute/maxImage';
export * from './compute/meanImage';
export * from './compute/medianImage';
export * from './load/decodeStack';
export * from './compute/minImage';
export * from './compute/sum';
42 changes: 42 additions & 0 deletions src/stack/load/__tests__/decodeStack.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TestImagePath } from '../../../../test/TestImagePath';
import { decodeStack } from '../decodeStack';

test.each([
{
name: 'formats/tif/grey8-multi.tif',
colorModel: 'GREY',
bitDepth: 8,
pages: 2,
},
{
name: 'formats/tif/grey16-multi.tif',
colorModel: 'GREY',
bitDepth: 16,
pages: 2,
},
{
name: 'formats/tif/color8-multi.tif',
colorModel: 'RGB',
bitDepth: 8,
pages: 2,
},
{
name: 'formats/tif/color16-multi.tif',
colorModel: 'RGB',
bitDepth: 16,
pages: 2,
},
])('stacks with 2 images ($colorModel, bitDepth = $bitDepth)', (data) => {
const buffer = testUtils.loadBuffer(data.name as TestImagePath);
const stack = decodeStack(buffer);
expect(stack.size).toBe(data.pages);
for (const image of stack) {
expect(image.colorModel).toBe(data.colorModel);
expect(image.bitDepth).toBe(data.bitDepth);
}
});

test('invalid data format', () => {
const buffer = testUtils.loadBuffer('formats/grey8.png');
expect(() => decodeStack(buffer)).toThrow('invalid data format: image/png');
});
26 changes: 26 additions & 0 deletions src/stack/load/decodeStack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import imageType from 'image-type';

import { Stack } from '../../Stack';

import { decodeStackFromTiff } from './decodeTiff';

/**
* Decode input data and create stack. Data format is automatically detected.
* Possible formats: tiff.
* @param data - Data to decode.
* @returns The decoded image.
*/
export function decodeStack(data: ArrayBufferView): Stack {
const typedArray = new Uint8Array(
data.buffer,
data.byteOffset,
data.byteLength,
);
const type = imageType(typedArray);
switch (type?.mime) {
case 'image/tiff':
return decodeStackFromTiff(typedArray);
default:
throw new RangeError(`invalid data format: ${type?.mime}`);
}
}
19 changes: 19 additions & 0 deletions src/stack/load/decodeTiff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { decode } from 'tiff';

import { Stack } from '../../Stack';
import { getImageFromIFD } from '../../load/decodeTiff';

/**
* Decode a TIFF and create a stack of images.
* @param buffer - The data to decode.
* @returns The stack of images.
*/
export function decodeStackFromTiff(buffer: Uint8Array): Stack {
const decoded = decode(buffer);
const images = [];
for (const IFD of decoded) {
images.push(getImageFromIFD(IFD));
}

return new Stack(images);
}
4 changes: 4 additions & 0 deletions test/TestImagePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export type TestImagePath =
| 'formats/tif/greya32.tif'
| 'formats/tif/rgb16.tif'
| 'formats/tif/rgba8.tif'
| 'formats/tif/grey8-multi.tif'
| 'formats/tif/grey16-multi.tif'
| 'formats/tif/rgb16-multi.tif'
| 'formats/tif/rgba8-multi.tif'
| 'formats/tif/palette.tif'
| 'opencv/test.png'
| 'opencv/testBlur.png'
Expand Down
Binary file added test/img/formats/tif/color16-multi.tif
Binary file not shown.
Binary file added test/img/formats/tif/color8-multi.tif
Binary file not shown.
Binary file added test/img/formats/tif/grey16-multi.tif
Binary file not shown.
Binary file added test/img/formats/tif/grey8-multi.tif
Binary file not shown.

0 comments on commit 69f1649

Please sign in to comment.