Home | History | Annotate | Download | only in IlmImf
      1 ///////////////////////////////////////////////////////////////////////////
      2 //
      3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
      4 // Digital Ltd. LLC
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions are
     10 // met:
     11 // *       Redistributions of source code must retain the above copyright
     12 // notice, this list of conditions and the following disclaimer.
     13 // *       Redistributions in binary form must reproduce the above
     14 // copyright notice, this list of conditions and the following disclaimer
     15 // in the documentation and/or other materials provided with the
     16 // distribution.
     17 // *       Neither the name of Industrial Light & Magic nor the names of
     18 // its contributors may be used to endorse or promote products derived
     19 // from this software without specific prior written permission.
     20 //
     21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32 //
     33 ///////////////////////////////////////////////////////////////////////////
     34 
     35 
     36 
     37 //-----------------------------------------------------------------------------
     38 //
     39 //	Miscellaneous helper functions for OpenEXR image file I/O
     40 //
     41 //-----------------------------------------------------------------------------
     42 
     43 #include <ImfMisc.h>
     44 #include <ImfHeader.h>
     45 #include <ImfCompressor.h>
     46 #include <ImfChannelList.h>
     47 #include <ImfXdr.h>
     48 #include <ImathFun.h>
     49 #include <Iex.h>
     50 #include <ImfStdIO.h>
     51 #include <ImfConvert.h>
     52 
     53 namespace Imf {
     54 
     55 using Imath::Box2i;
     56 using Imath::divp;
     57 using Imath::modp;
     58 using std::vector;
     59 
     60 int
     61 pixelTypeSize (PixelType type)
     62 {
     63     int size;
     64 
     65     switch (type)
     66     {
     67       case UINT:
     68 
     69     size = Xdr::size <unsigned int> ();
     70     break;
     71 
     72       case HALF:
     73 
     74     size = Xdr::size <half> ();
     75     break;
     76 
     77       case FLOAT:
     78 
     79     size = Xdr::size <float> ();
     80     break;
     81 
     82       default:
     83 
     84     throw Iex::ArgExc ("Unknown pixel type.");
     85     }
     86 
     87     return size;
     88 }
     89 
     90 
     91 int
     92 numSamples (int s, int a, int b)
     93 {
     94     int a1 = divp (a, s);
     95     int b1 = divp (b, s);
     96     return  b1 - a1 + ((a1 * s < a)? 0: 1);
     97 }
     98 
     99 
    100 size_t
    101 bytesPerLineTable (const Header &header,
    102            vector<size_t> &bytesPerLine)
    103 {
    104     const Box2i &dataWindow = header.dataWindow();
    105     const ChannelList &channels = header.channels();
    106 
    107     bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1);
    108 
    109     for (ChannelList::ConstIterator c = channels.begin();
    110      c != channels.end();
    111      ++c)
    112     {
    113     int nBytes = pixelTypeSize (c.channel().type) *
    114              (dataWindow.max.x - dataWindow.min.x + 1) /
    115              c.channel().xSampling;
    116 
    117     for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
    118         if (modp (y, c.channel().ySampling) == 0)
    119         bytesPerLine[i] += nBytes;
    120     }
    121 
    122     size_t maxBytesPerLine = 0;
    123 
    124     for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
    125     if (maxBytesPerLine < bytesPerLine[i])
    126         maxBytesPerLine = bytesPerLine[i];
    127 
    128     return maxBytesPerLine;
    129 }
    130 
    131 
    132 void
    133 offsetInLineBufferTable (const vector<size_t> &bytesPerLine,
    134              int linesInLineBuffer,
    135              vector<size_t> &offsetInLineBuffer)
    136 {
    137     offsetInLineBuffer.resize (bytesPerLine.size());
    138 
    139     size_t offset = 0;
    140 
    141     for (int i = 0; i < bytesPerLine.size(); ++i)
    142     {
    143     if (i % linesInLineBuffer == 0)
    144         offset = 0;
    145 
    146     offsetInLineBuffer[i] = offset;
    147     offset += bytesPerLine[i];
    148     }
    149 }
    150 
    151 
    152 int
    153 lineBufferMinY (int y, int minY, int linesInLineBuffer)
    154 {
    155     return ((y - minY) / linesInLineBuffer) * linesInLineBuffer + minY;
    156 }
    157 
    158 
    159 int
    160 lineBufferMaxY (int y, int minY, int linesInLineBuffer)
    161 {
    162     return lineBufferMinY (y, minY, linesInLineBuffer) + linesInLineBuffer - 1;
    163 }
    164 
    165 
    166 Compressor::Format
    167 defaultFormat (Compressor * compressor)
    168 {
    169     return compressor? compressor->format(): Compressor::XDR;
    170 }
    171 
    172 
    173 int
    174 numLinesInBuffer (Compressor * compressor)
    175 {
    176     return compressor? compressor->numScanLines(): 1;
    177 }
    178 
    179 
    180 void
    181 copyIntoFrameBuffer (const char *& readPtr,
    182              char * writePtr,
    183              char * endPtr,
    184                      size_t xStride,
    185              bool fill,
    186              double fillValue,
    187                      Compressor::Format format,
    188                      PixelType typeInFrameBuffer,
    189                      PixelType typeInFile)
    190 {
    191     //
    192     // Copy a horizontal row of pixels from an input
    193     // file's line or tile buffer to a frame buffer.
    194     //
    195 
    196     if (fill)
    197     {
    198         //
    199         // The file contains no data for this channel.
    200         // Store a default value in the frame buffer.
    201         //
    202 
    203         switch (typeInFrameBuffer)
    204         {
    205       case UINT:
    206 
    207             {
    208                 unsigned int fillVal = (unsigned int) (fillValue);
    209 
    210                 while (writePtr <= endPtr)
    211                 {
    212                     *(unsigned int *) writePtr = fillVal;
    213                     writePtr += xStride;
    214                 }
    215             }
    216             break;
    217 
    218           case HALF:
    219 
    220             {
    221                 half fillVal = half (fillValue);
    222 
    223                 while (writePtr <= endPtr)
    224                 {
    225                     *(half *) writePtr = fillVal;
    226                     writePtr += xStride;
    227                 }
    228             }
    229             break;
    230 
    231           case FLOAT:
    232 
    233             {
    234                 float fillVal = float (fillValue);
    235 
    236                 while (writePtr <= endPtr)
    237                 {
    238                     *(float *) writePtr = fillVal;
    239                     writePtr += xStride;
    240                 }
    241             }
    242             break;
    243 
    244           default:
    245 
    246             throw Iex::ArgExc ("Unknown pixel data type.");
    247         }
    248     }
    249     else if (format == Compressor::XDR)
    250     {
    251         //
    252         // The the line or tile buffer is in XDR format.
    253         //
    254         // Convert the pixels from the file's machine-
    255         // independent representation, and store the
    256         // results in the frame buffer.
    257         //
    258 
    259         switch (typeInFrameBuffer)
    260         {
    261           case UINT:
    262 
    263             switch (typeInFile)
    264             {
    265               case UINT:
    266 
    267                 while (writePtr <= endPtr)
    268                 {
    269                     Xdr::read <CharPtrIO> (readPtr, *(unsigned int *) writePtr);
    270                     writePtr += xStride;
    271                 }
    272                 break;
    273 
    274               case HALF:
    275 
    276                 while (writePtr <= endPtr)
    277                 {
    278                     half h;
    279                     Xdr::read <CharPtrIO> (readPtr, h);
    280                     *(unsigned int *) writePtr = halfToUint (h);
    281                     writePtr += xStride;
    282                 }
    283                 break;
    284 
    285               case FLOAT:
    286 
    287                 while (writePtr <= endPtr)
    288                 {
    289                     float f;
    290                     Xdr::read <CharPtrIO> (readPtr, f);
    291                     *(unsigned int *)writePtr = floatToUint (f);
    292                     writePtr += xStride;
    293                 }
    294                 break;
    295             }
    296             break;
    297 
    298           case HALF:
    299 
    300             switch (typeInFile)
    301             {
    302               case UINT:
    303 
    304                 while (writePtr <= endPtr)
    305                 {
    306                     unsigned int ui;
    307                     Xdr::read <CharPtrIO> (readPtr, ui);
    308                     *(half *) writePtr = uintToHalf (ui);
    309                     writePtr += xStride;
    310                 }
    311                 break;
    312 
    313               case HALF:
    314 
    315                 while (writePtr <= endPtr)
    316                 {
    317                     Xdr::read <CharPtrIO> (readPtr, *(half *) writePtr);
    318                     writePtr += xStride;
    319                 }
    320                 break;
    321 
    322               case FLOAT:
    323 
    324                 while (writePtr <= endPtr)
    325                 {
    326                     float f;
    327                     Xdr::read <CharPtrIO> (readPtr, f);
    328                     *(half *) writePtr = floatToHalf (f);
    329                     writePtr += xStride;
    330                 }
    331                 break;
    332             }
    333             break;
    334 
    335           case FLOAT:
    336 
    337             switch (typeInFile)
    338             {
    339               case UINT:
    340 
    341                 while (writePtr <= endPtr)
    342                 {
    343                     unsigned int ui;
    344                     Xdr::read <CharPtrIO> (readPtr, ui);
    345                     *(float *) writePtr = float (ui);
    346                     writePtr += xStride;
    347                 }
    348                 break;
    349 
    350               case HALF:
    351 
    352                 while (writePtr <= endPtr)
    353                 {
    354                     half h;
    355                     Xdr::read <CharPtrIO> (readPtr, h);
    356                     *(float *) writePtr = float (h);
    357                     writePtr += xStride;
    358                 }
    359                 break;
    360 
    361               case FLOAT:
    362 
    363                 while (writePtr <= endPtr)
    364                 {
    365                     Xdr::read <CharPtrIO> (readPtr, *(float *) writePtr);
    366                     writePtr += xStride;
    367                 }
    368                 break;
    369             }
    370             break;
    371 
    372           default:
    373 
    374             throw Iex::ArgExc ("Unknown pixel data type.");
    375         }
    376     }
    377     else
    378     {
    379         //
    380         // The the line or tile buffer is in NATIVE format.
    381         // Copy the results into the frame buffer.
    382         //
    383 
    384         switch (typeInFrameBuffer)
    385         {
    386           case UINT:
    387 
    388             switch (typeInFile)
    389             {
    390               case UINT:
    391 
    392                 while (writePtr <= endPtr)
    393                 {
    394                     for (size_t i = 0; i < sizeof (unsigned int); ++i)
    395                         writePtr[i] = readPtr[i];
    396 
    397                     readPtr += sizeof (unsigned int);
    398                     writePtr += xStride;
    399                 }
    400                 break;
    401 
    402               case HALF:
    403 
    404                 while (writePtr <= endPtr)
    405                 {
    406                     half h = *(half *) readPtr;
    407                     *(unsigned int *) writePtr = halfToUint (h);
    408                     readPtr += sizeof (half);
    409                     writePtr += xStride;
    410                 }
    411                 break;
    412 
    413               case FLOAT:
    414 
    415                 while (writePtr <= endPtr)
    416                 {
    417                     float f;
    418 
    419                     for (size_t i = 0; i < sizeof (float); ++i)
    420                         ((char *)&f)[i] = readPtr[i];
    421 
    422                     *(unsigned int *)writePtr = floatToUint (f);
    423                     readPtr += sizeof (float);
    424                     writePtr += xStride;
    425                 }
    426                 break;
    427             }
    428             break;
    429 
    430           case HALF:
    431 
    432             switch (typeInFile)
    433             {
    434               case UINT:
    435 
    436                 while (writePtr <= endPtr)
    437                 {
    438                     unsigned int ui;
    439 
    440                     for (size_t i = 0; i < sizeof (unsigned int); ++i)
    441                         ((char *)&ui)[i] = readPtr[i];
    442 
    443                     *(half *) writePtr = uintToHalf (ui);
    444                     readPtr += sizeof (unsigned int);
    445                     writePtr += xStride;
    446                 }
    447                 break;
    448 
    449               case HALF:
    450 
    451                 while (writePtr <= endPtr)
    452                 {
    453                     *(half *) writePtr = *(half *)readPtr;
    454                     readPtr += sizeof (half);
    455                     writePtr += xStride;
    456                 }
    457                 break;
    458 
    459               case FLOAT:
    460 
    461                 while (writePtr <= endPtr)
    462                 {
    463                     float f;
    464 
    465                     for (size_t i = 0; i < sizeof (float); ++i)
    466                         ((char *)&f)[i] = readPtr[i];
    467 
    468                     *(half *) writePtr = floatToHalf (f);
    469                     readPtr += sizeof (float);
    470                     writePtr += xStride;
    471                 }
    472                 break;
    473             }
    474             break;
    475 
    476           case FLOAT:
    477 
    478             switch (typeInFile)
    479             {
    480               case UINT:
    481 
    482                 while (writePtr <= endPtr)
    483                 {
    484                     unsigned int ui;
    485 
    486                     for (size_t i = 0; i < sizeof (unsigned int); ++i)
    487                         ((char *)&ui)[i] = readPtr[i];
    488 
    489                     *(float *) writePtr = float (ui);
    490                     readPtr += sizeof (unsigned int);
    491                     writePtr += xStride;
    492                 }
    493                 break;
    494 
    495               case HALF:
    496 
    497                 while (writePtr <= endPtr)
    498                 {
    499                     half h = *(half *) readPtr;
    500                     *(float *) writePtr = float (h);
    501                     readPtr += sizeof (half);
    502                     writePtr += xStride;
    503                 }
    504                 break;
    505 
    506               case FLOAT:
    507 
    508                 while (writePtr <= endPtr)
    509                 {
    510                     for (size_t i = 0; i < sizeof (float); ++i)
    511                         writePtr[i] = readPtr[i];
    512 
    513                     readPtr += sizeof (float);
    514                     writePtr += xStride;
    515                 }
    516                 break;
    517             }
    518             break;
    519 
    520           default:
    521 
    522             throw Iex::ArgExc ("Unknown pixel data type.");
    523         }
    524     }
    525 }
    526 
    527 
    528 void
    529 skipChannel (const char *& readPtr,
    530              PixelType typeInFile,
    531          size_t xSize)
    532 {
    533     switch (typeInFile)
    534     {
    535       case UINT:
    536 
    537         Xdr::skip <CharPtrIO> (readPtr, Xdr::size <unsigned int> () * xSize);
    538         break;
    539 
    540       case HALF:
    541 
    542         Xdr::skip <CharPtrIO> (readPtr, Xdr::size <half> () * xSize);
    543         break;
    544 
    545       case FLOAT:
    546 
    547         Xdr::skip <CharPtrIO> (readPtr, Xdr::size <float> () * xSize);
    548         break;
    549 
    550       default:
    551 
    552         throw Iex::ArgExc ("Unknown pixel data type.");
    553     }
    554 }
    555 
    556 
    557 void
    558 convertInPlace (char *& writePtr,
    559                 const char *& readPtr,
    560         PixelType type,
    561                 size_t numPixels)
    562 {
    563     switch (type)
    564     {
    565       case UINT:
    566 
    567         for (int j = 0; j < numPixels; ++j)
    568         {
    569             Xdr::write <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
    570             readPtr += sizeof(unsigned int);
    571         }
    572         break;
    573 
    574       case HALF:
    575 
    576         for (int j = 0; j < numPixels; ++j)
    577         {
    578             Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
    579             readPtr += sizeof(half);
    580         }
    581         break;
    582 
    583       case FLOAT:
    584 
    585         for (int j = 0; j < numPixels; ++j)
    586         {
    587             Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
    588             readPtr += sizeof(float);
    589         }
    590         break;
    591 
    592       default:
    593 
    594         throw Iex::ArgExc ("Unknown pixel data type.");
    595     }
    596 }
    597 
    598 
    599 void
    600 copyFromFrameBuffer (char *& writePtr,
    601              const char *& readPtr,
    602                      const char * endPtr,
    603              size_t xStride,
    604                      Compressor::Format format,
    605              PixelType type)
    606 {
    607     //
    608     // Copy a horizontal row of pixels from a frame
    609     // buffer to an output file's line or tile buffer.
    610     //
    611 
    612     if (format == Compressor::XDR)
    613     {
    614         //
    615         // The the line or tile buffer is in XDR format.
    616         //
    617 
    618         switch (type)
    619         {
    620           case UINT:
    621 
    622             while (readPtr <= endPtr)
    623             {
    624                 Xdr::write <CharPtrIO> (writePtr,
    625                                         *(const unsigned int *) readPtr);
    626                 readPtr += xStride;
    627             }
    628             break;
    629 
    630           case HALF:
    631 
    632             while (readPtr <= endPtr)
    633             {
    634                 Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
    635                 readPtr += xStride;
    636             }
    637             break;
    638 
    639           case FLOAT:
    640 
    641             while (readPtr <= endPtr)
    642             {
    643                 Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
    644                 readPtr += xStride;
    645             }
    646             break;
    647 
    648           default:
    649 
    650             throw Iex::ArgExc ("Unknown pixel data type.");
    651         }
    652     }
    653     else
    654     {
    655         //
    656         // The the line or tile buffer is in NATIVE format.
    657         //
    658 
    659         switch (type)
    660         {
    661           case UINT:
    662 
    663             while (readPtr <= endPtr)
    664             {
    665                 for (size_t i = 0; i < sizeof (unsigned int); ++i)
    666                     *writePtr++ = readPtr[i];
    667 
    668                 readPtr += xStride;
    669             }
    670             break;
    671 
    672           case HALF:
    673 
    674             while (readPtr <= endPtr)
    675             {
    676                 *(half *) writePtr = *(const half *) readPtr;
    677                 writePtr += sizeof (half);
    678                 readPtr += xStride;
    679             }
    680             break;
    681 
    682           case FLOAT:
    683 
    684             while (readPtr <= endPtr)
    685             {
    686                 for (size_t i = 0; i < sizeof (float); ++i)
    687                     *writePtr++ = readPtr[i];
    688 
    689                 readPtr += xStride;
    690             }
    691             break;
    692 
    693           default:
    694 
    695             throw Iex::ArgExc ("Unknown pixel data type.");
    696         }
    697     }
    698 }
    699 
    700 
    701 void
    702 fillChannelWithZeroes (char *& writePtr,
    703                Compressor::Format format,
    704                PixelType type,
    705                size_t xSize)
    706 {
    707     if (format == Compressor::XDR)
    708     {
    709         //
    710         // Fill with data in XDR format.
    711         //
    712 
    713         switch (type)
    714         {
    715           case UINT:
    716 
    717             for (int j = 0; j < xSize; ++j)
    718                 Xdr::write <CharPtrIO> (writePtr, (unsigned int) 0);
    719 
    720             break;
    721 
    722           case HALF:
    723 
    724             for (int j = 0; j < xSize; ++j)
    725                 Xdr::write <CharPtrIO> (writePtr, (half) 0);
    726 
    727             break;
    728 
    729           case FLOAT:
    730 
    731             for (int j = 0; j < xSize; ++j)
    732                 Xdr::write <CharPtrIO> (writePtr, (float) 0);
    733 
    734             break;
    735 
    736           default:
    737 
    738             throw Iex::ArgExc ("Unknown pixel data type.");
    739         }
    740     }
    741     else
    742     {
    743         //
    744         // Fill with data in NATIVE format.
    745         //
    746 
    747         switch (type)
    748         {
    749           case UINT:
    750 
    751             for (int j = 0; j < xSize; ++j)
    752             {
    753                 static const unsigned int ui = 0;
    754 
    755                 for (size_t i = 0; i < sizeof (ui); ++i)
    756                     *writePtr++ = ((char *) &ui)[i];
    757             }
    758             break;
    759 
    760           case HALF:
    761 
    762             for (int j = 0; j < xSize; ++j)
    763             {
    764                 *(half *) writePtr = half (0);
    765                 writePtr += sizeof (half);
    766             }
    767             break;
    768 
    769           case FLOAT:
    770 
    771             for (int j = 0; j < xSize; ++j)
    772             {
    773                 static const float f = 0;
    774 
    775                 for (size_t i = 0; i < sizeof (f); ++i)
    776                     *writePtr++ = ((char *) &f)[i];
    777             }
    778             break;
    779 
    780           default:
    781 
    782             throw Iex::ArgExc ("Unknown pixel data type.");
    783         }
    784     }
    785 }
    786 
    787 } // namespace Imf
    788