Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Tiled tiff loader #350

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
52 changes: 49 additions & 3 deletions include/vigra/multi_impex.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "multi_array.hxx"
#include "multi_pointoperators.hxx"
#include "sifImport.hxx"
#include "tiff_file.hxx"

#ifdef _MSC_VER
# include <direct.h>
Expand Down Expand Up @@ -168,8 +169,9 @@ class VolumeImportInfo
Possible values are:
<DL>
<DT>"MULTIPAGE"<DD> Multiple 2D images in a single file (currently only supported by TIFF).
<DT>"TILEDTIFF"<DD> Tiled TIFF (standard conform, but extremly rare, used by MeVisLab).
<DT>"SIF"<DD> <a href="http://www.andor.com">Andor Technology's</a> .sif format.
<DT>"RAW"<DD> Raw data file, accompanied by a .info file
<DT>"RAW"<DD> Raw data file, accompanied by an .info file
<DT>"STACK"<DD> A numbered set of 2D image files, one per slice of the volume.
</DL>
**/
Expand Down Expand Up @@ -491,7 +493,51 @@ void VolumeImportInfo::importImpl(MultiArrayView <3, T, Stride> &volume) const
{
vigra_precondition(this->shape() == volume.shape(), "importVolume(): Output array must be shaped according to VolumeImportInfo.");

if(fileType_ == "RAW")
if(fileType_ == "TILEDTIFF")
{
TIFFFile f(path_.c_str(), "r");

MultiArrayShape<3>::type
zero3D(0, 0, 0),
one3D(1, 1, 1),
imageSize = f.imageSize3D(),
tileSize = f.tileSize3D(),
tileCount = (imageSize + tileSize - one3D) / tileSize;

MultiArray<3, T> tileBuffer(tileSize);

// read all tiles; important background info on the libtiff API:
// - all tiles have the same size, i.e. we need to clip at the
// upper boundaries in general
// - although the tiles are also numbered, the can only be
// read by passing an arbitrary(!) coordinate pointing into
// that slice...
MultiArrayShape<3>::type copyPos;
for(copyPos[0] = 0; copyPos[0] < imageSize[0]; copyPos[0] += tileSize[0])
{
for(copyPos[1] = 0; copyPos[1] < imageSize[1]; copyPos[1] += tileSize[1])
{
for(copyPos[2] = 0; copyPos[2] < imageSize[2]; copyPos[2] += tileSize[2])
{
// clip by not always copying tileSize voxels into target volume
MultiArrayShape<3>::type copySize(tileSize);
for(char dim = 0; dim < 3; ++dim)
if(copySize[dim] > imageSize[dim] - copyPos[dim])
copySize[dim] = imageSize[dim] - copyPos[dim];

MultiArrayView<3, T, Stride>
targetVOI(volume.subarray(copyPos, imageSize));

// now read and copy (TODO: handle T != pixelType()!)
f.readTile(tileBuffer.data(), copyPos[0], copyPos[1], copyPos[2], 0);

copyMultiArray(srcMultiArrayRange(tileBuffer.subarray(zero3D, copySize)),
destMultiArray(targetVOI));
}
}
}
}
else if(fileType_ == "RAW")
{
std::string dirName, baseName;
char oldCWD[2048];
Expand Down Expand Up @@ -550,7 +596,7 @@ void VolumeImportInfo::importImpl(MultiArrayView <3, T, Stride> &volume) const
// import the image
ImageImportInfo info (filename.c_str ());

// generate a basic image view to the current layer
// generate a 2D image view to the current layer
MultiArrayView <2, T, Stride> view (volume.bindOuter (i));
vigra_precondition(view.shape() == info.shape(),
"importVolume(): the images have inconsistent sizes.");
Expand Down
62 changes: 62 additions & 0 deletions include/vigra/tiff_file.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <tiffio.h>
#include "vigra/tinyvector.hxx"

namespace vigra {

class TIFFFile
{
public:
typedef TinyVector<uint32, 3> VolumeSize;

TIFFFile(const char *filename, const char *mode);

/**
* There are two possible TIFF file types that require different
* I/O APIs: striped files (which you know well) and tiled files
* (veeeery esoteric).
*/
enum FileType { INVALID = 0, STRIPED = 1, TILED = 2 };

/**
* For usual TIFF files (no tile size fields), returns STRIPED.
* Returns TILED iff the TIFF file contains both tile width and
* height tags (and the tile depth tag for 3D files, i.e. if
* there's an image depth tag), INVALID otherwise (some, but not
* all extents specified).
*/
FileType fileType() const
{
return fileType_;
}

/**
* Returns true for 3D TIFFs, i.e. those with the SGI image/tile depth fields.
*/
bool hasDepth() const
{
return hasDepth_;
}

VolumeSize imageSize3D() const
{
return imageSize_;
}

VolumeSize tileSize3D() const
{
return tileSize_;
}

tsize_t readTile(tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t sample);

std::string pixelType() const;

private:
TIFF *h_; // TIFF file handle (cf. libtiff library)

TinyVector<uint32, 3> imageSize_, tileSize_;
FileType fileType_;
bool hasDepth_;
};

} // namespace vigra
2 changes: 2 additions & 0 deletions src/impex/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ ADD_LIBRARY(vigraimpex ${LIBTYPE}
hdf5_rf_impex.cxx
iccjpeg.c
imageinfo.cxx
multi_impex.cxx
tiff_file.cxx
jpeg.cxx
lz4.c
png.cxx
Expand Down
Loading