Skip to content

Commit

Permalink
More efficient handling of filled channels reading tiles with scanlin…
Browse files Browse the repository at this point in the history
…e API (AcademySoftwareFoundation#830)

* refactor channel filling in InputFile API with tiled source

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>

* handle edge-case of empty framebuffer

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
Signed-off-by: Cary Phillips <cary@ilm.com>
  • Loading branch information
peterhillman authored and cary-ilm committed May 12, 2021
1 parent 28ac26b commit dd8f203
Show file tree
Hide file tree
Showing 2 changed files with 313 additions and 95 deletions.
274 changes: 183 additions & 91 deletions OpenEXR/IlmImf/ImfInputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,14 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
//
// We don't have any valid buffered info, so we need to read in
// from the file.
// if no channels are being read that are present in file, cachedBuffer will be empty
//

ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
if (ifd->cachedBuffer->begin() != ifd->cachedBuffer->end())
{
ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
}

ifd->cachedTileY = j;
}

Expand All @@ -284,55 +289,135 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
// framebuffer.
//

for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin();
k != ifd->cachedBuffer->end();
for (FrameBuffer::ConstIterator k = ifd->tFileBuffer.begin();
k != ifd->tFileBuffer.end();
++k)
{
Slice fromSlice = k.slice(); // slice to write from
Slice toSlice = ifd->tFileBuffer[k.name()]; // slice to write to

char *fromPtr, *toPtr;
int size = pixelTypeSize (toSlice.type);

int xStart = levelRange.min.x;
int yStart = minYThisRow;
Slice toSlice = k.slice(); // slice to read from
char* toPtr;

int xStart = levelRange.min.x;
int yStart = minYThisRow;

while (modp (xStart, toSlice.xSampling) != 0)
++xStart;
while (modp (xStart, toSlice.xSampling) != 0)
++xStart;

while (modp (yStart, toSlice.ySampling) != 0)
++yStart;
while (modp (yStart, toSlice.ySampling) != 0)
++yStart;

for (int y = yStart;
y <= maxYThisRow;
y += toSlice.ySampling)
FrameBuffer::ConstIterator c = ifd->cachedBuffer->find(k.name());
intptr_t toBase = reinterpret_cast<intptr_t>(toSlice.base);


if( c!=ifd->cachedBuffer->end())
{
//
// output channel was read from source image: copy to output slice
//
Slice fromSlice = c.slice(); // slice to write to
intptr_t fromBase = reinterpret_cast<intptr_t>(fromSlice.base);

int size = pixelTypeSize (toSlice.type);
char* fromPtr;

for (int y = yStart;
y <= maxYThisRow;
y += toSlice.ySampling)
{
//
// Set the pointers to the start of the y scanline in
// this row of tiles
//

fromPtr = reinterpret_cast<char*> (fromBase +
(y - tileRange.min.y) * fromSlice.yStride +
xStart * fromSlice.xStride);

toPtr = reinterpret_cast<char*> (toBase +
divp (y, toSlice.ySampling) * toSlice.yStride +
divp (xStart, toSlice.xSampling) * toSlice.xStride);

//
// Copy all pixels for the scanline in this row of tiles
//

for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)
{
for (int i = 0; i < size; ++i)
toPtr[i] = fromPtr[i];

fromPtr += fromSlice.xStride * toSlice.xSampling;
toPtr += toSlice.xStride;
}
}
}
else
{
//
// Set the pointers to the start of the y scanline in
// this row of tiles
//

fromPtr = fromSlice.base +
(y - tileRange.min.y) * fromSlice.yStride +
xStart * fromSlice.xStride;

toPtr = toSlice.base +
divp (y, toSlice.ySampling) * toSlice.yStride +
divp (xStart, toSlice.xSampling) * toSlice.xStride;

//
// Copy all pixels for the scanline in this row of tiles
//

for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)

//
// channel wasn't present in source file: fill output slice
//
for (int y = yStart;
y <= maxYThisRow;
y += toSlice.ySampling)
{
for (int i = 0; i < size; ++i)
toPtr[i] = fromPtr[i];

fromPtr += fromSlice.xStride * toSlice.xSampling;
toPtr += toSlice.xStride;
toPtr = reinterpret_cast<char*> (toBase+
divp (y, toSlice.ySampling) * toSlice.yStride +
divp (xStart, toSlice.xSampling) * toSlice.xStride);

//
// Copy all pixels for the scanline in this row of tiles
//

switch ( toSlice.type)
{
case UINT:
{
unsigned int fill = toSlice.fillValue;
for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)
{
* reinterpret_cast<unsigned int*>(toPtr) = fill;
toPtr += toSlice.xStride;
}
break;
}
case HALF :
{
half fill = toSlice.fillValue;
for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)
{
* reinterpret_cast<half*>(toPtr) = fill;
toPtr += toSlice.xStride;
}
break;
}
case FLOAT :
{
float fill = toSlice.fillValue;
for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)
{
* reinterpret_cast<float*>(toPtr) = fill;
toPtr += toSlice.xStride;
}
break;
}
case NUM_PIXELTYPES :
{
break;
}

}
}
}
}
Expand Down Expand Up @@ -698,60 +783,67 @@ InputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
{
Slice s = k.slice();

switch (s.type)
{
case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:

_data->cachedBuffer->insert
(k.name(),
Slice (UINT,
(char *)(new unsigned int[tileRowSize] -
_data->offset),
sizeof (unsigned int),
sizeof (unsigned int) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:

_data->cachedBuffer->insert
(k.name(),
Slice (HALF,
(char *)(new half[tileRowSize] -
_data->offset),
sizeof (half),
sizeof (half) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:

_data->cachedBuffer->insert
(k.name(),
Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
(char *)(new float[tileRowSize] -
_data->offset),
sizeof(float),
sizeof(float) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

default:

throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type.");
}
//
// omit adding channels that are not listed - 'fill' channels are added later
//
if ( _data->header.channels().find(k.name()) != _data->header.channels().end() )
{
switch (s.type)
{
case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:

_data->cachedBuffer->insert
(k.name(),
Slice (UINT,
(char *)(new unsigned int[tileRowSize] -
_data->offset),
sizeof (unsigned int),
sizeof (unsigned int) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:

_data->cachedBuffer->insert
(k.name(),
Slice (HALF,
(char *)(new half[tileRowSize] -
_data->offset),
sizeof (half),
sizeof (half) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:

_data->cachedBuffer->insert
(k.name(),
Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
(char *)(new float[tileRowSize] -
_data->offset),
sizeof(float),
sizeof(float) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;

default:

throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type.");
}
}
}

_data->tFile->setFrameBuffer (*_data->cachedBuffer);

}

_data->tFileBuffer = frameBuffer;
Expand Down
Loading

0 comments on commit dd8f203

Please sign in to comment.