Skip to content

Commit

Permalink
feat(image-io): add writeImage function
Browse files Browse the repository at this point in the history
  • Loading branch information
thewtex committed Oct 10, 2023
1 parent 9983599 commit 8b8de3e
Show file tree
Hide file tree
Showing 44 changed files with 499 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as compareImages from '../../../dist/bundles/compare-images.js'
import compareDoubleImagesLoadSampleInputs, { usePreRun } from "./compare-double-images-load-sample-inputs.js"

class CompareDoubleImagesModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -17,10 +16,10 @@ class CompareDoubleImagesModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class CompareDoubleImagesController {
class CompareDoubleImagesController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as compareImages from '../../../dist/bundles/compare-images.js'
import vectorMagnitudeLoadSampleInputs, { usePreRun } from "./vector-magnitude-load-sample-inputs.js"

class VectorMagnitudeModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -17,10 +16,10 @@ class VectorMagnitudeModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class VectorMagnitudeController {
class VectorMagnitudeController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as compressStringify from '../../../dist/bundles/compress-stringify.js'
import compressStringifyLoadSampleInputs, { usePreRun } from "./compress-stringify-load-sample-inputs.js"

class CompressStringifyModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -14,10 +13,10 @@ class CompressStringifyModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class CompressStringifyController {
class CompressStringifyController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as compressStringify from '../../../dist/bundles/compress-stringify.js'
import parseStringDecompressLoadSampleInputs, { usePreRun } from "./parse-string-decompress-load-sample-inputs.js"

class ParseStringDecompressModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -14,10 +13,10 @@ class ParseStringDecompressModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class ParseStringDecompressController {
class ParseStringDecompressController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as dicom from '../../../dist/bundles/dicom.js'
import applyPresentationStateToImageLoadSampleInputs, { usePreRun } from "./apply-presentation-state-to-image-load-sample-inputs.js"

class ApplyPresentationStateToImageModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -16,10 +15,10 @@ class ApplyPresentationStateToImageModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class ApplyPresentationStateToImageController {
class ApplyPresentationStateToImageController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as dicom from '../../../dist/bundles/dicom.js'
import readDicomTagsLoadSampleInputs, { usePreRun } from "./read-dicom-tags-load-sample-inputs.js"

class ReadDicomTagsModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -14,10 +13,10 @@ class ReadDicomTagsModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class ReadDicomTagsController {
class ReadDicomTagsController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as dicom from '../../../dist/bundles/dicom.js'
import structuredReportToTextLoadSampleInputs, { usePreRun } from "./structured-report-to-text-load-sample-inputs.js"

class StructuredReportToTextModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>
Expand All @@ -14,10 +13,10 @@ class StructuredReportToTextModel {
this.options = new Map()
this.outputs = new Map()
}
}
}


class StructuredReportToTextController {
class StructuredReportToTextController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs
Expand Down
8 changes: 4 additions & 4 deletions packages/image-io/typescript/cypress/e2e/read-image.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('read-image', () => {
})
})

it('Reads an image File in the dem', function () {
it('Reads an image File in the demo', function () {
cy.get('sl-tab[panel="readImage-panel"]').click()

const testFile = { contents: new Uint8Array(this['cthead1.png']), fileName: 'cthead1.png' }
Expand Down Expand Up @@ -97,11 +97,11 @@ describe('read-image', () => {
})
})

it('Throws a catchable error for an invalid file', function () {
it('Throws a catchable error for an invalid file', { defaultCommandTimeout: 120000 }, function () {
cy.window().then(async (win) => {
const invalidArray = new Uint8Array([21, 4, 4, 4, 4, 9, 5, 0, 82, 42])
const invalidBlob = new window.Blob([invalidArray])
const invalidFile = new window.File([invalidBlob], 'invalid.file')
const invalidBlob = new win.Blob([invalidArray])
const invalidFile = new win.File([invalidBlob], 'invalid.file')
try {
const { webWorker, image } = await win.imageIo.readImage(null, invalidFile)
webWorker.terminate()
Expand Down
96 changes: 96 additions & 0 deletions packages/image-io/typescript/cypress/e2e/write-image.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { demoServer } from './common.ts'

import { IntTypes, PixelTypes } from 'itk-wasm'

const cthead1SmallBase64DataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfhBQYVKw8AZTNIAAADdklEQVQ4y2WTa2wUVRiGp6W7O3POnLmc2VrstokJlrBIUBJigjfSICVCCAo/QKM/FFNRIESJQKAws3M7M2f20t3GthRKQQq0kkoXMIq9oFwCXkg0UpMakGLgR9EmJF4TNOvZhRBb31+TvM955/vO+T6Ou69pAgSwKCCAEPc/lYUhFEUkMgH2ESmbYocEEUmKLIQqBKmEgUlERQhAPhyJiDMXPFZZDmRGoP8Q5TwC4ciMpatfXE9zmT2NVRVIQiLi76cDUVRDT/m72zLUc/Srv+gNCi8jhCrupvMAQIWf1zJx58pRj7g7h/sduunhiIIkUAJ4AUBZ0LZev3TondmeS42TuaYms6kOapJUalYQAAKxt+j4qD3yxvMZ0z47NLi/ydhWA7GMinWyAH6G1Wwe/OdUz6dz33T35dPdIxdIYrPGK0qxTnYrobVtjm+3pNvPxGu9/dTRgw8/e89et0AKF1uFItS2u7ZP7fr4K3H19VbP94me/T6fXRifM6+a/QKC6N5+PWGYZhVeNn9pzvUoTVnt3/QEz81dUTONgwjis4UzvS2Z5JbY9JlPdxmEuFZzX9va0yu5WlXmRAlWd3Tmjg980vXBprJZbYPtza0dXw40ZleeP1ZbrWKOXXpsu7Grb3gnsY/27B46+e3ElVuF3w+sm7Pki2VAUxkAo1t0a7TL8YnVPZxy6KG9fX/+2qu/+9DARoAVBiDYaHjnfc/3nHOdicA1Em6WpnOdG/I6zwCA5PCzrn6uw6VO99gBnRBKGUyIMfz3BgmrHHta8cEdu04dN6wjPwy6FinaTNT8emKNzGrgBEmJLLf7T6Tf/60wpFP2oKToB/bNr+pVTWHjghQxZuTzW51C4aIZENdj8gMv+1f3I7iYwPEqrFu+z1/zzI3vHN/ziEd9P0haV39aXxXFRaBMRrCu9Vjj5o/S5C4QBCnjws+pJ9SoqpZmRlqyeNWlPa922El22PMCl5if38q9FGV+CeAaFuK4OZY5nLRoksnsPX19nL5do2GsREoAlCtr68lo4VoXNROWdXD8j7GUNV96AMPye5MtYgU/ujF/887tHy+PXLt9o9/asUipvDfWpc1QNFWKPfla8PHI5Ysnsua2l2dH1Un7WS6rKlamxx9f/MKKhkX1syoxmLqcUMVRDTNMlZGkilPsUrOsJ6wxRSel/wuAkzbenLRf4gAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wNS0wNlQxNzoyNjozNC0wNDowMORO/MMAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDUtMDZUMTc6MjY6MzQtMDQ6MDCVE0R/AAAAAElFTkSuQmCC'
const byteString = window.atob(cthead1SmallBase64DataURI.split(',')[1])
const mimeString = cthead1SmallBase64DataURI.split(',')[0].split(':')[1].split(';')[0]
const intArray = new Uint8Array(byteString.length)
for (let ii = 0; ii < byteString.length; ++ii) {
intArray[ii] = byteString.charCodeAt(ii)
}
const cthead1SmallBlob = new window.Blob([intArray], { type: mimeString })

function verifyImage (image, componentType, pixelType) {
cy.expect(image.imageType.dimension).to.equal(2)
cy.expect(image.imageType.componentType).to.equal(componentType)
cy.expect(image.imageType.pixelType).to.equal(pixelType)
cy.expect(image.imageType.components).to.equal(1)
cy.expect(image.origin[0]).to.equal(0.0)
cy.expect(image.origin[1]).to.equal(0.0)
cy.expect(image.spacing[0]).to.equal(1.0)
cy.expect(image.spacing[1]).to.equal(1.0)
cy.expect(image.size[0]).to.equal(32)
cy.expect(image.size[1]).to.equal(32)
cy.expect(image.data.length).to.equal(1024)
cy.expect(image.data[512]).to.equal(12)
}

describe('write-image', () => {
beforeEach(function() {
cy.visit(demoServer)

const testPathPrefix = '../test/data/input/'

const testImageFiles = [
'cthead1.iwi.cbor'
]
testImageFiles.forEach((fileName) => {
cy.readFile(`${testPathPrefix}${fileName}`, null).as(fileName)
})
})

it('Writes an image in the demo', function () {
cy.get('sl-tab[panel="writeImage-panel"]').click()

const testFile = { contents: new Uint8Array(this['cthead1.iwi.cbor']), fileName: 'cthead1.iwi.cbor' }
cy.get('#writeImageInputs input[name="image-file"]').selectFile([testFile,], { force: true })
cy.get('#writeImage-image-details').should('contain', 'imageType')
cy.get('#writeImageInputs sl-input[name="serialized-image"]').find('input', { includeShadowDom: true }).type('cthead1.png', { force: true })

cy.get('#writeImageInputs sl-button[name="run"]').click()

cy.get('#writeImage-serialized-image-details').should('contain', '0,3')
})

it('Writes an image to an ArrayBuffer', function () {
cy.window().then(async (win) => {
const arrayBuffer = await cthead1SmallBlob.arrayBuffer()
const { image, webWorker } = await win.imageIo.readImage(null, { data: new Uint8Array(arrayBuffer), path: 'cthead1Small.png' })
const { serializedImage } = await win.imageIo.writeImage(webWorker, image, 'cthead1.mha')
const { image: imageBack } = await win.imageIo.readImage(webWorker, serializedImage)
webWorker.terminate()
const componentType = IntTypes.UInt8
const pixelType = PixelTypes.Scalar
verifyImage(imageBack, componentType, pixelType)
})
})

it('Writes an image to an ArrayBuffer, given componentType, pixelType', function () {
cy.window().then(async (win) => {
const componentType = IntTypes.UInt16
const pixelType = PixelTypes.Vector
const arrayBuffer = await cthead1SmallBlob.arrayBuffer()
const { image, webWorker } = await win.imageIo.readImage(null, { data: new Uint8Array(arrayBuffer), path: 'cthead1Small.png' })
const { serializedImage } = await win.imageIo.writeImage(webWorker, image, 'cthead1.mha', { pixelType, componentType})
// Reading back, the pixelType is always Scalar (reader behavior). Is this a bug?
const { image: imageBack } = await win.imageIo.readImage(webWorker, serializedImage, { pixelType })
webWorker.terminate()
verifyImage(imageBack, componentType, pixelType)
})
})

it('Writes an image to an ArrayBuffer, uses compression', function () {
cy.window().then(async (win) => {
const arrayBuffer = await cthead1SmallBlob.arrayBuffer()
const { image, webWorker } = await win.imageIo.readImage(null, { data: new Uint8Array(arrayBuffer), path: 'cthead1Small.png' })
const options = { useCompression: false }
const { serializedImage } = await win.imageIo.writeImage(webWorker, image, 'cthead1.mha', options)
const { image: imageBack } = await win.imageIo.readImage(webWorker, serializedImage)
webWorker.terminate()
const componentType = IntTypes.UInt8
const pixelType = PixelTypes.Scalar
verifyImage(imageBack, componentType, pixelType)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface BioRadWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface BmpWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface FdfWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface GdcmWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface GeAdwWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface Ge4WriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface Ge5WriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface GiplWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface Hdf5WriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
9 changes: 9 additions & 0 deletions packages/image-io/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ export type { ReadImageResult }
import readImage from './read-image.js'
export { readImage }

import WriteImageOptions from './write-image-options.js'
export type { WriteImageOptions }

import WriteImageResult from './write-image-result.js'
export type { WriteImageResult }

import writeImage from './write-image.js'
export { writeImage }

import BioRadReadImageResult from './bio-rad-read-image-result.js'
export type { BioRadReadImageResult }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface JpegWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface LsmWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated file. To retain edits, remove this comment.

interface MetaWriteImageOptions {
/** Only read image metadata -- do not read pixel data. */
/** Only write image metadata -- do not write pixel data. */
informationOnly?: boolean

/** Use compression in the written file */
Expand Down
Loading

0 comments on commit 8b8de3e

Please sign in to comment.