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 #ifndef INCLUDED_IMF_TILED_OUTPUT_FILE_H 37 #define INCLUDED_IMF_TILED_OUTPUT_FILE_H 38 39 //----------------------------------------------------------------------------- 40 // 41 // class TiledOutputFile 42 // 43 //----------------------------------------------------------------------------- 44 45 #include <ImfHeader.h> 46 #include <ImfFrameBuffer.h> 47 #include "ImathBox.h" 48 #include <ImfTileDescription.h> 49 #include <ImfThreading.h> 50 51 namespace Imf { 52 53 class TiledInputFile; 54 class InputFile; 55 struct PreviewRgba; 56 57 58 class TiledOutputFile 59 { 60 public: 61 62 //------------------------------------------------------------------- 63 // A constructor that opens the file with the specified name, and 64 // writes the file header. The file header is also copied into the 65 // TiledOutputFile object, and can later be accessed via the header() 66 // method. 67 // 68 // Destroying TiledOutputFile constructed with this constructor 69 // automatically closes the corresponding files. 70 // 71 // The header must contain a TileDescriptionAttribute called "tiles". 72 // 73 // The x and y subsampling factors for all image channels must be 1; 74 // subsampling is not supported. 75 // 76 // Tiles can be written to the file in arbitrary order. The line 77 // order attribute can be used to cause the tiles to be sorted in 78 // the file. When the file is read later, reading the tiles in the 79 // same order as they are in the file tends to be significantly 80 // faster than reading the tiles in random order (see writeTile, 81 // below). 82 //------------------------------------------------------------------- 83 84 TiledOutputFile (const char fileName[], 85 const Header &header, 86 int numThreads = globalThreadCount ()); 87 88 89 // ---------------------------------------------------------------- 90 // A constructor that attaches the new TiledOutputFile object to 91 // a file that has already been opened. Destroying TiledOutputFile 92 // objects constructed with this constructor does not automatically 93 // close the corresponding files. 94 // ---------------------------------------------------------------- 95 96 TiledOutputFile (OStream &os, 97 const Header &header, 98 int numThreads = globalThreadCount ()); 99 100 101 //----------------------------------------------------- 102 // Destructor 103 // 104 // Destroying a TiledOutputFile object before all tiles 105 // have been written results in an incomplete file. 106 //----------------------------------------------------- 107 108 virtual ~TiledOutputFile (); 109 110 111 //------------------------ 112 // Access to the file name 113 //------------------------ 114 115 const char * fileName () const; 116 117 118 //-------------------------- 119 // Access to the file header 120 //-------------------------- 121 122 const Header & header () const; 123 124 125 //------------------------------------------------------- 126 // Set the current frame buffer -- copies the FrameBuffer 127 // object into the TiledOutputFile object. 128 // 129 // The current frame buffer is the source of the pixel 130 // data written to the file. The current frame buffer 131 // must be set at least once before writeTile() is 132 // called. The current frame buffer can be changed 133 // after each call to writeTile(). 134 //------------------------------------------------------- 135 136 void setFrameBuffer (const FrameBuffer &frameBuffer); 137 138 139 //----------------------------------- 140 // Access to the current frame buffer 141 //----------------------------------- 142 143 const FrameBuffer & frameBuffer () const; 144 145 146 //------------------- 147 // Utility functions: 148 //------------------- 149 150 //--------------------------------------------------------- 151 // Multiresolution mode and tile size: 152 // The following functions return the xSize, ySize and mode 153 // fields of the file header's TileDescriptionAttribute. 154 //--------------------------------------------------------- 155 156 unsigned int tileXSize () const; 157 unsigned int tileYSize () const; 158 LevelMode levelMode () const; 159 LevelRoundingMode levelRoundingMode () const; 160 161 162 //-------------------------------------------------------------------- 163 // Number of levels: 164 // 165 // numXLevels() returns the file's number of levels in x direction. 166 // 167 // if levelMode() == ONE_LEVEL: 168 // return value is: 1 169 // 170 // if levelMode() == MIPMAP_LEVELS: 171 // return value is: rfunc (log (max (w, h)) / log (2)) + 1 172 // 173 // if levelMode() == RIPMAP_LEVELS: 174 // return value is: rfunc (log (w) / log (2)) + 1 175 // 176 // where 177 // w is the width of the image's data window, max.x - min.x + 1, 178 // y is the height of the image's data window, max.y - min.y + 1, 179 // and rfunc(x) is either floor(x), or ceil(x), depending on 180 // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. 181 // 182 // numYLevels() returns the file's number of levels in y direction. 183 // 184 // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: 185 // return value is the same as for numXLevels() 186 // 187 // if levelMode() == RIPMAP_LEVELS: 188 // return value is: rfunc (log (h) / log (2)) + 1 189 // 190 // 191 // numLevels() is a convenience function for use with MIPMAP_LEVELS 192 // files. 193 // 194 // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: 195 // return value is the same as for numXLevels() 196 // 197 // if levelMode() == RIPMAP_LEVELS: 198 // an Iex::LogicExc exception is thrown 199 // 200 // isValidLevel(lx, ly) returns true if the file contains 201 // a level with level number (lx, ly), false if not. 202 // 203 //-------------------------------------------------------------------- 204 205 int numLevels () const; 206 int numXLevels () const; 207 int numYLevels () const; 208 bool isValidLevel (int lx, int ly) const; 209 210 211 //--------------------------------------------------------- 212 // Dimensions of a level: 213 // 214 // levelWidth(lx) returns the width of a level with level 215 // number (lx, *), where * is any number. 216 // 217 // return value is: 218 // max (1, rfunc (w / pow (2, lx))) 219 // 220 // 221 // levelHeight(ly) returns the height of a level with level 222 // number (*, ly), where * is any number. 223 // 224 // return value is: 225 // max (1, rfunc (h / pow (2, ly))) 226 // 227 //--------------------------------------------------------- 228 229 int levelWidth (int lx) const; 230 int levelHeight (int ly) const; 231 232 233 //---------------------------------------------------------- 234 // Number of tiles: 235 // 236 // numXTiles(lx) returns the number of tiles in x direction 237 // that cover a level with level number (lx, *), where * is 238 // any number. 239 // 240 // return value is: 241 // (levelWidth(lx) + tileXSize() - 1) / tileXSize() 242 // 243 // 244 // numYTiles(ly) returns the number of tiles in y direction 245 // that cover a level with level number (*, ly), where * is 246 // any number. 247 // 248 // return value is: 249 // (levelHeight(ly) + tileXSize() - 1) / tileXSize() 250 // 251 //---------------------------------------------------------- 252 253 int numXTiles (int lx = 0) const; 254 int numYTiles (int ly = 0) const; 255 256 257 //--------------------------------------------------------- 258 // Level pixel ranges: 259 // 260 // dataWindowForLevel(lx, ly) returns a 2-dimensional 261 // region of valid pixel coordinates for a level with 262 // level number (lx, ly) 263 // 264 // return value is a Box2i with min value: 265 // (dataWindow.min.x, dataWindow.min.y) 266 // 267 // and max value: 268 // (dataWindow.min.x + levelWidth(lx) - 1, 269 // dataWindow.min.y + levelHeight(ly) - 1) 270 // 271 // dataWindowForLevel(level) is a convenience function used 272 // for ONE_LEVEL and MIPMAP_LEVELS files. It returns 273 // dataWindowForLevel(level, level). 274 // 275 //--------------------------------------------------------- 276 277 Imath::Box2i dataWindowForLevel (int l = 0) const; 278 Imath::Box2i dataWindowForLevel (int lx, int ly) const; 279 280 281 //------------------------------------------------------------------- 282 // Tile pixel ranges: 283 // 284 // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional 285 // region of valid pixel coordinates for a tile with tile coordinates 286 // (dx,dy) and level number (lx, ly). 287 // 288 // return value is a Box2i with min value: 289 // (dataWindow.min.x + dx * tileXSize(), 290 // dataWindow.min.y + dy * tileYSize()) 291 // 292 // and max value: 293 // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, 294 // dataWindow.min.y + (dy + 1) * tileYSize() - 1) 295 // 296 // dataWindowForTile(dx, dy, level) is a convenience function 297 // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns 298 // dataWindowForTile(dx, dy, level, level). 299 // 300 //------------------------------------------------------------------- 301 302 Imath::Box2i dataWindowForTile (int dx, int dy, 303 int l = 0) const; 304 305 Imath::Box2i dataWindowForTile (int dx, int dy, 306 int lx, int ly) const; 307 308 //------------------------------------------------------------------ 309 // Write pixel data: 310 // 311 // writeTile(dx, dy, lx, ly) writes the tile with tile 312 // coordinates (dx, dy), and level number (lx, ly) to 313 // the file. 314 // 315 // dx must lie in the interval [0, numXTiles(lx) - 1] 316 // dy must lie in the interval [0, numYTiles(ly) - 1] 317 // 318 // lx must lie in the interval [0, numXLevels() - 1] 319 // ly must lie in the inverval [0, numYLevels() - 1] 320 // 321 // writeTile(dx, dy, level) is a convenience function 322 // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls 323 // writeTile(dx, dy, level, level). 324 // 325 // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow 326 // writing multiple tiles at once. If multi-threading is used 327 // multiple tiles are written concurrently. The tile coordinates, 328 // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile 329 // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the 330 // tiles are always written in the order specified by the line 331 // order attribute. Hence, it is not possible to specify an 332 // "invalid" or empty tile range. 333 // 334 // Pixels that are outside the pixel coordinate range for the tile's 335 // level, are never accessed by writeTile(). 336 // 337 // Each tile in the file must be written exactly once. 338 // 339 // The file's line order attribute determines the order of the tiles 340 // in the file: 341 // 342 // INCREASING_Y In the file, the tiles for each level are stored 343 // in a contiguous block. The levels are ordered 344 // like this: 345 // 346 // (0, 0) (1, 0) ... (nx-1, 0) 347 // (0, 1) (1, 1) ... (nx-1, 1) 348 // ... 349 // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) 350 // 351 // where nx = numXLevels(), and ny = numYLevels(). 352 // In an individual level, (lx, ly), the tiles 353 // are stored in the following order: 354 // 355 // (0, 0) (1, 0) ... (tx-1, 0) 356 // (0, 1) (1, 1) ... (tx-1, 1) 357 // ... 358 // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) 359 // 360 // where tx = numXTiles(lx), 361 // and ty = numYTiles(ly). 362 // 363 // DECREASING_Y As for INCREASING_Y, the tiles for each level 364 // are stored in a contiguous block. The levels 365 // are ordered the same way as for INCREASING_Y, 366 // but within an individual level, the tiles 367 // are stored in this order: 368 // 369 // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) 370 // ... 371 // (0, 1) (1, 1) ... (tx-1, 1) 372 // (0, 0) (1, 0) ... (tx-1, 0) 373 // 374 // 375 // RANDOM_Y The order of the calls to writeTile() determines 376 // the order of the tiles in the file. 377 // 378 //------------------------------------------------------------------ 379 380 void writeTile (int dx, int dy, int l = 0); 381 void writeTile (int dx, int dy, int lx, int ly); 382 383 void writeTiles (int dx1, int dx2, int dy1, int dy2, 384 int lx, int ly); 385 386 void writeTiles (int dx1, int dx2, int dy1, int dy2, 387 int l = 0); 388 389 390 //------------------------------------------------------------------ 391 // Shortcut to copy all pixels from a TiledInputFile into this file, 392 // without uncompressing and then recompressing the pixel data. 393 // This file's header must be compatible with the TiledInputFile's 394 // header: The two header's "dataWindow", "compression", 395 // "lineOrder", "channels", and "tiles" attributes must be the same. 396 //------------------------------------------------------------------ 397 398 void copyPixels (TiledInputFile &in); 399 400 401 //------------------------------------------------------------------ 402 // Shortcut to copy all pixels from an InputFile into this file, 403 // without uncompressing and then recompressing the pixel data. 404 // This file's header must be compatible with the InputFile's 405 // header: The two header's "dataWindow", "compression", 406 // "lineOrder", "channels", and "tiles" attributes must be the same. 407 // 408 // To use this function, the InputFile must be tiled. 409 //------------------------------------------------------------------ 410 411 void copyPixels (InputFile &in); 412 413 414 //-------------------------------------------------------------- 415 // Updating the preview image: 416 // 417 // updatePreviewImage() supplies a new set of pixels for the 418 // preview image attribute in the file's header. If the header 419 // does not contain a preview image, updatePreviewImage() throws 420 // an Iex::LogicExc. 421 // 422 // Note: updatePreviewImage() is necessary because images are 423 // often stored in a file incrementally, a few tiles at a time, 424 // while the image is being generated. Since the preview image 425 // is an attribute in the file's header, it gets stored in the 426 // file as soon as the file is opened, but we may not know what 427 // the preview image should look like until we have written the 428 // last tile of the main image. 429 // 430 //-------------------------------------------------------------- 431 432 void updatePreviewImage (const PreviewRgba newPixels[]); 433 434 435 //------------------------------------------------------------- 436 // Break a tile -- for testing and debugging only: 437 // 438 // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the 439 // output file by writing n copies of character c, starting 440 // p bytes from the beginning of the tile with tile coordinates 441 // (dx, dy) and level number (lx, ly). 442 // 443 // Warning: Calling this function usually results in a broken 444 // image file. The file or parts of it may not be readable, 445 // or the file may contain bad data. 446 // 447 //------------------------------------------------------------- 448 449 void breakTile (int dx, int dy, 450 int lx, int ly, 451 int offset, 452 int length, 453 char c); 454 struct Data; 455 456 private: 457 458 TiledOutputFile (const TiledOutputFile &); // not implemented 459 TiledOutputFile & operator = (const TiledOutputFile &); // not implemented 460 461 void initialize (const Header &header); 462 463 bool isValidTile (int dx, int dy, 464 int lx, int ly) const; 465 466 size_t bytesPerLineForTile (int dx, int dy, 467 int lx, int ly) const; 468 469 Data * _data; 470 }; 471 472 473 } // namespace Imf 474 475 #endif 476