Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bafkreigfnnwheantnltrycahox5r3agtmf4q2vfmbabrjx7rjs66iikozi
bafkreifuvkmy4vvxyhxwcga5rvs3y75dwyt4bf3h6g2fyoxt3am5jqzbra
5 changes: 4 additions & 1 deletion Modules/ThirdParty/MetaIO/src/MetaIO/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

if(METAIO_FOR_VTK)
set(METAIO_NAMESPACE "vtkmetaio")
set(METAIO_TARGET "metaio")
set(METAIO_TARGET "vtkmetaio")
set(METAIO_INSTALL_NO_LIBRARIES TRUE)
set(METAIO_INSTALL_NO_DEVELOPMENT TRUE)
if(BUILD_SHARED_LIBS)
Expand Down Expand Up @@ -124,6 +124,9 @@ if (METAIO_FOR_VTK)
SOURCES ${sources}
HEADERS ${headers}
HEADERS_SUBDIR "vtkmetaio")
vtk_module_set_property(VTK::metaio
PROPERTY DEFINE_SYMBOL
VALUE metaio_EXPORTS)
else ()
add_library(${METAIO_TARGET}
${sources}
Expand Down
18 changes: 13 additions & 5 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/metaArray.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -979,19 +979,27 @@ MetaArray::M_ReadElements(METAIO_STREAM::ifstream * _fstream, void * _data, int
// If compressed we inflate
if (m_CompressedData)
{
// if m_CompressedElementDataSize is not defined we assume the size of the
// file is the size of the compressed data
// if m_CompressedElementDataSize is not defined we assume the compressed
// data runs from the current position to the end of the file
if (m_CompressedElementDataSize == 0)
{
const std::streampos dataPos = _fstream->tellg();
_fstream->seekg(0, std::ios::end);
m_CompressedElementDataSize = _fstream->tellg();
_fstream->seekg(0, std::ios::beg);
m_CompressedElementDataSize = static_cast<std::streamoff>(_fstream->tellg() - dataPos);
_fstream->seekg(dataPos);
}

auto * compr = new unsigned char[static_cast<size_t>(m_CompressedElementDataSize)];
_fstream->read(reinterpret_cast<char *>(compr), static_cast<size_t>(m_CompressedElementDataSize));

MET_PerformUncompression(compr, m_CompressedElementDataSize, static_cast<unsigned char *>(_data), readSize);
const bool uncompressed =
MET_PerformUncompression(compr, m_CompressedElementDataSize, static_cast<unsigned char *>(_data), readSize);
delete[] compr;
if (!uncompressed)
{
std::cerr << "MetaArray: M_ReadElements: could not uncompress element data" << '\n';
return false;
}
}
else // if not compressed
{
Expand Down
42 changes: 31 additions & 11 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/metaImage.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ MetaImage::InitializeEssential(int _nDims,
m_ElementDirection[i*m_NDims+j] = 1;
}
}
}
}
}

if (_elementData != nullptr)
Expand Down Expand Up @@ -1330,10 +1330,13 @@ MetaImage::ReadStream(int _nDims, METAIO_STREAM::ifstream * _stream, bool _readE
delete[] wrds[i];
}
delete[] wrds;
if ((fileImageDim == 0) || (fileImageDim > m_NDims))
if ((fileImageDim <= 0) || (fileImageDim >= m_NDims))
{
// if optional file dimension size is not given or is larger than
// overall dimension then default to a size of m_NDims - 1.
// if optional file dimension size is not given, is not positive, or
// does not leave a dimension to iterate files over, then default to
// a size of m_NDims - 1. m_DimSize and m_SubQuantity are only
// indexable over [0, m_NDims), so out-of-range values must not reach
// the loops below.
fileImageDim = m_NDims - 1;
}
std::string s;
Expand All @@ -1346,6 +1349,7 @@ MetaImage::ReadStream(int _nDims, METAIO_STREAM::ifstream * _stream, bool _readE
{
totalFiles *= m_DimSize[i - 1];
}
int filesRead = 0;
for (i = 0; i < totalFiles && !_stream->eof(); i++)
{
std::getline(*_stream, s);
Expand Down Expand Up @@ -1382,9 +1386,17 @@ MetaImage::ReadStream(int _nDims, METAIO_STREAM::ifstream * _stream, bool _readE
}

readStreamTemp->close();
filesRead++;
}
}
delete readStreamTemp;
if (filesRead < totalFiles)
{
// The list ended early, so the tail of m_ElementData was never read.
std::cerr << "MetaImage: Read: LIST names " << filesRead << " file(s), but " << totalFiles << " are required"
<< '\n';
return false;
}
}
else if (m_ElementDataFileName.find('%') != std::string::npos)
{
Expand Down Expand Up @@ -2475,7 +2487,7 @@ MetaImage::M_Read()
m_Offset[i] = mF->value[i];
}
}

mF = MET_GetFieldRecord("ElementDirection", &m_Fields);
if (mF && mF->defined)
{
Expand All @@ -2496,7 +2508,7 @@ MetaImage::M_Read()
m_ElementOrigin[i] = mF->value[i];
}
}

mF = MET_GetFieldRecord("ElementDirection", &m_Fields);
if (mF && mF->defined)
{
Expand Down Expand Up @@ -2610,15 +2622,16 @@ MetaImage::M_ReadElements(METAIO_STREAM::ifstream * _fstream, void * _data, std:
// If compressed we inflate
if (m_BinaryData && m_CompressedData)
{
// if m_CompressedDataSize is not defined we assume the size of the
// file is the size of the compressed data
// if m_CompressedDataSize is not defined we assume the compressed data
// runs from the current position to the end of the file
bool compressedDataDeterminedFromFile = false;
if (m_CompressedDataSize == 0)
{
compressedDataDeterminedFromFile = true;
const std::streampos dataPos = _fstream->tellg();
_fstream->seekg(0, std::ios::end);
m_CompressedDataSize = _fstream->tellg();
_fstream->seekg(0, std::ios::beg);
m_CompressedDataSize = static_cast<std::streamoff>(_fstream->tellg() - dataPos);
_fstream->seekg(dataPos);
}

auto * compr = new unsigned char[static_cast<size_t>(m_CompressedDataSize)];
Expand All @@ -2629,14 +2642,21 @@ MetaImage::M_ReadElements(METAIO_STREAM::ifstream * _fstream, void * _data, std:
return false;
}

MET_PerformUncompression(compr, m_CompressedDataSize, static_cast<unsigned char *>(_data), readSize);
const bool uncompressed =
MET_PerformUncompression(compr, m_CompressedDataSize, static_cast<unsigned char *>(_data), readSize);

if (compressedDataDeterminedFromFile)
{
m_CompressedDataSize = 0;
}

delete[] compr;

if (!uncompressed)
{
std::cerr << "MetaImage: M_ReadElements: could not uncompress element data" << '\n';
return false;
}
}
else // if not compressed
{
Expand Down
4 changes: 2 additions & 2 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/metaImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class METAIO_EXPORT MetaImage : public MetaObject
// direction that the fastest moving index in the image traverses in
// physical space while the last column defines the direction that the
// slowest moving index in the image traverses in physical space.
//
//
// Set the direction cosines of the image. The direction cosines
// are vectors that point from one pixel to the next.
//
Expand Down Expand Up @@ -438,7 +438,7 @@ class METAIO_EXPORT MetaImage : public MetaObject

double m_ElementOrigin[10]{}; // "ElementOrigin = " 0,0,0
double m_ElementDirection[100]{}; // "ElementDirection = " 1,0,0,0,1,0,0,0,1

bool m_AutoFreeElementData{};

void * m_ElementData{};
Expand Down
14 changes: 7 additions & 7 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/metaObject.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,16 @@ MetaObject::ClearUserFields()

if (!deleted)
{
auto it2 = m_Fields.begin();
auto end2 = m_Fields.end();
while (it2 != end2)
auto fieldit2 = m_Fields.begin();
auto fieldend2 = m_Fields.end();
while (fieldit2 != fieldend2)
{
if (*it2 == field)
if (*fieldit2 == field)
{
m_Fields.erase(it2);
m_Fields.erase(fieldit2);
break;
}
++it2;
++fieldit2;
}
delete field;
}
Expand Down Expand Up @@ -1750,7 +1750,7 @@ MetaObject::M_Read()
++it;
continue;
}

// Don't add a read field to the write fields if it is already in the write fields
bool found = false;
FieldsContainerType::iterator dup;
Expand Down
12 changes: 10 additions & 2 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/metaUtils.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,10 @@ MET_PerformUncompression(const unsigned char * sourceCompressed,
d_stream.next_out = uncompressedData + dest_pos;
d_stream.avail_out = cur_remain_chunk;
err = inflate(&d_stream, Z_NO_FLUSH);
// Account for this call's output before any exit, including the final
// call that reports Z_STREAM_END.
uInt count_uncompressed = cur_remain_chunk - d_stream.avail_out;
dest_pos += count_uncompressed;
if (err == Z_STREAM_END || err < 0)
{
if (err != Z_STREAM_END && err != Z_BUF_ERROR) // Z_BUF_ERROR means there is still data to uncompress,
Expand All @@ -884,11 +888,15 @@ MET_PerformUncompression(const unsigned char * sourceCompressed,
}
break;
}
uInt count_uncompressed = cur_remain_chunk - d_stream.avail_out;
dest_pos += count_uncompressed;
} while (d_stream.avail_out == 0);
} while (err != Z_STREAM_END && err >= 0);
inflateEnd(&d_stream);
if (dest_pos != uncompressedDataSize)
{
std::cerr << "MET_PerformUncompression: expected " << uncompressedDataSize << " bytes, produced " << dest_pos
<< '\n';
return false;
}
Comment thread
hjmjohnson marked this conversation as resolved.
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ MetaAddTest(testMeta9Landmark)
MetaAddTest(testMeta10Contour)
MetaAddTest(testMeta11Form)
MetaAddTest(testMeta12Array)
MetaAddTest(testMeta13ImageList)
MetaAddTest(testMeta14ImageCompressed)
119 changes: 119 additions & 0 deletions Modules/ThirdParty/MetaIO/src/MetaIO/src/tests/testMeta13ImageList.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Regression tests for the "ElementDataFile = LIST" reader.

#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>

#include <metaImage.h>

namespace
{

const char * const slice0 = "testMeta13_s0.raw";
const char * const slice1 = "testMeta13_s1.raw";

void
WriteSlice(const char * name, unsigned char value)
{
std::ofstream out(name, std::ios::binary);
const unsigned char buf[4] = { value, value, value, value };
out.write(reinterpret_cast<const char *>(buf), 4);
}

// A 2x2x2 MET_UCHAR volume whose slices come from a LIST. "listBody" supplies
// the ElementDataFile value and the file names that follow it.
void
WriteHeader(const std::string & name, const std::string & listBody)
{
std::ofstream out(name.c_str());
out << "ObjectType = Image\n"
<< "NDims = 3\n"
<< "DimSize = 2 2 2\n"
<< "ElementType = MET_UCHAR\n"
<< "ElementSpacing = 1 1 1\n"
<< "ElementByteOrderMSB = False\n"
<< listBody;
}

bool
SlicesAreOneThenTwo(MetaImage & image)
{
for (int i = 0; i < 8; ++i)
{
const int expected = (i < 4) ? 1 : 2;
if (static_cast<int>(image.ElementData(i)) != expected)
{
std::cout << " element " << i << " is " << image.ElementData(i) << ", expected " << expected << '\n';
return false;
}
}
return true;
}

} // namespace

int
main(int, char *[])
{
WriteSlice(slice0, 1);
WriteSlice(slice1, 2);

const std::string bothSlices = std::string(slice0) + "\n" + slice1 + "\n";

// A well-formed list reads both slices.
WriteHeader("testMeta13_valid.mhd", "ElementDataFile = LIST\n" + bothSlices);
{
MetaImage image;
if (!image.Read("testMeta13_valid.mhd"))
{
std::cout << "Well-formed LIST failed to read: FAIL" << '\n';
return EXIT_FAILURE;
}
if (!SlicesAreOneThenTwo(image))
{
std::cout << "Well-formed LIST read wrong values: FAIL" << '\n';
return EXIT_FAILURE;
}
}

// A list naming fewer files than DimSize requires must not report success,
// because the tail of the buffer is never written.
WriteHeader("testMeta13_short.mhd", std::string("ElementDataFile = LIST\n") + slice0 + "\n");
{
MetaImage image;
if (image.Read("testMeta13_short.mhd"))
{
std::cout << "Short LIST reported success: FAIL" << '\n';
return EXIT_FAILURE;
}
}

// An out-of-range file dimension must fall back to NDims - 1 rather than
// indexing m_DimSize/m_SubQuantity outside [0, NDims).
const char * const outOfRange[] = { "ElementDataFile = LIST -1\n", "ElementDataFile = LIST 3\n" };
for (const char * const listType : outOfRange)
{
WriteHeader("testMeta13_range.mhd", listType + bothSlices);
MetaImage image;
if (!image.Read("testMeta13_range.mhd"))
{
std::cout << "Out-of-range file dimension failed to read: FAIL (" << listType << ')' << '\n';
return EXIT_FAILURE;
}
if (!SlicesAreOneThenTwo(image))
{
std::cout << "Out-of-range file dimension read wrong values: FAIL (" << listType << ')' << '\n';
return EXIT_FAILURE;
}
}

std::remove(slice0);
std::remove(slice1);
std::remove("testMeta13_valid.mhd");
std::remove("testMeta13_short.mhd");
std::remove("testMeta13_range.mhd");

std::cout << "LIST element data file tests: PASS" << '\n';
return EXIT_SUCCESS;
}
Loading
Loading