Skip to content

Commit

Permalink
WIP: feat: itk::WasmTransformIO initial addition
Browse files Browse the repository at this point in the history
  • Loading branch information
thewtex committed Apr 19, 2024
1 parent fa735c7 commit 545645d
Show file tree
Hide file tree
Showing 14 changed files with 1,384 additions and 355 deletions.
9 changes: 5 additions & 4 deletions include/itkInputMeshIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "itkPipeline.h"
#include "itkWasmMeshIOBase.h"
#include "itkWasmMeshIO.h"
#include "itkWasmIOCommon.h"

#ifndef ITK_WASM_NO_MEMORY_IO
#include "itkWasmExports.h"
Expand Down Expand Up @@ -87,15 +88,15 @@ bool lexical_cast(const std::string &input, InputMeshIO &inputMeshIO)
const std::string pointsString( pointsJson.GetString() );
const char * pointsPtr = reinterpret_cast< char * >( std::strtoull(pointsString.substr(35).c_str(), nullptr, 10) );
WasmMeshIOBase::DataContainerType * pointsContainer = wasmMeshIOBase->GetPointsContainer();
SizeValueType numberOfBytes = wasmMeshIO->GetNumberOfPoints() * wasmMeshIO->GetPointDimension() * WasmMeshIO::ITKComponentSize( wasmMeshIO->GetPointComponentType() );
SizeValueType numberOfBytes = wasmMeshIO->GetNumberOfPoints() * wasmMeshIO->GetPointDimension() * ITKComponentSize( wasmMeshIO->GetPointComponentType() );
pointsContainer->resize(numberOfBytes);
pointsContainer->assign(pointsPtr, pointsPtr + numberOfBytes);

const rapidjson::Value & cellsJson = document["cells"];
const std::string cellsString( cellsJson.GetString() );
const char * cellsPtr = reinterpret_cast< char * >( std::strtoull(cellsString.substr(35).c_str(), nullptr, 10) );
WasmMeshIOBase::DataContainerType * cellsContainer = wasmMeshIOBase->GetCellsContainer();
numberOfBytes = static_cast< SizeValueType >( wasmMeshIO->GetCellBufferSize() * WasmMeshIO::ITKComponentSize( wasmMeshIO->GetCellComponentType() ));
numberOfBytes = static_cast< SizeValueType >( wasmMeshIO->GetCellBufferSize() * ITKComponentSize( wasmMeshIO->GetCellComponentType() ));
cellsContainer->resize(numberOfBytes);
cellsContainer->assign(cellsPtr, cellsPtr + numberOfBytes);

Expand All @@ -105,7 +106,7 @@ bool lexical_cast(const std::string &input, InputMeshIO &inputMeshIO)
WasmMeshIOBase::DataContainerType * pointDataContainer = wasmMeshIOBase->GetPointDataContainer();
numberOfBytes =
static_cast< SizeValueType >(
wasmMeshIO->GetNumberOfPointPixels() * wasmMeshIO->GetNumberOfPointPixelComponents() * WasmMeshIO::ITKComponentSize( wasmMeshIO->GetPointPixelComponentType() )
wasmMeshIO->GetNumberOfPointPixels() * wasmMeshIO->GetNumberOfPointPixelComponents() * ITKComponentSize( wasmMeshIO->GetPointPixelComponentType() )
);
pointDataContainer->resize(numberOfBytes);
pointDataContainer->assign(pointDataPtr, pointDataPtr + numberOfBytes);
Expand All @@ -116,7 +117,7 @@ bool lexical_cast(const std::string &input, InputMeshIO &inputMeshIO)
WasmMeshIOBase::DataContainerType * cellDataContainer = wasmMeshIOBase->GetCellDataContainer();
numberOfBytes =
static_cast< SizeValueType >(
wasmMeshIO->GetNumberOfPointPixels() * wasmMeshIO->GetNumberOfPointPixelComponents() * WasmMeshIO::ITKComponentSize( wasmMeshIO->GetPointPixelComponentType() )
wasmMeshIO->GetNumberOfPointPixels() * wasmMeshIO->GetNumberOfPointPixelComponents() * ITKComponentSize( wasmMeshIO->GetPointPixelComponentType() )
);
cellDataContainer->resize(numberOfBytes);
cellDataContainer->assign(cellDataPtr, cellDataPtr + numberOfBytes);
Expand Down
8 changes: 4 additions & 4 deletions include/itkOutputMeshIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,15 @@ class OutputMeshIO
return;
}

SizeValueType numberOfBytes = this->m_MeshIO->GetNumberOfPoints() * this->m_MeshIO->GetPointDimension() * WasmMeshIO::ITKComponentSize( this->m_MeshIO->GetPointComponentType() );
SizeValueType numberOfBytes = this->m_MeshIO->GetNumberOfPoints() * this->m_MeshIO->GetPointDimension() * ITKComponentSize( this->m_MeshIO->GetPointComponentType() );
std::vector<char> loadBuffer(numberOfBytes);
if (numberOfBytes)
{
this->m_MeshIO->ReadPoints(reinterpret_cast< void * >( &(loadBuffer.at(0)) ));
wasmMeshIO->WritePoints(reinterpret_cast< void * >( &(loadBuffer.at(0)) ));
}

numberOfBytes = static_cast< SizeValueType >( this->m_MeshIO->GetCellBufferSize() * WasmMeshIO::ITKComponentSize( this->m_MeshIO->GetCellComponentType() ));
numberOfBytes = static_cast< SizeValueType >( this->m_MeshIO->GetCellBufferSize() * ITKComponentSize( this->m_MeshIO->GetCellComponentType() ));
if (numberOfBytes)
{
loadBuffer.resize(numberOfBytes);
Expand All @@ -171,7 +171,7 @@ class OutputMeshIO

numberOfBytes =
static_cast< SizeValueType >(
this->m_MeshIO->GetNumberOfPointPixels() * this->m_MeshIO->GetNumberOfPointPixelComponents() * WasmMeshIO::ITKComponentSize( this->m_MeshIO->GetPointPixelComponentType() )
this->m_MeshIO->GetNumberOfPointPixels() * this->m_MeshIO->GetNumberOfPointPixelComponents() * ITKComponentSize( this->m_MeshIO->GetPointPixelComponentType() )
);
if (numberOfBytes)
{
Expand All @@ -182,7 +182,7 @@ class OutputMeshIO

numberOfBytes =
static_cast< SizeValueType >(
this->m_MeshIO->GetNumberOfCellPixels() * this->m_MeshIO->GetNumberOfCellPixelComponents() * WasmMeshIO::ITKComponentSize( this->m_MeshIO->GetCellPixelComponentType() )
this->m_MeshIO->GetNumberOfCellPixels() * this->m_MeshIO->GetNumberOfCellPixelComponents() * ITKComponentSize( this->m_MeshIO->GetCellPixelComponentType() )
);
if (numberOfBytes)
{
Expand Down
93 changes: 93 additions & 0 deletions include/itkWasmIOCommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*=========================================================================
*
* 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.
*
*=========================================================================*/
#ifndef itkWasmIOCommon_h
#define itkWasmIOCommon_h
// Common functions used across the WebAssembly IO classes

#include "WebAssemblyInterfaceExport.h"

#include "itkIntTypes.h"
#include "itkMath.h"
#include "itkCommonEnums.h"

#include <fstream>

#include "cbor.h"

namespace itk
{

/** \brief Opens a file for reading and random access
*
* \param[out] inputStream is an istream presumed to be opened for reading
* \param[in] filename is the name of the file
* \param[in] ascii optional (default is false);
* if true than the file will be opened in ASCII mode,
* which generally only applies to Windows
*
* The stream is closed if it's already opened. If an error is
* encountered than an exception will be thrown.
*/
WebAssemblyInterface_EXPORT
void
openFileForReading(std::ifstream & inputStream, const std::string & filename,
bool ascii = false);

/** \brief Opens a file for writing and random access
*
* \param[out] outputStream is an ostream presumed to be opened for writing
* \param[in] filename is the name of the file
* \param[in] truncate optional (default is true);
* if true than the file's existing content is truncated,
* if false than the file is opened for reading and
* writing with existing content intact
* \param[in] ascii optional (default is false);
* if true than the file will be opened in ASCII mode,
* which generally only applies to Windows
*
* The stream is closed if it's already opened. If an error is
* encountered than an exception will be thrown.
*/
WebAssemblyInterface_EXPORT
void
openFileForWriting(std::ofstream & outputStream, const std::string & filename,
bool truncate = true, bool ascii = false);

/** Convenient method to read a buffer as binary. Return true on success. */
WebAssemblyInterface_EXPORT
bool
readBufferAsBinary(std::istream & os, void *buffer, SizeValueType numberOfBytesToBeRead);

WebAssemblyInterface_EXPORT
bool fileNameIsCBOR(const char * fileName);

WebAssemblyInterface_EXPORT
void
readCBORBuffer(cbor_item_t * index, const char * dataName, void * buffer, SizeValueType numberOfBytesToBeRead);

WebAssemblyInterface_EXPORT
void
writeCBORBuffer(cbor_item_t * index, const char * dataName, void * buffer, SizeValueType numberOfBytesToWrite, IOComponentEnum ioComponent);

WebAssemblyInterface_EXPORT
size_t
ITKComponentSize( const CommonEnums::IOComponent );

} // end namespace itk

#endif // itkWasmIOCommon_h
4 changes: 2 additions & 2 deletions include/itkWasmImageIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace itk
* \brief Read and write an itk::Image in a web-friendly format.
*
* This format is intended to facilitate data exchange in itk-wasm.
* It reads and writes an itk-wasm Image object in a CbOR file on the
* It reads and writes an itk-wasm Image object in a CBOR file on the
* filesystem with JSON files and binary files for TypedArrays.
*
*
* The file extensions used are .iwi and .iwi.cbor.
*
* \ingroup IOFilters
Expand Down
47 changes: 3 additions & 44 deletions include/itkWasmMeshIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ namespace itk
*
* This format is intended to facilitate data exchange in itk-wasm.
* It reads and writes an itk-wasm Mesh object where TypedArrays are
* replaced by binary files on the filesystem or in a ZIP file.
*
* The format is experimental and subject to change. We mean it.
* replaced by binary files on the filesystem or in a CBOR file.
*
* The file extensions used are .iwm and .iwm.cbor.
*
* \ingroup IOFilters
* \ingroup WebAssemblyInterface
*/
Expand Down Expand Up @@ -95,52 +95,11 @@ class WebAssemblyInterface_EXPORT WasmMeshIO: public MeshIOBase
rapidjson::Document GetJSON();
#endif

static size_t ITKComponentSize( const CommonEnums::IOComponent );

protected:
WasmMeshIO();
~WasmMeshIO() override;
void PrintSelf(std::ostream & os, Indent indent) const override;

/** \brief Opens a file for reading and random access
*
* \param[out] inputStream is an istream presumed to be opened for reading
* \param[in] filename is the name of the file
* \param[in] ascii optional (default is false);
* if true than the file will be opened in ASCII mode,
* which generally only applies to Windows
*
* The stream is closed if it's already opened. If an error is
* encountered than an exception will be thrown.
*/
void OpenFileForReading(std::ifstream & inputStream, const std::string & filename,
bool ascii = false);

/** \brief Opens a file for writing and random access
*
* \param[out] outputStream is an ostream presumed to be opened for writing
* \param[in] filename is the name of the file
* \param[in] truncate optional (default is true);
* if true than the file's existing content is truncated,
* if false than the file is opened for reading and
* writing with existing content intact
* \param[in] ascii optional (default is false);
* if true than the file will be opened in ASCII mode,
* which generally only applies to Windows
*
* The stream is closed if it's already opened. If an error is
* encountered than an exception will be thrown.
*/
void OpenFileForWriting(std::ofstream & outputStream, const std::string & filename,
bool truncate = true, bool ascii = false);

/** Convenient method to read a buffer as binary. Return true on success. */
bool ReadBufferAsBinary(std::istream & os, void *buffer, SizeValueType numberOfBytesToBeRead);

bool FileNameIsCBOR();
void ReadCBORBuffer(const char * dataName, void * buffer, SizeValueType numberOfBytesToBeRead);
void WriteCBORBuffer(const char * dataName, void * buffer, SizeValueType numberOfBytesToWrite, IOComponentEnum ioComponent);

/** Reads in the mesh information and populates the related buffers. */
void ReadCBOR(void * buffer = nullptr, unsigned char * cborBuffer = nullptr, size_t cborBufferLength = 0);
/** Writes the buffers into the CBOR item and the buffer out to disk. */
Expand Down
143 changes: 143 additions & 0 deletions include/itkWasmTransformIO.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*=========================================================================
*
* 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.
*
*=========================================================================*/
#ifndef itkWasmTransformIO_h
#define itkWasmTransformIO_h
#include "WebAssemblyInterfaceExport.h"

#include "itkTransformIOBase.h"
#include "itkMacro.h"
#include <fstream>

#include "rapidjson/document.h"
#include "cbor.h"

namespace itk
{
/** \class WasmTransformIOTemplate
*
* \brief Read and write the an itk::Transform in a format for interfacing in WebAssembly (Wasm).
*
* This format is intended to facilitate data exchange in itk-wasm.
* It reads and writes an itk-wasm Transform object where TypedArrays are
* replaced by binary files on the filesystem or in a CBOR file.
*
* The file extensions used are .iwt and .iwt.cbor.
*
* \ingroup IOFilters
* \ingroup WebAssemblyInterface
*/
template <typename TParametersValueType>
class ITK_TEMPLATE_EXPORT WasmTransformIOTemplate: public TransformIOBaseTemplate<TParametersValueType>
{
public:
using Self = WasmTransformIOTemplate;
using Superclass = TransformIOBaseTemplate<TParametersValueType>;
using Pointer = SmartPointer<Self>;
using typename Superclass::TransformType;
using typename Superclass::TransformPointer;
using typename Superclass::TransformListType;
using ParametersType = typename TransformType::ParametersType;
using ParametersValueType = typename TransformType::ParametersValueType;
using FixedParametersType = typename TransformType::FixedParametersType;
using FixedParametersValueType = typename TransformType::FixedParametersValueType;

using ConstTransformListType = typename TransformIOBaseTemplate<ParametersValueType>::ConstTransformListType;

/** Method for creation through the object factory. */
itkNewMacro(Self);

/** Run-time type information (and related methods). */
itkTypeMacro(WasmTransformIOTemplate, TransformIOBaseTemplate);

/** Reads the data from disk into the memory buffer provided. */
void
Read() override;

bool CanReadFile(const char *) override;

/** Set the JSON representation of the image information. */
void SetJSON(rapidjson::Document & json);

/*-------- This part of the interfaces deals with writing data ----- */

bool CanWriteFile(const char *) override;

void Write() override;

#if !defined(ITK_WRAPPING_PARSER)
/** Get the JSON representation of the mesh information. */
rapidjson::Document GetJSON();
#endif

protected:
WasmTransformIOTemplate();
~WasmTransformIOTemplate() override;
void PrintSelf(std::ostream & os, Indent indent) const override;

void ReadTransformInformation();
void ReadFixedParameters(void *buffer);
void ReadParameters(void *buffer);

void WriteTransformInformation();
void WriteFixedParameters(void *buffer);
void WriteParameters(void *buffer);

/** Reads in the mesh information and populates the related buffers. */
void ReadCBOR(void * buffer = nullptr, unsigned char * cborBuffer = nullptr, size_t cborBufferLength = 0);
/** Writes the buffers into the CBOR item and the buffer out to disk. */
void WriteCBOR();

cbor_item_t * m_CBORRoot{ nullptr };

private:
ITK_DISALLOW_COPY_AND_ASSIGN(WasmTransformIOTemplate);
};
} // end namespace itk

#endif // itkWasmTransformIO_h

/** Explicit instantiations */
#ifndef ITK_TEMPLATE_EXPLICIT_WasmTransformIO
// Explicit instantiation is required to ensure correct dynamic_cast
// behavior across shared libraries.
//
// IMPORTANT: Since within the same compilation unit,
// ITK_TEMPLATE_EXPLICIT_<classname> defined and undefined states
// need to be considered. This code *MUST* be *OUTSIDE* the header
// guards.
//
#if defined(WebAssemblyInterface_EXPORTS)
// We are building this library
# define WebAssemblyInterface_EXPORT_EXPLICIT ITK_FORWARD_EXPORT
#else
// We are using this library
# define WebAssemblyInterface_EXPORT_EXPLICIT WebAssemblyInterface_EXPORT
#endif
namespace itk
{
ITK_GCC_PRAGMA_DIAG_PUSH()
ITK_GCC_PRAGMA_DIAG(ignored "-Wattributes")

extern template class WebAssemblyInterface_EXPORT_EXPLICIT WasmTransformIOTemplate<double>;
extern template class WebAssemblyInterface_EXPORT_EXPLICIT WasmTransformIOTemplate<float>;

ITK_GCC_PRAGMA_DIAG_POP()

} // end namespace itk
#undef WebAssemblyInterface_EXPORT_EXPLICIT
#endif
Loading

0 comments on commit 545645d

Please sign in to comment.