Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8bcf0df
ENH: Original source code
dzenanz May 24, 2016
888b1e3
ENH: reorganizing files into a remote module
dzenanz May 24, 2016
b579170
COMP: Compiles and passes style check
dzenanz May 24, 2016
f8a9ee8
ENH: Passes the test
dzenanz May 24, 2016
6d13b97
ENH: Putting data to Midas
dzenanz May 24, 2016
57a3afd
ENH: non-random way to calculate the output
dzenanz May 25, 2016
af619e5
STYLE: Modernize to C++11 conventions
hjmjohnson Feb 12, 2018
0f28199
STYLE: Merge pull request #2 from KitwareMedical/ITKv5Style
hjmjohnson Feb 12, 2018
5ea3203
STYLE: Prefer C++11 type alias over typedef
hjmjohnson Feb 13, 2018
1ed2fba
STYLE: Merge pull request #3 from KitwareMedical/ITKv5Style
hjmjohnson Feb 13, 2018
d66ba97
DOC: Update copyright assignment to NumFOCUS
hjmjohnson Feb 19, 2020
3ccfce4
ENH: Fix CI (hashes MD5->SHA512, bump CMake version, ITK 5.3RC3)
dzenanz Feb 25, 2022
e4adcef
ENH: Bump ITK and change http to https
tbirdso May 31, 2022
eaf9b0c
BUG: Fix test library variable name
blowekamp Jan 27, 2026
2e6d462
ENH: Convert from md5 to .cid tags.
hjmjohnson Apr 22, 2026
4903234
ENH: Merge pull request #17 from hjmjohnson/update-cid-tags
hjmjohnson Apr 23, 2026
7536dde
ENH: Ingest ITKMultipleImageIterator into Modules/Core
hjmjohnson May 12, 2026
b641bf1
DOC: Add MultipleImageIterator README and clean module scaffolding
hjmjohnson May 12, 2026
4a244ab
COMP: Remove MultipleImageIterator .remote.cmake (in-tree)
hjmjohnson May 12, 2026
70ff6b6
ENH: Enable Module_MultipleImageIterator in configure-ci
hjmjohnson May 12, 2026
a1a0d48
STYLE: Address greptile review on MultipleImageIterator
hjmjohnson May 12, 2026
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
3 changes: 3 additions & 0 deletions Modules/Core/MultipleImageIterator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
project(MultipleImageIterator)

itk_module_impl()
24 changes: 24 additions & 0 deletions Modules/Core/MultipleImageIterator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# MultipleImageIterator

In-tree ITK module providing `itk::MultipleImageIterator`, a single
iterator that walks any number of co-registered images in lockstep.
The iterator returns a `std::vector` of pixel values (or references)
at each position, simplifying multi-channel processing without the
boilerplate of synchronizing N separate iterators.

## Origin

Ingested from the standalone remote module
[**KitwareMedical/MultipleImageIterator**](https://github.com/KitwareMedical/MultipleImageIterator)
on 2026-05-12, following the v4 ingestion guidelines defined in
InsightSoftwareConsortium/ITK#6204. Placed under `Modules/Core/` to
match the placement of other ITK iterators (`itkImageRegionIterator`,
`itkNeighborhoodIterator`). The upstream repository will be archived
read-only after this PR merges; it remains reachable at the URL above
for historical reference.

## References

- Schaerer J. *A MultipleImageIterator for iterating over multiple
images simultaneously.* The Insight Journal. December 2014.
<https://doi.org/10.54294/e5lmyz>
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*=========================================================================
*
* 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 itkMultipleImageIterator_h
#define itkMultipleImageIterator_h
#include <vector>
#include <itkImageRegionIterator.h>


namespace itk
{
/** \class MultipleImageIterator
* \brief An wrapper around image iterators to iterate over several images simultaneously
* All iterators must
* - point to images of the same type
* - be of the same size (number of values from begin to end)
* \ingroup ImageIterators
* \ingroup MultipleImageIterator */
template <typename TIterator>
class MultipleImageIterator
{
public:
using Self = MultipleImageIterator;
using IteratorType = TIterator;
using ImageType = typename IteratorType::ImageType;
/// Access one of the iterators
IteratorType &
operator[](const unsigned int i)
{
return m_Iterators[i];
}
Comment thread
hjmjohnson marked this conversation as resolved.
/// Add a new iterator
void
AddIterator(const IteratorType & it)
{
m_Iterators.push_back(it);
}
/// Advance all iterators
Self &
operator++()
{
for (auto it = m_Iterators.begin(); it != m_Iterators.end(); ++it)
{
++(*it);
}
return *this;
}
/// Rewind all iterators
void
GoToBegin()
{
for (auto it = m_Iterators.begin(); it != m_Iterators.end(); ++it)
{
it->GoToBegin();
}
}
/** Check if the first iterator is at end. In debug mode, additionally check
* that at least one iterator is present and that all iterators' IsAtEnd()
* methods return the same thing */
bool
IsAtEnd()
{
#ifdef NDEBUG
return m_Iterators[0].IsAtEnd();
#else
assert(m_Iterators.size());
bool retval = m_Iterators[0].IsAtEnd();
for (unsigned int i = 0; i < m_Iterators.size(); ++i)
assert(m_Iterators[i].IsAtEnd() == retval);
return retval;
#endif
}
/// Returns the number of iterators
unsigned int
Size() const
{
return m_Iterators.size();
}

protected:
std::vector<IteratorType> m_Iterators;
};
} // namespace itk
#endif // itkMultipleImageIterator_h
11 changes: 11 additions & 0 deletions Modules/Core/MultipleImageIterator/itk-module.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Maintainer: Joel Schaerer
itk_module(
MultipleImageIterator
DEPENDS
ITKCommon
TEST_DEPENDS
ITKTestKernel
EXCLUDE_FROM_DEFAULT
DESCRIPTION
"An iterator wrapper that walks multiple co-registered images in lockstep, returning a std::vector of pixel values at each position. https://doi.org/10.54294/e5lmyz"
)
19 changes: 19 additions & 0 deletions Modules/Core/MultipleImageIterator/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
itk_module_test()

set(MultipleImageIteratorTests DumpIntensities.cxx)

createtestdriver(MultipleImageIterator "${MultipleImageIterator-Test_LIBRARIES}" "${MultipleImageIteratorTests}")

itk_add_test(
NAME MultipleImageIteratorTest
COMMAND
MultipleImageIteratorTestDriver
--compare
DATA{randBase.nrrd}
"${ITK_TEST_OUTPUT_DIR}/randOut.nrrd"
DumpIntensities
"${ITK_TEST_OUTPUT_DIR}/randOut.nrrd"
DATA{img1.png}
DATA{img2.png}
DATA{img3.png}
)
95 changes: 95 additions & 0 deletions Modules/Core/MultipleImageIterator/test/DumpIntensities.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*=========================================================================
*
* 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 <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include "itkMultipleImageIterator.h"

// Dumps random samples from files into a csv file

int
DumpIntensities(int argc, char * argv[])
{
if (argc < 3)
{
std::cerr << "Usage: DumpIntensities outfile inImage [inImage ...]" << std::endl;
return 1;
}
using PixelType = unsigned short;
using ImageType = itk::Image<PixelType, 3>;
using ReaderType = itk::ImageFileReader<ImageType>;

using IteratorType = itk::ImageRegionIterator<ImageType>;
itk::MultipleImageIterator<IteratorType> it;

std::vector<ImageType::Pointer> images; // Need to keep a reference as iterators only have weak references
for (int i = 2; i < argc; ++i)
{
ReaderType::Pointer r = ReaderType::New();
r->SetFileName(argv[i]);
r->Update();
ImageType::Pointer im = r->GetOutput();
im->DisconnectPipeline();
images.push_back(im);
it.AddIterator(itk::ImageRegionIterator<ImageType>(im, im->GetLargestPossibleRegion()));
}

unsigned long long c = 0;
using Vec3 = itk::FixedArray<PixelType, 3>;
std::vector<Vec3> values;
for (it.GoToBegin(); !it.IsAtEnd(); ++it, ++c)
{
if (c % 42 == 0)
{
Vec3 v;
for (unsigned int i = 0; i < it.Size(); ++i)
{
v[i] = it[i].Get();
}
values.push_back(v);
}
}

using Image1D = itk::Image<Vec3, 1>;
Image1D::RegionType region;
region.SetIndex(0, 0);
region.SetSize(0, values.size());
Image1D::Pointer randImage = Image1D::New();
randImage->SetRegions(region);
randImage->Allocate();

int index = 0;
itk::ImageRegionIterator<Image1D> oIt(randImage, randImage->GetLargestPossibleRegion());
while (!oIt.IsAtEnd())
{
oIt.Set(values[index++]);
++oIt;
}

using WriterType = itk::ImageFileWriter<Image1D>;
WriterType::Pointer writer = WriterType::New();
writer->SetInput(randImage);
writer->SetFileName(argv[1]);
writer->Update();

return 0;
}
1 change: 1 addition & 0 deletions Modules/Core/MultipleImageIterator/test/img1.png.cid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bafkreicd6xi33oatbqzspxkeszliv3mmjnnmiiu6dj6qj6wuclkv7uokda
1 change: 1 addition & 0 deletions Modules/Core/MultipleImageIterator/test/img2.png.cid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bafkreiactetnzqheknc2zjeg6aoo6y7uqbid7oukpwttfjuj52stok6wbe
1 change: 1 addition & 0 deletions Modules/Core/MultipleImageIterator/test/img3.png.cid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bafkreibqkbie3ezhl2y2kvgfizpoj5qfz3y5xdbe5rqtjo35pb5zn5geti
1 change: 1 addition & 0 deletions Modules/Core/MultipleImageIterator/test/randBase.nrrd.cid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bafkreihso7ziayrcpwm22dbjctew7ju3a7egxdyoytdn4ueuwggu26tscq
61 changes: 0 additions & 61 deletions Modules/Remote/MultipleImageIterator.remote.cmake

This file was deleted.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ cmd = '''cmake \
-DModule_IOMeshMZ3:BOOL=ON \
-DModule_IOFDF:BOOL=ON \
-DModule_MorphologicalContourInterpolation:BOOL=ON \
-DModule_MultipleImageIterator:BOOL=ON \
-DModule_RLEImage:BOOL=ON \
-DModule_SubdivisionQuadEdgeMeshFilter:BOOL=ON \
-DModule_TextureFeatures:BOOL=ON \
Expand Down
Loading