Skip to content
Snippets Groups Projects
Commit 4e060c24 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell
Browse files

Copy simple TIFF images into buffers more directly

If we have simple, single component, tightly-packed images then
copy them directly into the allocated buffer. If we are clipping, use
memcpy to just copy the subset requested. This is primarily aimed at
accelerating the load times for TIFF volumes. Thanks to Robert
Maynard for the suggested simplications in the templated image
function.

Change-Id: I6c3b10a019fc892b1e1bbbce32841e7f946eb995
parent c2a7f9ff
No related merge requests found
......@@ -27,6 +27,62 @@ extern "C" {
#include "vtk_tiff.h"
}
namespace {
struct FlipTrue {};
struct FlipFalse {};
int GetFileRow(int row, int height, FlipTrue)
{
return height - row - 1;
}
int GetFileRow(int row, int, FlipFalse)
{
return row;
}
// Simple scan line copy of a slice in a volume with tightly packed memory.
template<typename T, typename Flip>
bool ReadTemplatedImage(T* out, Flip flip,
int startCol, int endCol,
int startRow, int endRow,
int yIncrements,
unsigned int height, TIFF *image)
{
unsigned int isize = TIFFScanlineSize(image);
size_t scanLineSize = endCol - startCol + 1;
if (scanLineSize * sizeof(T) == isize)
{
// We can copy straight into the image data output.
for (int i = startRow; i <= endRow; ++i)
{
T* tmp = out + (i - startRow) * yIncrements;
if (TIFFReadScanline(image, tmp, GetFileRow(i, height, flip), 0) <= 0)
{
return false;
}
}
}
else
{
// Copy into a buffer of the appropriate size, then subset into the output.
tdata_t buf = _TIFFmalloc(isize);
for (int i = startRow; i <= endRow; ++i)
{
T* tmp = out + (i - startRow) * yIncrements;
if (TIFFReadScanline(image, buf, GetFileRow(i, height, flip), 0) <= 0)
{
_TIFFfree(buf);
return false;
}
memcpy(tmp, static_cast<T*>(buf) + startCol, sizeof(T) * scanLineSize);
}
_TIFFfree(buf);
}
return true;
}
}
//-------------------------------------------------------------------------
vtkStandardNewMacro(vtkTIFFReader)
......@@ -1012,6 +1068,41 @@ void vtkTIFFReader::ReadTwoSamplesPerPixelImage(void *out,
template<typename T>
void vtkTIFFReader::ReadGenericImage(T* out, unsigned int, unsigned int height)
{
// Fast path for simple images
unsigned int format = this->GetFormat();
if (this->InternalImage->PlanarConfig == PLANARCONFIG_CONTIG &&
this->OutputIncrements[0] == 1 &&
(format == vtkTIFFReader::GRAYSCALE &&
this->InternalImage->Photometrics == PHOTOMETRIC_MINISBLACK &&
this->InternalImage->SamplesPerPixel == 1))
{
if (this->InternalImage->Orientation == ORIENTATION_TOPLEFT)
{
FlipFalse flip;
if (!ReadTemplatedImage(out, flip,
this->OutputExtent[0], this->OutputExtent[1],
this->OutputExtent[2], this->OutputExtent[3],
this->OutputIncrements[1],
height, this->InternalImage->Image))
{
vtkErrorMacro(<< "Problem reading slice of volume in TIFF file.");
}
}
else
{
FlipTrue flip;
if (!ReadTemplatedImage(out, flip,
this->OutputExtent[0], this->OutputExtent[1],
this->OutputExtent[2], this->OutputExtent[3],
this->OutputIncrements[1],
height, this->InternalImage->Image))
{
vtkErrorMacro(<< "Problem reading slice of volume in TIFF file.");
}
}
return;
}
unsigned int isize = TIFFScanlineSize(this->InternalImage->Image);
tdata_t buf = _TIFFmalloc(isize);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment