"Fossies" - the Fresh Open Source Software Archive

Member "aqsis-1.8.2/libs/tex/io/exrinputfile.cpp" (24 Aug 2012, 7299 Bytes) of package /linux/privat/aqsis-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Aqsis
    2 // Copyright (C) 2001, Paul C. Gregory and the other authors and contributors
    3 // All rights reserved.
    4 //
    5 // Redistribution and use in source and binary forms, with or without
    6 // modification, are permitted provided that the following conditions are met:
    7 //
    8 // * Redistributions of source code must retain the above copyright notice,
    9 //   this list of conditions and the following disclaimer.
   10 // * Redistributions in binary form must reproduce the above copyright notice,
   11 //   this list of conditions and the following disclaimer in the documentation
   12 //   and/or other materials provided with the distribution.
   13 // * Neither the name of the software's owners nor the names of its
   14 //   contributors may be used to endorse or promote products derived from this
   15 //   software without specific prior written permission.
   16 //
   17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 // POSSIBILITY OF SUCH DAMAGE.
   28 //
   29 // (This is the New BSD license)
   30 
   31 /** \file
   32  *
   33  * \brief Scanline-oriented pixel access for OpenEXR input - implementation.
   34  *
   35  * \author Chris Foster  chris42f _at_ gmail.com
   36  *
   37  */
   38 
   39 #include "exrinputfile.h"
   40 
   41 #include <algorithm>
   42 #include <cctype>
   43 
   44 #include <OpenEXR/ImfInputFile.h>
   45 #include <OpenEXR/ImfChannelList.h>
   46 #include <OpenEXR/ImfFrameBuffer.h>
   47 #include <OpenEXR/Iex.h>
   48 
   49 #include <aqsis/util/logging.h>
   50 #include <aqsis/tex/texexception.h>
   51 
   52 namespace Aqsis {
   53 
   54 //------------------------------------------------------------------------------
   55 /// Implementation of some helper functions
   56 
   57 /// Get the aqsistex channel type corresponding to an OpenEXR channel type
   58 EqChannelType channelTypeFromExr(Imf::PixelType exrType)
   59 {
   60     switch(exrType)
   61     {
   62         case Imf::UINT:
   63             return Channel_Unsigned32;
   64         case Imf::FLOAT:
   65             return Channel_Float32;
   66         case Imf::HALF:
   67             return Channel_Float16;
   68         default:
   69             AQSIS_THROW_XQERROR(XqInternal, EqE_Bug, "Unknown OpenEXR pixel type");
   70     }
   71 }
   72 
   73 Imf::PixelType exrChannelType(EqChannelType type)
   74 {
   75     switch(type)
   76     {
   77         case Channel_Unsigned32:
   78             return Imf::UINT;
   79         case Channel_Float32:
   80             return Imf::FLOAT;
   81         case Channel_Float16:
   82             return Imf::HALF;
   83         default:
   84                 AQSIS_THROW_XQERROR(XqInternal, EqE_Bug,
   85                         "Unsupported output pixel type for OpenEXR");
   86     }
   87 }
   88 
   89 /** \brief Get a compression string from an OpenEXR compression type
   90  *
   91  * \param compression - OpenEXR compression enum
   92  * \return short descriptive string describing the compression scheme.
   93  */
   94 const char* exrCompressionToString(Imf::Compression compression)
   95 {
   96     /// \todo Try to adjust these names to correspond better with TIFF?
   97     switch(compression)
   98     {
   99         case Imf::RLE_COMPRESSION:
  100             // run length encoding
  101             return "rle";
  102         case Imf::ZIPS_COMPRESSION:
  103             // zlib compression, one scan line at a time
  104             return "zips";
  105         case Imf::ZIP_COMPRESSION:
  106             // zlib compression, in blocks of 16 scan lines
  107             return "zip";
  108         case Imf::PIZ_COMPRESSION:
  109             // piz-based wavelet compression
  110             return "piz";
  111         case Imf::PXR24_COMPRESSION:
  112             // lossy 24-bit float compression
  113             return "pixar24";
  114         case Imf::NO_COMPRESSION:
  115             // no compression
  116             return "none";
  117         default:
  118             return "unknown";
  119     }
  120 }
  121 
  122 /** \brief Convert an OpenEXR header to our own header representation.
  123  *
  124  * \param exrHeader - input header
  125  * \param header - output header
  126  */
  127 void convertHeader(const Imf::Header& exrHeader, CqTexFileHeader& header)
  128 {
  129     // Set width, height
  130     const Imath::Box2i& dataBox = exrHeader.dataWindow();
  131     header.setWidth(dataBox.max.x - dataBox.min.x+1);
  132     header.setHeight(dataBox.max.y - dataBox.min.y+1);
  133     // display window
  134     const Imath::Box2i& displayBox = exrHeader.displayWindow();
  135     header.set<Attr::DisplayWindow>( SqImageRegion(
  136                 displayBox.max.x - displayBox.min.x,
  137                 displayBox.max.y - displayBox.min.y,
  138                 displayBox.min.x - dataBox.min.x,
  139                 displayBox.min.y - dataBox.min.y) );
  140 
  141     // Set tiling information ?
  142 
  143     // Aspect ratio
  144     header.set<Attr::PixelAspectRatio>(exrHeader.pixelAspectRatio());
  145 
  146     TqChannelNameMap channelNameMap;
  147     // Convert channel representation
  148     const Imf::ChannelList& exrChannels = exrHeader.channels();
  149     CqChannelList& channels = header.channelList();
  150     for(Imf::ChannelList::ConstIterator i = exrChannels.begin();
  151             i != exrChannels.end(); ++i)
  152     {
  153         // use lower case names for channels; OpenEXR uses upper case.
  154         std::string chanName = i.name();
  155         std::transform(chanName.begin(), chanName.end(), chanName.begin(),
  156                 ::tolower);
  157         channelNameMap[chanName] = i.name();
  158         channels.addChannel( SqChannelInfo(chanName,
  159                 channelTypeFromExr(i.channel().type)) );
  160     }
  161     header.set<Attr::ExrChannelNameMap>(channelNameMap);
  162     channels.reorderChannels();
  163 
  164     // Set compresssion type
  165     header.set<Attr::Compression>(exrCompressionToString(exrHeader.compression()));
  166 }
  167 
  168 //------------------------------------------------------------------------------
  169 // CqExrInputFile - implementation
  170 
  171 CqExrInputFile::CqExrInputFile(const boostfs::path& fileName)
  172     : m_header(),
  173     m_exrFile()
  174 {
  175     try
  176     {
  177         m_exrFile.reset(new Imf::InputFile(native(fileName).c_str()));
  178     }
  179     catch(Iex::BaseExc &e)
  180     {
  181         AQSIS_THROW_XQERROR(XqBadTexture, EqE_BadFile, e.what());
  182     }
  183     convertHeader(m_exrFile->header(), m_header);
  184 }
  185 
  186 /*
  187 CqExrInputFile::CqExrInputFile(std::istream& inStream)
  188     : m_header(),
  189     m_exrFile()
  190 {
  191     initialize();
  192 }
  193 */
  194 
  195 boostfs::path CqExrInputFile::fileName() const
  196 {
  197     return m_exrFile->fileName();
  198 }
  199 
  200 void CqExrInputFile::readPixelsImpl(TqUint8* buffer,
  201         TqInt startLine, TqInt numScanlines) const
  202 {
  203     // correct the start line for OpenEXR conventions
  204     const Imath::Box2i& dataWindow = m_exrFile->header().dataWindow();
  205     startLine += dataWindow.min.y;
  206     // Set up an OpenEXR framebuffer
  207     Imf::FrameBuffer frameBuffer;
  208     const CqChannelList& channels = m_header.channelList();
  209     const TqChannelNameMap& nameMap = m_header.find<Attr::ExrChannelNameMap>();
  210     const TqInt xStride = channels.bytesPerPixel();
  211     const TqInt yStride = m_header.width()*xStride;
  212     // In OpenEXR, the buffer base pointer is assumed to point at the
  213     // coordinates of the (0,0) pixel.  We need to correct our buffer pointer
  214     // by subtracting the offset to (0,0) from the start of the data.
  215     buffer -= dataWindow.min.x*xStride + dataWindow.min.y*yStride;
  216     for(TqInt i = 0; i < channels.numChannels(); ++i)
  217     {
  218         frameBuffer.insert(nameMap.find(channels[i].name)->second.c_str(),
  219                 Imf::Slice(
  220                     exrChannelType(channels[i].type),
  221                     reinterpret_cast<char*>(buffer + channels.channelByteOffset(i)),
  222                     xStride,
  223                     yStride
  224                     )
  225                 );
  226     }
  227     m_exrFile->setFrameBuffer(frameBuffer);
  228     // Read in the pixels
  229     m_exrFile->readPixels(startLine, startLine + numScanlines - 1);
  230 }
  231 
  232 } // namespace Aqsis