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