diff --git a/docs/tutorial/_sidebar.md b/docs/tutorial/_sidebar.md index 8d43c28b0..4d4e186ca 100644 --- a/docs/tutorial/_sidebar.md +++ b/docs/tutorial/_sidebar.md @@ -3,7 +3,8 @@ - [Hello World!](/tutorial/hello_world) - [Hello Pipeline!](/tutorial/hello_pipeline) - - [Input/Output](/tutorial/inputs_outputs) + - [Pipeline Input/Output](/tutorial/pipeline_input_output) + - [Input/Output Types](/tutorial/input_output_types) - [Debugging](/tutorial/debugging) - [Examples](/examples/) diff --git a/docs/tutorial/hello_pipeline.md b/docs/tutorial/hello_pipeline.md index 8669ed436..b34a80a1b 100644 --- a/docs/tutorial/hello_pipeline.md +++ b/docs/tutorial/hello_pipeline.md @@ -2,7 +2,7 @@ Hello Pipeline World! ## Introduction -This example introduces the `itk::wasm::Pipeline`. An `itk::wasm::Pipeline` transforms elegant standalone C++ command line programs into powerful [WebAssembly](https://webassembly.org/) (Wasm) modules with a simple, efficient interface for execution in the browser, other programming languages, and on the command line. +This example introduces the `itk::wasm::Pipeline`. An `itk::wasm::Pipeline` transforms elegant standalone C++ command line programs into powerful [WebAssembly](https://webassembly.org/) (wasm) modules with a simple, efficient interface for execution in the browser, other programming languages, and on the command line. Make sure to complete the [Hello World!](/tutorial/hello_world) example before you start your Hello Pipeline adventure. diff --git a/docs/tutorial/input_output_types.md b/docs/tutorial/input_output_types.md new file mode 100644 index 000000000..c91c1095a --- /dev/null +++ b/docs/tutorial/input_output_types.md @@ -0,0 +1,7 @@ +# Input/Output Types + +## Introduction + +This tutorial section + +## Write the code \ No newline at end of file diff --git a/docs/tutorial/inputs_outputs.md b/docs/tutorial/pipeline_input_output.md similarity index 96% rename from docs/tutorial/inputs_outputs.md rename to docs/tutorial/pipeline_input_output.md index 1a542c5d6..40b5adcbc 100644 --- a/docs/tutorial/inputs_outputs.md +++ b/docs/tutorial/pipeline_input_output.md @@ -1,8 +1,8 @@ -# Pipeline Inputs and Outputs +# Pipeline Input/Output ## Introduction -This example dives deeper into `itk::wasm::Pipeline` image inputs and outputs and how they are handled. We will create a pipeline to smooth an image with a median filter, run the Wasm from the command line, in Node.js. +This tutorial section dives deeper into `itk::wasm::Pipeline` image inputs and outputs and how they are handled. We will create a pipeline to smooth an image with a median filter, run the wasm from the command line, in Node.js. Make sure to complete the [Hello Pipeline!](/tutorial/hello_pipeline) example before you start your filtering journey. diff --git a/examples/inputs-outputs/package.json b/examples/inputs-outputs/package.json index 2d19d461a..aa29d0b11 100644 --- a/examples/inputs-outputs/package.json +++ b/examples/inputs-outputs/package.json @@ -1,12 +1,12 @@ { - "name": "itk-wasm-inputs-outputs-example", - "version": "1.0.2", - "description": "An itk-wasm pipeline example for inputs/outputs", + "name": "@itk-wasm/inputs-outputs-tutorial", + "version": "1.0.3", + "description": "itk-wasm example for the pipeline inputs/outputs tutorial", "main": "index.mjs", "type": "module", "scripts": { "build": "npm run build:wasi && npm run build:emscripten", - "build:wasi": "itk-wasm -b wasi-build -i itkwasm/wasi build", + "build:wasi": "itk-wasm -i itkwasm/wasi build", "build:emscripten": "itk-wasm -i itkwasm/emscripten:latest-debug build -b emscripten-build -- -DCMAKE_BUILD_TYPE=Debug", "test": "npm run test:wasi && npm run test:wasi:help && npm run test:emscripten", "test:wasi": "itk-wasm -b wasi-build run inputs-outputs.wasi.wasm -- -- cthead1.png smoothed.png", @@ -17,7 +17,7 @@ "license": "Apache-2.0", "dependencies": { "fs-extra": "^10.0.0", - "itk-image-io": "^1.0.0-b.63", - "itk-wasm": "^1.0.0-b.63" + "itk-image-io": "^1.0.0-b.83", + "itk-wasm": "^1.0.0-b.83" } } diff --git a/examples/io-types/.gitignore b/examples/io-types/.gitignore new file mode 100644 index 000000000..cf0f04e8a --- /dev/null +++ b/examples/io-types/.gitignore @@ -0,0 +1,5 @@ +package-lock.json +smoothed.png +smoothed-uint16.png +emscripten-build/ +wasi-build/ diff --git a/examples/io-types/CMakeLists.txt b/examples/io-types/CMakeLists.txt new file mode 100644 index 000000000..ce228ac7e --- /dev/null +++ b/examples/io-types/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.16) +project(io-types) + +# Use C++17 or newer with itk-wasm +set(CMAKE_CXX_STANDARD 17) + +# We always want to build against the WebAssemblyInterface module. +set(itk_components + WebAssemblyInterface + ITKSmoothing # provides itkMedianImageFilter.h + ) +# WASI or native binaries +if (NOT EMSCRIPTEN) + # WebAssemblyInterface supports the .iwi, .iwi.cbor itk-wasm format. + # We can list other ITK IO modules to build against to support other + # formats when building native executable or WASI WebAssembly. + # However, this will bloat the size of the WASI WebAssembly binary, so + # add them judiciously. + set(itk_components + ${itk_components} + ITKIOPNG + # ITKImageIO # Adds support for all available image IO modules + ) +endif() +find_package(ITK REQUIRED + COMPONENTS ${itk_components} + ) +include(${ITK_USE_FILE}) + +add_executable(io-types io-types.cxx) +target_link_libraries(io-types PUBLIC ${ITK_LIBRARIES}) \ No newline at end of file diff --git a/examples/io-types/cthead1-uint16.png b/examples/io-types/cthead1-uint16.png new file mode 100644 index 000000000..bc8d9b8a4 Binary files /dev/null and b/examples/io-types/cthead1-uint16.png differ diff --git a/examples/io-types/cthead1.png b/examples/io-types/cthead1.png new file mode 100644 index 000000000..2f37d355a Binary files /dev/null and b/examples/io-types/cthead1.png differ diff --git a/examples/io-types/io-types.cxx b/examples/io-types/io-types.cxx new file mode 100644 index 000000000..123779695 --- /dev/null +++ b/examples/io-types/io-types.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#include "itkPipeline.h" +#include "itkInputImage.h" +#include "itkOutputImage.h" +#include "itkSupportInputImageTypes.h" + +#include "itkImage.h" +#include "itkMedianImageFilter.h" + +template +int +MedianFilter(itk::wasm::Pipeline & pipeline, const TImage * inputImage) +{ + using ImageType = TImage; + + // For running the pipeline, mark the input image as required + // and specify its type name + pipeline.get_option("input-image")->required()->type_name("INPUT_IMAGE"); + + // Add a flag to specify the radius of the median filter. + unsigned int radius = 1; + pipeline.add_option("-r,--radius", radius, "Kernel radius in pixels"); + + // Add an output image argument. + using OutputImageType = itk::wasm::OutputImage; + OutputImageType outputImage; + pipeline.add_option("output-image", outputImage, "The output image")->required()->type_name("OUTPUT_IMAGE"); + + ITK_WASM_PARSE(pipeline); + + // Process our data + using FilterType = itk::MedianImageFilter< ImageType, ImageType >; + auto filter = FilterType::New(); + filter->SetInput(inputImage); + filter->SetRadius(radius); + filter->Update(); + + // Set the output image before the program completes. + outputImage.Set(filter->GetOutput()); + + return EXIT_SUCCESS; +} + +template +class PipelineFunctor +{ +public: + int operator()(itk::wasm::Pipeline & pipeline) + { + using ImageType = TImage; + + using InputImageType = itk::wasm::InputImage; + InputImageType inputImage; + pipeline.add_option("input-image", inputImage, "The input image"); + + // Use the ITK_WASM_PRE_PARSE macro, which checks only the defined options. + ITK_WASM_PRE_PARSE(pipeline); + + typename ImageType::ConstPointer image = inputImage.Get(); + return MedianFilter(pipeline, image); + } +}; + +int main( int argc, char * argv[] ) +{ + itk::wasm::Pipeline pipeline("different-input-types", "An itk-wasm pipeline example that demonstrates accepting different input types", argc, argv); + + // Specify + // 1) Input image pixel types we want to support + // 2) Input image dimensions we want to support + return itk::wasm::SupportInputImageTypes + ::Dimensions<2U>("input-image", pipeline); +} diff --git a/examples/io-types/package.json b/examples/io-types/package.json new file mode 100644 index 000000000..0d20471f6 --- /dev/null +++ b/examples/io-types/package.json @@ -0,0 +1,19 @@ +{ + "name": "@itk-wasm/io-types-tutorial", + "version": "1.0.2", + "description": "itk-wasm pipeline example for the input/output types tutorial", + "type": "module", + "scripts": { + "build": "npm run build:wasi", + "build:wasi": "itk-wasm -i itkwasm/wasi build", + "test": "npm run test:wasi && npm run test:wasi:help", + "test:wasi": "itk-wasm run wasi-build/io-types.wasi.wasm -- -- cthead1.png smoothed.png", + "test:wasi:uint16": "itk-wasm run wasi-build/io-types.wasi.wasm -- -- cthead1-uint16.png smoothed-uint16.png", + "test:wasi:help": "itk-wasm run wasi-build/io-types.wasi.wasm -- -- --help" + }, + "author": "Matt McCormick ", + "license": "Apache-2.0", + "dependencies": { + "itk-wasm": "^1.0.0-b.83" + } +}