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