Skip to content

Commit

Permalink
ENH: App initial import import from @itk-wasm/compress-stringify test
Browse files Browse the repository at this point in the history
  • Loading branch information
thewtex committed Jul 27, 2023
1 parent c7352ec commit a288ef2
Show file tree
Hide file tree
Showing 17 changed files with 1,538 additions and 0 deletions.
3 changes: 3 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
public/
dist/
118 changes: 118 additions & 0 deletions app/compress-stringify-controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Generated file. To retain edits, remove this comment.

import * as compressStringify from '../../../dist/bundles/compress-stringify.js'
import compressStringifyLoadSampleInputs from "./compress-stringify-load-sample-inputs.js"

class CompressStringifyModel {

inputs: Map<string, any>
options: Map<string, any>
outputs: Map<string, any>

constructor() {
this.inputs = new Map()
this.options = new Map()
this.outputs = new Map()
}
}


class CompressStringifyController {

constructor(loadSampleInputs) {
this.loadSampleInputs = loadSampleInputs

this.model = new CompressStringifyModel()
const model = this.model

this.webWorker = null

if (loadSampleInputs) {
const loadSampleInputsButton = document.querySelector("#compressStringifyInputs [name=loadSampleInputs]")
loadSampleInputsButton.setAttribute('style', 'display: block-inline;')
loadSampleInputsButton.addEventListener('click', (event) => {
loadSampleInputs(model)
})
}

// ----------------------------------------------
// Inputs
const inputElement = document.querySelector('#compressStringifyInputs input[name=input-file]')
inputElement.addEventListener('change', (event) => {
const dataTransfer = event.dataTransfer
const files = event.target.files || dataTransfer.files

files[0].arrayBuffer().then((arrayBuffer) => {
model.inputs.set("input", new Uint8Array(arrayBuffer))
const input = document.querySelector("#compressStringifyInputs sl-input[name=input]")
input.value = model.inputs.get("input").toString().substring(0, 50) + ' ...'
})
})

// ----------------------------------------------
// Options
const stringifyElement = document.querySelector('#compressStringifyInputs sl-checkbox[name=stringify]')
stringifyElement.addEventListener('sl-change', (event) => {
model.options.set("stringify", stringifyElement.checked)
})

const compressionLevelElement = document.querySelector('#compressStringifyInputs sl-input[name=compression-level]')
compressionLevelElement.addEventListener('sl-change', (event) => {
model.options.set("compressionLevel", parseInt(compressionLevelElement.value))
})

const dataUrlPrefixElement = document.querySelector('#compressStringifyInputs sl-input[name=data-url-prefix]')
dataUrlPrefixElement.addEventListener('sl-change', (event) => {
model.options.set("dataUrlPrefix", dataUrlPrefixElement.value)
})

// ----------------------------------------------
// Outputs
const outputOutputDownload = document.querySelector('#compressStringifyOutputs sl-button[name=output-download]')
outputOutputDownload.addEventListener('click', (event) => {
event.preventDefault()
event.stopPropagation()
if (model.outputs.has("output")) {
globalThis.downloadFile(model.outputs.get("output"), "output.bin")
}
})

const runButton = document.querySelector('#compressStringifyInputs sl-button[name="run"]')
runButton.addEventListener('click', async (event) => {
event.preventDefault()

if(!model.inputs.has('input')) {
globalThis.notify("Required input not provided", "input", "danger", "exclamation-octagon")
return
}


try {
runButton.loading = true
const t0 = performance.now()

const { webWorker, output } = await compressStringify.compressStringify(this.webWorker,
model.inputs.get('input').slice(),
Object.fromEntries(model.options.entries())
)

const t1 = performance.now()
globalThis.notify("compressStringify successfully completed", `in ${t1 - t0} milliseconds.`, "success", "rocket-fill")
this.webWorker = webWorker

model.outputs.set("output", output)
outputOutputDownload.variant = "success"
outputOutputDownload.disabled = false
const outputOutput = document.querySelector('#compressStringifyOutputs sl-textarea[name=output]')
outputOutput.value = output.toString().substring(0, 200) + ' ...'
} catch (error) {
globalThis.notify("Error while running pipeline", error.toString(), "danger", "exclamation-octagon")
throw error
} finally {
runButton.loading = false
}
})
}
}

const compressStringifyController = new CompressStringifyController(compressStringifyLoadSampleInputs)
21 changes: 21 additions & 0 deletions app/compress-stringify-load-sample-inputs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export default function compressStringifyLoadSampleInputs (context) {
const sampleInput = new Uint8Array([222, 173, 190, 239])
context.inputs.set("input", sampleInput)
const inputElement = document.querySelector("#compressStringifyInputs [name=input]")
inputElement.value = sampleInput.toString()

const stringify = true
context.options.set("stringify", stringify)
const stringifyElement = document.querySelector('#compressStringifyInputs sl-checkbox[name=stringify]')
stringifyElement.checked = stringify

const compressionLevel = 5
context.options.set("compressionLevel", compressionLevel)
const compressionLevelElement = document.querySelector('#compressStringifyInputs sl-input[name=compression-level]')
compressionLevelElement.value = compressionLevel

const dataUrlPrefix = 'data:application/iwi+cbor+zstd;base64,'
context.options.set("dataUrlPrefix", dataUrlPrefix)
const dataUrlPrefixElement = document.querySelector('#compressStringifyInputs sl-input[name=data-url-prefix]')
dataUrlPrefixElement.value = dataUrlPrefix
}
Empty file added app/converter-controller.ts
Empty file.
118 changes: 118 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<!-- Generated file. To retain edits, remove this comment. -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />

<script type="module">
import '@shoelace-style/shoelace/dist/themes/light.css';
import '@shoelace-style/shoelace/dist/themes/dark.css';
import '@shoelace-style/shoelace/dist/components/button/button.js';
import '@shoelace-style/shoelace/dist/components/tab-group/tab-group.js';
import '@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js';
import '@shoelace-style/shoelace/dist/components/tab/tab.js';
import '@shoelace-style/shoelace/dist/components/input/input.js';
import '@shoelace-style/shoelace/dist/components/checkbox/checkbox.js';
import '@shoelace-style/shoelace/dist/components/textarea/textarea.js';
import '@shoelace-style/shoelace/dist/components/alert/alert.js';
import '@shoelace-style/shoelace/dist/components/icon/icon.js';
import '@shoelace-style/shoelace/dist/components/divider/divider.js';

import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
setBasePath('/');

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
// dark mode
document.documentElement.classList.add('sl-theme-dark');
}
</script>

<title>@itk-wasm/compress-stringify<img src="./javascript-logo.svg" alt="JavaScript logo" class="language-logo"/><img src="./typescript-logo.svg" alt="TypeScript logo" class="language-logo"/></title>
</head>
<body>

<script src="./utilities.js"></script>

<!-- https://tholman.com/github-corners/ -->
<a href="https://github.com/InsightSoftwareConsortium/itk-wasm" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>

<div id="app">
<a href="https://wasm.itk.org/" target="_blank">
<img src="./logo.svg" class="logo vanilla" alt="ITK Wasm logo" />
</a>

<h2>@itk-wasm/compress-stringify<img src="./javascript-logo.svg" alt="JavaScript logo" class="language-logo"/><img src="./typescript-logo.svg" alt="TypeScript logo" class="language-logo"/></h2>
<i>Zstandard compression and decompression and base64 encoding and decoding in WebAssembly.</i>
<br /><br />

<sl-tab-group>
<sl-tab slot="nav" panel="compressStringify-panel">compressStringify</sl-tab>
<sl-tab slot="nav" panel="parseStringDecompress-panel">parseStringDecompress</sl-tab>


<sl-tab-panel name="compressStringify-panel">

<small><i>Given a binary, compress and optionally base64 encode.</i></small><br /><br />

<div id="compressStringifyInputs"><form action="">
<sl-input required name="input" type="text" label="input" help-text="Input binary" disabled></sl-input>
<label for="input-file"><sl-button required variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sl-button></label><input type="file" name="input-file" style="display: none"/>
<br /><br />
<sl-checkbox name="stringify">stringify - <i>Stringify the output</i></sl-checkbox>
<br /><br />
<sl-input name="compression-level" type="number" value="3" label="compressionLevel" help-text="Compression level, typically 1-9"></sl-input>
<br />
<sl-input name="data-url-prefix" type="text" label="dataUrlPrefix" help-text="dataURL prefix"></sl-input>
<sl-divider></sl-divider>
<br /><sl-button name="loadSampleInputs" variant="default" style="display: none;">Load sample inputs</sl-button>
<sl-button type="button" variant="success" name="run">Run</sl-button><br /><br />

</form></div>
<sl-divider></sl-divider>

<div id="compressStringifyOutputs">
<sl-textarea name="output" label="output" help-text="Output compressed binary"><sl-skeleton effect="none"></sl-skeleton></sl-textarea>
<sl-button variant="neutral" outline name="output-download" disabled>Download</sl-button>
<br /><br />
</div>

</sl-tab-panel>


<sl-tab-panel name="parseStringDecompress-panel">

<small><i>Given a binary or string produced with compress-stringify, decompress and optionally base64 decode.</i></small><br /><br />

<div id="parseStringDecompressInputs"><form action="">
<sl-input required name="input" type="text" label="input" help-text="Compressed input" disabled></sl-input>
<label for="input-file"><sl-button required variant="primary" outline onclick="this.parentElement.nextElementSibling.click()">Upload</sl-button></label><input type="file" name="input-file" style="display: none"/>
<br /><br />
<sl-checkbox name="parse-string">parseString - <i>Parse the input string before decompression</i></sl-checkbox>
<br /><br />
<sl-divider></sl-divider>
<br /><sl-button name="loadSampleInputs" variant="default" style="display: none;">Load sample inputs</sl-button>
<sl-button type="button" variant="success" name="run">Run</sl-button><br /><br />

</form></div>
<sl-divider></sl-divider>

<div id="parseStringDecompressOutputs">
<sl-textarea name="output" label="output" help-text="Output decompressed binary"><sl-skeleton effect="none"></sl-skeleton></sl-textarea>
<sl-button variant="neutral" outline name="output-download" disabled>Download</sl-button>
<br /><br />
</div>

</sl-tab-panel>


</sl-tab-group>
</div>

<script type="module" src="./index.ts"></script>

</body>
</html>
10 changes: 10 additions & 0 deletions app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { readImageFile } from 'itk-wasm'

// Use local, vendored WebAssembly module assets
// const pipelinesBaseUrl: string | URL = new URL('/pipelines', document.location.origin).href
// compressStringify.setPipelinesBaseUrl(pipelinesBaseUrl)
// const pipelineWorkerUrl: string | URL | null = new URL('/web-workers/pipeline.worker.js', document.location.origin).href
// compressStringify.setPipelineWorkerUrl(pipelineWorkerUrl)

import './converter-controller.js'
// import './calibration-controller.js'
1 change: 1 addition & 0 deletions app/javascript-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "itk-io-scanco-app",
"version": "0.1.0",
"description": "Convert and calibrate Scanco microCT volume .isq and .aim files.",
"scripts": {
"start": "npm run copyShoelaceAssets && vite -c vite.config.js",
"test": "echo \"tests are not configured\" && exit 1",
"copyShoelaceAssets": "shx mkdir -p public/shoelace && shx cp -r node_modules/@shoelace-style/shoelace/dist/assets public/",
"build": "npm run copyShoelaceAssets && vite -c vite.config.js build"
},
"keywords": [
"itk",
"wasm",
"scanco",
"isq",
"aim",
"webassembly",
"wasi"
],
"author": "Matt McCormick <[email protected]>",
"license": "Apache-2.0",
"homepage": "https://github.com/KitwareMedical/ITKIOScanco#readme",
"dependencies": {
"itk-image-io": "1.0.0-b.119",
"itk-wasm": "1.0.0-b.119"
},
"devDependencies": {
"@shoelace-style/shoelace": "^2.5.2",
"@types/node": "^20.2.5",
"shx": "^0.3.4",
"vite": "^4.3.3",
"vite-plugin-static-copy": "^0.14.0"
},
"repository": {
"type": "git",
"url": "https://github.com/KitwareMedical/ITKIOScanco"
}
}
Loading

0 comments on commit a288ef2

Please sign in to comment.