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 //	Miscellaneous stuff related to tiled files
     39 //
     40 //-----------------------------------------------------------------------------
     41 
     42 #include <ImfTiledMisc.h>
     43 #include "Iex.h"
     44 #include <ImfMisc.h>
     45 #include <ImfChannelList.h>
     46 #include <algorithm> // for std::max()
     47 
     48 
     49 namespace Imf {
     50 
     51 using Imath::Box2i;
     52 using Imath::V2i;
     53 
     54 
     55 int
     56 levelSize (int min, int max, int l, LevelRoundingMode rmode)
     57 {
     58     if (l < 0)
     59     throw Iex::ArgExc ("Argument not in valid range.");
     60 
     61     int a = max - min + 1;
     62     int b = (1 << l);
     63     int size = a / b;
     64 
     65     if (rmode == ROUND_UP && size * b < a)
     66     size += 1;
     67 
     68     return std::max (size, 1);
     69 }
     70 
     71 
     72 Box2i
     73 dataWindowForLevel (const TileDescription &tileDesc,
     74             int minX, int maxX,
     75             int minY, int maxY,
     76             int lx, int ly)
     77 {
     78     V2i levelMin = V2i (minX, minY);
     79 
     80     V2i levelMax = levelMin +
     81            V2i (levelSize (minX, maxX, lx, tileDesc.roundingMode) - 1,
     82             levelSize (minY, maxY, ly, tileDesc.roundingMode) - 1);
     83 
     84     return Box2i(levelMin, levelMax);
     85 }
     86 
     87 
     88 Box2i
     89 dataWindowForTile (const TileDescription &tileDesc,
     90            int minX, int maxX,
     91            int minY, int maxY,
     92            int dx, int dy,
     93            int lx, int ly)
     94 {
     95     V2i tileMin = V2i (minX + dx * tileDesc.xSize,
     96                minY + dy * tileDesc.ySize);
     97 
     98     V2i tileMax = tileMin + V2i (tileDesc.xSize - 1, tileDesc.ySize - 1);
     99 
    100     V2i levelMax = dataWindowForLevel
    101                (tileDesc, minX, maxX, minY, maxY, lx, ly).max;
    102 
    103     tileMax = V2i (std::min (tileMax[0], levelMax[0]),
    104            std::min (tileMax[1], levelMax[1]));
    105 
    106     return Box2i (tileMin, tileMax);
    107 }
    108 
    109 
    110 size_t
    111 calculateBytesPerPixel (const Header &header)
    112 {
    113     const ChannelList &channels = header.channels();
    114 
    115     size_t bytesPerPixel = 0;
    116 
    117     for (ChannelList::ConstIterator c = channels.begin();
    118      c != channels.end();
    119      ++c)
    120     {
    121     bytesPerPixel += pixelTypeSize (c.channel().type);
    122     }
    123 
    124     return bytesPerPixel;
    125 }
    126 
    127 
    128 namespace {
    129 
    130 int
    131 floorLog2 (int x)
    132 {
    133     //
    134     // For x > 0, floorLog2(y) returns floor(log(x)/log(2)).
    135     //
    136 
    137     int y = 0;
    138 
    139     while (x > 1)
    140     {
    141     y +=  1;
    142     x >>= 1;
    143     }
    144 
    145     return y;
    146 }
    147 
    148 
    149 int
    150 ceilLog2 (int x)
    151 {
    152     //
    153     // For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)).
    154     //
    155 
    156     int y = 0;
    157     int r = 0;
    158 
    159     while (x > 1)
    160     {
    161     if (x & 1)
    162         r = 1;
    163 
    164     y +=  1;
    165     x >>= 1;
    166     }
    167 
    168     return y + r;
    169 }
    170 
    171 
    172 int
    173 roundLog2 (int x, LevelRoundingMode rmode)
    174 {
    175     return (rmode == ROUND_DOWN)? floorLog2 (x): ceilLog2 (x);
    176 }
    177 
    178 
    179 int
    180 calculateNumXLevels (const TileDescription& tileDesc,
    181              int minX, int maxX,
    182              int minY, int maxY)
    183 {
    184     int num = 0;
    185 
    186     switch (tileDesc.mode)
    187     {
    188       case ONE_LEVEL:
    189 
    190     num = 1;
    191     break;
    192 
    193       case MIPMAP_LEVELS:
    194 
    195     {
    196       int w = maxX - minX + 1;
    197       int h = maxY - minY + 1;
    198       num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
    199     }
    200         break;
    201 
    202       case RIPMAP_LEVELS:
    203 
    204     {
    205       int w = maxX - minX + 1;
    206       num = roundLog2 (w, tileDesc.roundingMode) + 1;
    207     }
    208     break;
    209 
    210       default:
    211 
    212     throw Iex::ArgExc ("Unknown LevelMode format.");
    213     }
    214 
    215     return num;
    216 }
    217 
    218 
    219 int
    220 calculateNumYLevels (const TileDescription& tileDesc,
    221              int minX, int maxX,
    222              int minY, int maxY)
    223 {
    224     int num = 0;
    225 
    226     switch (tileDesc.mode)
    227     {
    228       case ONE_LEVEL:
    229 
    230     num = 1;
    231     break;
    232 
    233       case MIPMAP_LEVELS:
    234 
    235     {
    236       int w = maxX - minX + 1;
    237       int h = maxY - minY + 1;
    238       num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
    239     }
    240         break;
    241 
    242       case RIPMAP_LEVELS:
    243 
    244     {
    245       int h = maxY - minY + 1;
    246       num = roundLog2 (h, tileDesc.roundingMode) + 1;
    247     }
    248     break;
    249 
    250       default:
    251 
    252     throw Iex::ArgExc ("Unknown LevelMode format.");
    253     }
    254 
    255     return num;
    256 }
    257 
    258 
    259 void
    260 calculateNumTiles (int *numTiles,
    261            int numLevels,
    262            int min, int max,
    263            int size,
    264            LevelRoundingMode rmode)
    265 {
    266     for (int i = 0; i < numLevels; i++)
    267     {
    268     numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size;
    269     }
    270 }
    271 
    272 } // namespace
    273 
    274 
    275 void
    276 precalculateTileInfo (const TileDescription& tileDesc,
    277               int minX, int maxX,
    278               int minY, int maxY,
    279               int *&numXTiles, int *&numYTiles,
    280               int &numXLevels, int &numYLevels)
    281 {
    282     numXLevels = calculateNumXLevels(tileDesc, minX, maxX, minY, maxY);
    283     numYLevels = calculateNumYLevels(tileDesc, minX, maxX, minY, maxY);
    284 
    285     numXTiles = new int[numXLevels];
    286     numYTiles = new int[numYLevels];
    287 
    288     calculateNumTiles (numXTiles,
    289                numXLevels,
    290                minX, maxX,
    291                tileDesc.xSize,
    292                tileDesc.roundingMode);
    293 
    294     calculateNumTiles (numYTiles,
    295                numYLevels,
    296                minY, maxY,
    297                tileDesc.ySize,
    298                tileDesc.roundingMode);
    299 }
    300 
    301 
    302 } // namespace Imf
    303