Skip to content

Commit

Permalink
feat(image-io): Add readImageNode to package
Browse files Browse the repository at this point in the history
  • Loading branch information
thewtex committed Oct 8, 2023
1 parent d4131e5 commit d52c46f
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 21 deletions.
73 changes: 73 additions & 0 deletions packages/image-io/typescript/src/image-io-index-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import pngReadImageNode from './png-read-image-node.js'
import pngWriteImageNode from './png-write-image-node.js'
import metaReadImageNode from './meta-read-image-node.js'
import metaWriteImageNode from './meta-write-image-node.js'
import tiffReadImageNode from './tiff-read-image-node.js'
import tiffWriteImageNode from './tiff-write-image-node.js'
import niftiReadImageNode from './nifti-read-image-node.js'
import niftiWriteImageNode from './nifti-write-image-node.js'
import jpegReadImageNode from './jpeg-read-image-node.js'
import jpegWriteImageNode from './jpeg-write-image-node.js'
import nrrdReadImageNode from './nrrd-read-image-node.js'
import nrrdWriteImageNode from './nrrd-write-image-node.js'
import vtkReadImageNode from './vtk-read-image-node.js'
import vtkWriteImageNode from './vtk-write-image-node.js'
import bmpReadImageNode from './bmp-read-image-node.js'
import bmpWriteImageNode from './bmp-write-image-node.js'
import hdf5ReadImageNode from './hdf5-read-image-node.js'
import hdf5WriteImageNode from './hdf5-write-image-node.js'
import mincReadImageNode from './minc-read-image-node.js'
import mincWriteImageNode from './minc-write-image-node.js'
import mrcReadImageNode from './mrc-read-image-node.js'
import mrcWriteImageNode from './mrc-write-image-node.js'
import lsmReadImageNode from './lsm-read-image-node.js'
import lsmWriteImageNode from './lsm-write-image-node.js'
import mghReadImageNode from './mgh-read-image-node.js'
import mghWriteImageNode from './mgh-write-image-node.js'
import bioRadReadImageNode from './bio-rad-read-image-node.js'
import bioRadWriteImageNode from './bio-rad-write-image-node.js'
import giplReadImageNode from './gipl-read-image-node.js'
import giplWriteImageNode from './gipl-write-image-node.js'
import geAdwReadImageNode from './ge-adw-read-image-node.js'
import geAdwWriteImageNode from './ge-adw-write-image-node.js'
import ge4ReadImageNode from './ge4-read-image-node.js'
import ge4WriteImageNode from './ge4-write-image-node.js'
import ge5ReadImageNode from './ge5-read-image-node.js'
import ge5WriteImageNode from './ge5-write-image-node.js'
import gdcmReadImageNode from './gdcm-read-image-node.js'
import gdcmWriteImageNode from './gdcm-write-image-node.js'
import scancoReadImageNode from './scanco-read-image-node.js'
import scancoWriteImageNode from './scanco-write-image-node.js'
import fdfReadImageNode from './fdf-read-image-node.js'
import wasmReadImageNode from './wasm-read-image-node.js'
import wasmWriteImageNode from './wasm-write-image-node.js'
import wasmZstdReadImageNode from './wasm-zstd-read-image-node.js'
import wasmZstdWriteImageNode from './wasm-zstd-write-image-node.js'

const imageIoIndexNode = new Map([
['png', [pngReadImageNode, pngWriteImageNode]],
['meta', [metaReadImageNode, metaWriteImageNode]],
['tiff', [tiffReadImageNode, tiffWriteImageNode]],
['nifti', [niftiReadImageNode, niftiWriteImageNode]],
['jpeg', [jpegReadImageNode, jpegWriteImageNode]],
['nrrd', [nrrdReadImageNode, nrrdWriteImageNode]],
['vtk', [vtkReadImageNode, vtkWriteImageNode]],
['bmp', [bmpReadImageNode, bmpWriteImageNode]],
['hdf5', [hdf5ReadImageNode, hdf5WriteImageNode]],
['minc', [mincReadImageNode, mincWriteImageNode]],
['mrc', [mrcReadImageNode, mrcWriteImageNode]],
['lsm', [lsmReadImageNode, lsmWriteImageNode]],
['mgh', [mghReadImageNode, mghWriteImageNode]],
['bioRad', [bioRadReadImageNode, bioRadWriteImageNode]],
['gipl', [giplReadImageNode, giplWriteImageNode]],
['geAdw', [geAdwReadImageNode, geAdwWriteImageNode]],
['ge4', [ge4ReadImageNode, ge4WriteImageNode]],
['ge5', [ge5ReadImageNode, ge5WriteImageNode]],
['gdcm', [gdcmReadImageNode, gdcmWriteImageNode]],
['scanco', [scancoReadImageNode, scancoWriteImageNode]],
['fdf', [fdfReadImageNode, null]],
['wasm', [wasmReadImageNode, wasmWriteImageNode]],
['wasmZstd', [wasmZstdReadImageNode, wasmZstdWriteImageNode]]
])

export default imageIoIndexNode
75 changes: 73 additions & 2 deletions packages/image-io/typescript/src/image-io-index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,74 @@
const ImageIOIndex = ['png', 'meta', 'tiff', 'nifti', 'jpeg', 'nrrd', 'vtk', 'bmp', 'hdf5', 'minc', 'mrc', 'lsm', 'mgh', 'bio-rad', 'gipl', 'ge-adw', 'ge4', 'ge5', 'gdcm', 'scanco', 'fdf', 'wasm', 'wasm-zstd', ]
import pngReadImage from './png-read-image.js'
import pngWriteImage from './png-write-image.js'
import metaReadImage from './meta-read-image.js'
import metaWriteImage from './meta-write-image.js'
import tiffReadImage from './tiff-read-image.js'
import tiffWriteImage from './tiff-write-image.js'
import niftiReadImage from './nifti-read-image.js'
import niftiWriteImage from './nifti-write-image.js'
import jpegReadImage from './jpeg-read-image.js'
import jpegWriteImage from './jpeg-write-image.js'
import nrrdReadImage from './nrrd-read-image.js'
import nrrdWriteImage from './nrrd-write-image.js'
import vtkReadImage from './vtk-read-image.js'
import vtkWriteImage from './vtk-write-image.js'
import bmpReadImage from './bmp-read-image.js'
import bmpWriteImage from './bmp-write-image.js'
import hdf5ReadImage from './hdf5-read-image.js'
import hdf5WriteImage from './hdf5-write-image.js'
import mincReadImage from './minc-read-image.js'
import mincWriteImage from './minc-write-image.js'
import mrcReadImage from './mrc-read-image.js'
import mrcWriteImage from './mrc-write-image.js'
import lsmReadImage from './lsm-read-image.js'
import lsmWriteImage from './lsm-write-image.js'
import mghReadImage from './mgh-read-image.js'
import mghWriteImage from './mgh-write-image.js'
import bioRadReadImage from './bio-rad-read-image.js'
import bioRadWriteImage from './bio-rad-write-image.js'
import giplReadImage from './gipl-read-image.js'
import giplWriteImage from './gipl-write-image.js'
import geAdwReadImage from './ge-adw-read-image.js'
import geAdwWriteImage from './ge-adw-write-image.js'
import ge4ReadImage from './ge4-read-image.js'
import ge4WriteImage from './ge4-write-image.js'
import ge5ReadImage from './ge5-read-image.js'
import ge5WriteImage from './ge5-write-image.js'
import gdcmReadImage from './gdcm-read-image.js'
import gdcmWriteImage from './gdcm-write-image.js'
import scancoReadImage from './scanco-read-image.js'
import scancoWriteImage from './scanco-write-image.js'
import fdfReadImage from './fdf-read-image.js'
import wasmReadImage from './wasm-read-image.js'
import wasmWriteImage from './wasm-write-image.js'
import wasmZstdReadImage from './wasm-zstd-read-image.js'
import wasmZstdWriteImage from './wasm-zstd-write-image.js'

const imageIoIndex = new Map([
['png', [pngReadImage, pngWriteImage]],
['meta', [metaReadImage, metaWriteImage]],
['tiff', [tiffReadImage, tiffWriteImage]],
['nifti', [niftiReadImage, niftiWriteImage]],
['jpeg', [jpegReadImage, jpegWriteImage]],
['nrrd', [nrrdReadImage, nrrdWriteImage]],
['vtk', [vtkReadImage, vtkWriteImage]],
['bmp', [bmpReadImage, bmpWriteImage]],
['hdf5', [hdf5ReadImage, hdf5WriteImage]],
['minc', [mincReadImage, mincWriteImage]],
['mrc', [mrcReadImage, mrcWriteImage]],
['lsm', [lsmReadImage, lsmWriteImage]],
['mgh', [mghReadImage, mghWriteImage]],
['bioRad', [bioRadReadImage, bioRadWriteImage]],
['gipl', [giplReadImage, giplWriteImage]],
['geAdw', [geAdwReadImage, geAdwWriteImage]],
['ge4', [ge4ReadImage, ge4WriteImage]],
['ge5', [ge5ReadImage, ge5WriteImage]],
['gdcm', [gdcmReadImage, gdcmWriteImage]],
['scanco', [scancoReadImage, scancoWriteImage]],
['fdf', [fdfReadImage, null]],
['wasm', [wasmReadImage, wasmWriteImage]],
['wasmZstd', [wasmZstdReadImage, wasmZstdWriteImage]]
])

export default imageIoIndex

export default ImageIOIndex
5 changes: 4 additions & 1 deletion packages/image-io/typescript/src/index-node.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Generated file. To retain edits, remove this comment.

import ReadImageOptions from './read-image-options.js'
export type { ReadImageOptions }

import readImageNode from './read-image-node.js'
export { readImageNode }

import BioRadReadImageNodeResult from './bio-rad-read-image-node-result.js'
export type { BioRadReadImageNodeResult }
Expand Down
18 changes: 9 additions & 9 deletions packages/image-io/typescript/src/mime-to-image-io.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const mimeToIO = new Map([
['image/jpeg', 'JPEGImageIO'],
['image/png', 'PNGImageIO'],
['image/tiff', 'TIFFImageIO'],
['image/x-ms-bmp', 'BMPImageIO'],
['image/x-bmp', 'BMPImageIO'],
['image/bmp', 'BMPImageIO'],
['application/dicom', 'GDCMImageIO']
const mimeToImageIo = new Map([
['image/jpeg', 'jpeg'],
['image/png', 'png'],
['image/tiff', 'tiff'],
['image/x-ms-bmp', 'bmp'],
['image/x-bmp', 'bmp'],
['image/bmp', 'bmp'],
['application/dicom', 'gdcm']
])

export default mimeToIO
export default mimeToImageIo
76 changes: 76 additions & 0 deletions packages/image-io/typescript/src/read-image-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import path from 'path'
import mime from 'mime-types'

import {
Image,
getFileExtension,
castImage,
} from 'itk-wasm'

import mimeToImageIo from './mime-to-image-io.js'
import extensionToImageIo from './extension-to-image-io.js'
import imageIoIndexNode from './image-io-index-node.js'

import ReadImageOptions from './read-image-options.js'

interface ReaderResult {
couldRead: boolean,
image: Image
}
type Reader = (serializedImage: string) => Promise<ReaderResult>


/**
* Read an image file format and convert it to the itk-wasm file format
*
* @param {string} serializedImage - Path to input image serialized in the file format
* @param {ReadImageOptions} options - options to cast resulting image type
*
* @returns {Promise<Image>} - Image result
*/
async function readImageNode(
serializedImage: string,
options: ReadImageOptions = {}
) : Promise<Image> {

const absoluteFilePath = path.resolve(serializedImage)
const mimeType = mime.lookup(absoluteFilePath)
const extension = getFileExtension(absoluteFilePath)

let io = null
if (mimeType !== false && mimeToImageIo.has(mimeType)) {
io = mimeToImageIo.get(mimeType)
} else if (extensionToImageIo.has(extension)) {
io = extensionToImageIo.get(extension)
} else {
for (const readerWriter of imageIoIndexNode.values()) {
if (readerWriter[0] !== null) {
let { couldRead, image } = await (readerWriter[0] as Reader)(absoluteFilePath)
if (couldRead) {
if (typeof options !== 'undefined') {
image = castImage(image, options)
}
return image
}
}
}
}
if (io === null ) {
throw Error('Could not find IO for: ' + absoluteFilePath)
}
const readerWriter = imageIoIndexNode.get(io as string)

const reader = (readerWriter as Array<Reader>)[0]
let { couldRead, image } = await reader(absoluteFilePath)
if (!couldRead) {
throw Error('Could not read: ' + absoluteFilePath)
}

if (typeof options !== 'undefined') {
image = castImage(image, options)
}

return image
}

export default readImageNode
11 changes: 11 additions & 0 deletions packages/image-io/typescript/src/read-image-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IntTypes, FloatTypes, PixelTypes } from 'itk-wasm'

interface ReadImageOptions {
/** Component type, from itk-wasm IntTypes, FloatTypes, for the output pixel components. Defaults to the input component type. */
componentType?: typeof IntTypes[keyof typeof IntTypes] | typeof FloatTypes[keyof typeof FloatTypes]

/** Pixel type, from itk-wasm PixelTypes, for the output pixels. Defaults to the input pixel type. */
pixelType?: typeof PixelTypes[keyof typeof PixelTypes]
}

export default ReadImageOptions
17 changes: 17 additions & 0 deletions packages/image-io/typescript/src/read-image-result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated file. To retain edits, remove this comment.

import { JsonCompatible, Image } from 'itk-wasm'

interface MetaReadImageResult {
/** WebWorker used for computation */
webWorker: Worker | null

/** Whether the input could be read. If false, the output image is not valid. */
couldRead: JsonCompatible

/** Output image */
image: Image

}

export default MetaReadImageResult
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import test from 'ava'
import path from 'path'

import { IntTypes, PixelTypes, getMatrixElement, readImageLocalFile } from '../../../../dist/index.js'
import { readImageNode } from '../../dist/bundles/image-io-node.js'
import { IntTypes, PixelTypes, getMatrixElement } from 'itk-wasm'

const testFilePath = path.resolve('build-emscripten', 'ExternalData', 'test', 'Input', 'cthead1.png')
import { testInputPath, testOutputPath } from './common.js'

const testInputFilePath = path.join(testInputPath, 'cthead1.png')

function verifyImage (t, image, componentType, pixelType) {
t.is(image.imageType.dimension, 2)
Expand All @@ -23,23 +26,23 @@ function verifyImage (t, image, componentType, pixelType) {
t.is(image.data.length, 196608)
}

test('readImageLocalFile reads a file path given on the local filesystem', async t => {
const image = await readImageLocalFile(testFilePath)
test('Test reading a PNG with readImageNode file', async t => {
const image = await readImageNode(testInputFilePath)
const componentType = IntTypes.UInt8
const pixelType = PixelTypes.RGB
verifyImage(t, image, componentType, pixelType)
})

test('readImageLocalFile casts to the specified componentType', async t => {
test('Test reading a PNG with readImageNode file cast to the specified componentType', async t => {
const componentType = IntTypes.UInt16
const image = await readImageLocalFile(testFilePath, { componentType })
const image = await readImageNode(testInputFilePath, { componentType })
const pixelType = PixelTypes.RGB
verifyImage(t, image, componentType, pixelType)
})

test('readImageLocalFile casts to the specified pixelType', async t => {
test('Test reading a PNG with readImageNode file cast to the specified pixelType', async t => {
const pixelType = PixelTypes.Vector
const image = await readImageLocalFile(testFilePath, { pixelType })
const image = await readImageNode(testInputFilePath, { pixelType })
const componentType = IntTypes.UInt8
verifyImage(t, image, componentType, pixelType)
})
})
Loading

0 comments on commit d52c46f

Please sign in to comment.