/src/FreeImage/Source/OpenEXR/IlmImf/ImfMisc.cpp
https://bitbucket.org/cabalistic/ogredeps/ · C++ · 787 lines · 542 code · 172 blank · 73 comment · 80 complexity · aaf31256e57e679a4e004ddebf282ddf MD5 · raw file
- ///////////////////////////////////////////////////////////////////////////
- //
- // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
- // Digital Ltd. LLC
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Industrial Light & Magic nor the names of
- // its contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- ///////////////////////////////////////////////////////////////////////////
- //-----------------------------------------------------------------------------
- //
- // Miscellaneous helper functions for OpenEXR image file I/O
- //
- //-----------------------------------------------------------------------------
- #include <ImfMisc.h>
- #include <ImfHeader.h>
- #include <ImfCompressor.h>
- #include <ImfChannelList.h>
- #include <ImfXdr.h>
- #include <ImathFun.h>
- #include <Iex.h>
- #include <ImfStdIO.h>
- #include <ImfConvert.h>
- namespace Imf {
- using Imath::Box2i;
- using Imath::divp;
- using Imath::modp;
- using std::vector;
- int
- pixelTypeSize (PixelType type)
- {
- int size;
- switch (type)
- {
- case UINT:
-
- size = Xdr::size <unsigned int> ();
- break;
- case HALF:
- size = Xdr::size <half> ();
- break;
- case FLOAT:
- size = Xdr::size <float> ();
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel type.");
- }
- return size;
- }
- int
- numSamples (int s, int a, int b)
- {
- int a1 = divp (a, s);
- int b1 = divp (b, s);
- return b1 - a1 + ((a1 * s < a)? 0: 1);
- }
- size_t
- bytesPerLineTable (const Header &header,
- vector<size_t> &bytesPerLine)
- {
- const Box2i &dataWindow = header.dataWindow();
- const ChannelList &channels = header.channels();
- bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1);
- for (ChannelList::ConstIterator c = channels.begin();
- c != channels.end();
- ++c)
- {
- int nBytes = pixelTypeSize (c.channel().type) *
- (dataWindow.max.x - dataWindow.min.x + 1) /
- c.channel().xSampling;
- for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
- if (modp (y, c.channel().ySampling) == 0)
- bytesPerLine[i] += nBytes;
- }
- size_t maxBytesPerLine = 0;
- for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
- if (maxBytesPerLine < bytesPerLine[i])
- maxBytesPerLine = bytesPerLine[i];
- return maxBytesPerLine;
- }
- void
- offsetInLineBufferTable (const vector<size_t> &bytesPerLine,
- int linesInLineBuffer,
- vector<size_t> &offsetInLineBuffer)
- {
- offsetInLineBuffer.resize (bytesPerLine.size());
- size_t offset = 0;
- for (int i = 0; i < bytesPerLine.size(); ++i)
- {
- if (i % linesInLineBuffer == 0)
- offset = 0;
- offsetInLineBuffer[i] = offset;
- offset += bytesPerLine[i];
- }
- }
- int
- lineBufferMinY (int y, int minY, int linesInLineBuffer)
- {
- return ((y - minY) / linesInLineBuffer) * linesInLineBuffer + minY;
- }
- int
- lineBufferMaxY (int y, int minY, int linesInLineBuffer)
- {
- return lineBufferMinY (y, minY, linesInLineBuffer) + linesInLineBuffer - 1;
- }
- Compressor::Format
- defaultFormat (Compressor * compressor)
- {
- return compressor? compressor->format(): Compressor::XDR;
- }
- int
- numLinesInBuffer (Compressor * compressor)
- {
- return compressor? compressor->numScanLines(): 1;
- }
- void
- copyIntoFrameBuffer (const char *& readPtr,
- char * writePtr,
- char * endPtr,
- size_t xStride,
- bool fill,
- double fillValue,
- Compressor::Format format,
- PixelType typeInFrameBuffer,
- PixelType typeInFile)
- {
- //
- // Copy a horizontal row of pixels from an input
- // file's line or tile buffer to a frame buffer.
- //
- if (fill)
- {
- //
- // The file contains no data for this channel.
- // Store a default value in the frame buffer.
- //
- switch (typeInFrameBuffer)
- {
- case UINT:
-
- {
- unsigned int fillVal = (unsigned int) (fillValue);
- while (writePtr <= endPtr)
- {
- *(unsigned int *) writePtr = fillVal;
- writePtr += xStride;
- }
- }
- break;
- case HALF:
- {
- half fillVal = half (fillValue);
- while (writePtr <= endPtr)
- {
- *(half *) writePtr = fillVal;
- writePtr += xStride;
- }
- }
- break;
- case FLOAT:
- {
- float fillVal = float (fillValue);
- while (writePtr <= endPtr)
- {
- *(float *) writePtr = fillVal;
- writePtr += xStride;
- }
- }
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- else if (format == Compressor::XDR)
- {
- //
- // The the line or tile buffer is in XDR format.
- //
- // Convert the pixels from the file's machine-
- // independent representation, and store the
- // results in the frame buffer.
- //
- switch (typeInFrameBuffer)
- {
- case UINT:
-
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- Xdr::read <CharPtrIO> (readPtr, *(unsigned int *) writePtr);
- writePtr += xStride;
- }
- break;
- case HALF:
- while (writePtr <= endPtr)
- {
- half h;
- Xdr::read <CharPtrIO> (readPtr, h);
- *(unsigned int *) writePtr = halfToUint (h);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- float f;
- Xdr::read <CharPtrIO> (readPtr, f);
- *(unsigned int *)writePtr = floatToUint (f);
- writePtr += xStride;
- }
- break;
- }
- break;
- case HALF:
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- unsigned int ui;
- Xdr::read <CharPtrIO> (readPtr, ui);
- *(half *) writePtr = uintToHalf (ui);
- writePtr += xStride;
- }
- break;
-
- case HALF:
- while (writePtr <= endPtr)
- {
- Xdr::read <CharPtrIO> (readPtr, *(half *) writePtr);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- float f;
- Xdr::read <CharPtrIO> (readPtr, f);
- *(half *) writePtr = floatToHalf (f);
- writePtr += xStride;
- }
- break;
- }
- break;
- case FLOAT:
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- unsigned int ui;
- Xdr::read <CharPtrIO> (readPtr, ui);
- *(float *) writePtr = float (ui);
- writePtr += xStride;
- }
- break;
- case HALF:
- while (writePtr <= endPtr)
- {
- half h;
- Xdr::read <CharPtrIO> (readPtr, h);
- *(float *) writePtr = float (h);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- Xdr::read <CharPtrIO> (readPtr, *(float *) writePtr);
- writePtr += xStride;
- }
- break;
- }
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- else
- {
- //
- // The the line or tile buffer is in NATIVE format.
- // Copy the results into the frame buffer.
- //
- switch (typeInFrameBuffer)
- {
- case UINT:
-
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- for (size_t i = 0; i < sizeof (unsigned int); ++i)
- writePtr[i] = readPtr[i];
- readPtr += sizeof (unsigned int);
- writePtr += xStride;
- }
- break;
- case HALF:
- while (writePtr <= endPtr)
- {
- half h = *(half *) readPtr;
- *(unsigned int *) writePtr = halfToUint (h);
- readPtr += sizeof (half);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- float f;
- for (size_t i = 0; i < sizeof (float); ++i)
- ((char *)&f)[i] = readPtr[i];
- *(unsigned int *)writePtr = floatToUint (f);
- readPtr += sizeof (float);
- writePtr += xStride;
- }
- break;
- }
- break;
- case HALF:
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- unsigned int ui;
- for (size_t i = 0; i < sizeof (unsigned int); ++i)
- ((char *)&ui)[i] = readPtr[i];
- *(half *) writePtr = uintToHalf (ui);
- readPtr += sizeof (unsigned int);
- writePtr += xStride;
- }
- break;
- case HALF:
- while (writePtr <= endPtr)
- {
- *(half *) writePtr = *(half *)readPtr;
- readPtr += sizeof (half);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- float f;
- for (size_t i = 0; i < sizeof (float); ++i)
- ((char *)&f)[i] = readPtr[i];
- *(half *) writePtr = floatToHalf (f);
- readPtr += sizeof (float);
- writePtr += xStride;
- }
- break;
- }
- break;
- case FLOAT:
- switch (typeInFile)
- {
- case UINT:
- while (writePtr <= endPtr)
- {
- unsigned int ui;
- for (size_t i = 0; i < sizeof (unsigned int); ++i)
- ((char *)&ui)[i] = readPtr[i];
- *(float *) writePtr = float (ui);
- readPtr += sizeof (unsigned int);
- writePtr += xStride;
- }
- break;
- case HALF:
- while (writePtr <= endPtr)
- {
- half h = *(half *) readPtr;
- *(float *) writePtr = float (h);
- readPtr += sizeof (half);
- writePtr += xStride;
- }
- break;
- case FLOAT:
- while (writePtr <= endPtr)
- {
- for (size_t i = 0; i < sizeof (float); ++i)
- writePtr[i] = readPtr[i];
- readPtr += sizeof (float);
- writePtr += xStride;
- }
- break;
- }
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- }
- void
- skipChannel (const char *& readPtr,
- PixelType typeInFile,
- size_t xSize)
- {
- switch (typeInFile)
- {
- case UINT:
-
- Xdr::skip <CharPtrIO> (readPtr, Xdr::size <unsigned int> () * xSize);
- break;
- case HALF:
- Xdr::skip <CharPtrIO> (readPtr, Xdr::size <half> () * xSize);
- break;
- case FLOAT:
- Xdr::skip <CharPtrIO> (readPtr, Xdr::size <float> () * xSize);
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- void
- convertInPlace (char *& writePtr,
- const char *& readPtr,
- PixelType type,
- size_t numPixels)
- {
- switch (type)
- {
- case UINT:
-
- for (int j = 0; j < numPixels; ++j)
- {
- Xdr::write <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
- readPtr += sizeof(unsigned int);
- }
- break;
-
- case HALF:
-
- for (int j = 0; j < numPixels; ++j)
- {
- Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
- readPtr += sizeof(half);
- }
- break;
-
- case FLOAT:
-
- for (int j = 0; j < numPixels; ++j)
- {
- Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
- readPtr += sizeof(float);
- }
- break;
-
- default:
-
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- void
- copyFromFrameBuffer (char *& writePtr,
- const char *& readPtr,
- const char * endPtr,
- size_t xStride,
- Compressor::Format format,
- PixelType type)
- {
- //
- // Copy a horizontal row of pixels from a frame
- // buffer to an output file's line or tile buffer.
- //
- if (format == Compressor::XDR)
- {
- //
- // The the line or tile buffer is in XDR format.
- //
- switch (type)
- {
- case UINT:
- while (readPtr <= endPtr)
- {
- Xdr::write <CharPtrIO> (writePtr,
- *(const unsigned int *) readPtr);
- readPtr += xStride;
- }
- break;
- case HALF:
- while (readPtr <= endPtr)
- {
- Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
- readPtr += xStride;
- }
- break;
- case FLOAT:
- while (readPtr <= endPtr)
- {
- Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
- readPtr += xStride;
- }
- break;
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- else
- {
- //
- // The the line or tile buffer is in NATIVE format.
- //
- switch (type)
- {
- case UINT:
- while (readPtr <= endPtr)
- {
- for (size_t i = 0; i < sizeof (unsigned int); ++i)
- *writePtr++ = readPtr[i];
- readPtr += xStride;
- }
- break;
- case HALF:
- while (readPtr <= endPtr)
- {
- *(half *) writePtr = *(const half *) readPtr;
- writePtr += sizeof (half);
- readPtr += xStride;
- }
- break;
- case FLOAT:
- while (readPtr <= endPtr)
- {
- for (size_t i = 0; i < sizeof (float); ++i)
- *writePtr++ = readPtr[i];
- readPtr += xStride;
- }
- break;
-
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- }
- void
- fillChannelWithZeroes (char *& writePtr,
- Compressor::Format format,
- PixelType type,
- size_t xSize)
- {
- if (format == Compressor::XDR)
- {
- //
- // Fill with data in XDR format.
- //
- switch (type)
- {
- case UINT:
- for (int j = 0; j < xSize; ++j)
- Xdr::write <CharPtrIO> (writePtr, (unsigned int) 0);
- break;
- case HALF:
- for (int j = 0; j < xSize; ++j)
- Xdr::write <CharPtrIO> (writePtr, (half) 0);
- break;
- case FLOAT:
- for (int j = 0; j < xSize; ++j)
- Xdr::write <CharPtrIO> (writePtr, (float) 0);
- break;
-
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- else
- {
- //
- // Fill with data in NATIVE format.
- //
- switch (type)
- {
- case UINT:
- for (int j = 0; j < xSize; ++j)
- {
- static const unsigned int ui = 0;
- for (size_t i = 0; i < sizeof (ui); ++i)
- *writePtr++ = ((char *) &ui)[i];
- }
- break;
- case HALF:
- for (int j = 0; j < xSize; ++j)
- {
- *(half *) writePtr = half (0);
- writePtr += sizeof (half);
- }
- break;
- case FLOAT:
- for (int j = 0; j < xSize; ++j)
- {
- static const float f = 0;
- for (size_t i = 0; i < sizeof (f); ++i)
- *writePtr++ = ((char *) &f)[i];
- }
- break;
-
- default:
- throw Iex::ArgExc ("Unknown pixel data type.");
- }
- }
- }
- } // namespace Imf