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 // class TiledRgbaOutputFile 38 // class TiledRgbaInputFile 39 // 40 //----------------------------------------------------------------------------- 41 42 #include <ImfTiledRgbaFile.h> 43 #include <ImfRgbaFile.h> 44 #include <ImfTiledOutputFile.h> 45 #include <ImfTiledInputFile.h> 46 #include <ImfChannelList.h> 47 #include <ImfTileDescriptionAttribute.h> 48 #include <ImfStandardAttributes.h> 49 #include <ImfRgbaYca.h> 50 #include <ImfArray.h> 51 #include "IlmThreadMutex.h" 52 #include "Iex.h" 53 54 55 namespace Imf { 56 57 using namespace std; 58 using namespace Imath; 59 using namespace RgbaYca; 60 using namespace IlmThread; 61 62 namespace { 63 64 void 65 insertChannels (Header &header, 66 RgbaChannels rgbaChannels, 67 const char fileName[]) 68 { 69 ChannelList ch; 70 71 if (rgbaChannels & (WRITE_Y | WRITE_C)) 72 { 73 if (rgbaChannels & WRITE_Y) 74 { 75 ch.insert ("Y", Channel (HALF, 1, 1)); 76 } 77 78 if (rgbaChannels & WRITE_C) 79 { 80 THROW (Iex::ArgExc, "Cannot open file \"" << fileName << "\" " 81 "for writing. Tiled image files do not " 82 "support subsampled chroma channels."); 83 } 84 } 85 else 86 { 87 if (rgbaChannels & WRITE_R) 88 ch.insert ("R", Channel (HALF, 1, 1)); 89 90 if (rgbaChannels & WRITE_G) 91 ch.insert ("G", Channel (HALF, 1, 1)); 92 93 if (rgbaChannels & WRITE_B) 94 ch.insert ("B", Channel (HALF, 1, 1)); 95 } 96 97 if (rgbaChannels & WRITE_A) 98 ch.insert ("A", Channel (HALF, 1, 1)); 99 100 header.channels() = ch; 101 } 102 103 104 RgbaChannels 105 rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "") 106 { 107 int i = 0; 108 109 if (ch.findChannel (channelNamePrefix + "R")) 110 i |= WRITE_R; 111 112 if (ch.findChannel (channelNamePrefix + "G")) 113 i |= WRITE_G; 114 115 if (ch.findChannel (channelNamePrefix + "B")) 116 i |= WRITE_B; 117 118 if (ch.findChannel (channelNamePrefix + "A")) 119 i |= WRITE_A; 120 121 if (ch.findChannel (channelNamePrefix + "Y")) 122 i |= WRITE_Y; 123 124 return RgbaChannels (i); 125 } 126 127 128 string 129 prefixFromLayerName (const string &layerName, const Header &header) 130 { 131 if (layerName.empty()) 132 return ""; 133 134 if (hasMultiView (header) && multiView(header)[0] == layerName) 135 return ""; 136 137 return layerName + "."; 138 } 139 140 141 V3f 142 ywFromHeader (const Header &header) 143 { 144 Chromaticities cr; 145 146 if (hasChromaticities (header)) 147 cr = chromaticities (header); 148 149 return computeYw (cr); 150 } 151 152 } // namespace 153 154 155 class TiledRgbaOutputFile::ToYa: public Mutex 156 { 157 public: 158 159 ToYa (TiledOutputFile &outputFile, RgbaChannels rgbaChannels); 160 161 void setFrameBuffer (const Rgba *base, 162 size_t xStride, 163 size_t yStride); 164 165 void writeTile (int dx, int dy, int lx, int ly); 166 167 private: 168 169 TiledOutputFile & _outputFile; 170 bool _writeA; 171 unsigned int _tileXSize; 172 unsigned int _tileYSize; 173 V3f _yw; 174 Array2D <Rgba> _buf; 175 const Rgba * _fbBase; 176 size_t _fbXStride; 177 size_t _fbYStride; 178 }; 179 180 181 TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile, 182 RgbaChannels rgbaChannels) 183 : 184 _outputFile (outputFile) 185 { 186 _writeA = (rgbaChannels & WRITE_A)? true: false; 187 188 const TileDescription &td = outputFile.header().tileDescription(); 189 190 _tileXSize = td.xSize; 191 _tileYSize = td.ySize; 192 _yw = ywFromHeader (_outputFile.header()); 193 _buf.resizeErase (_tileYSize, _tileXSize); 194 _fbBase = 0; 195 _fbXStride = 0; 196 _fbYStride = 0; 197 } 198 199 200 void 201 TiledRgbaOutputFile::ToYa::setFrameBuffer (const Rgba *base, 202 size_t xStride, 203 size_t yStride) 204 { 205 _fbBase = base; 206 _fbXStride = xStride; 207 _fbYStride = yStride; 208 } 209 210 211 void 212 TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly) 213 { 214 if (_fbBase == 0) 215 { 216 THROW (Iex::ArgExc, "No frame buffer was specified as the " 217 "pixel data source for image file " 218 "\"" << _outputFile.fileName() << "\"."); 219 } 220 221 // 222 // Copy the tile's RGBA pixels into _buf and convert 223 // them to luminance/alpha format 224 // 225 226 Box2i dw = _outputFile.dataWindowForTile (dx, dy, lx, ly); 227 int width = dw.max.x - dw.min.x + 1; 228 229 for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) 230 { 231 for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) 232 _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride]; 233 234 RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]); 235 } 236 237 // 238 // Store the contents of _buf in the output file 239 // 240 241 FrameBuffer fb; 242 243 fb.insert ("Y", Slice (HALF, // type 244 (char *) &_buf[-dw.min.y][-dw.min.x].g, // base 245 sizeof (Rgba), // xStride 246 sizeof (Rgba) * _tileXSize)); // yStride 247 248 fb.insert ("A", Slice (HALF, // type 249 (char *) &_buf[-dw.min.y][-dw.min.x].a, // base 250 sizeof (Rgba), // xStride 251 sizeof (Rgba) * _tileXSize)); // yStride 252 253 _outputFile.setFrameBuffer (fb); 254 _outputFile.writeTile (dx, dy, lx, ly); 255 } 256 257 258 TiledRgbaOutputFile::TiledRgbaOutputFile 259 (const char name[], 260 const Header &header, 261 RgbaChannels rgbaChannels, 262 int tileXSize, 263 int tileYSize, 264 LevelMode mode, 265 LevelRoundingMode rmode, 266 int numThreads) 267 : 268 _outputFile (0), 269 _toYa (0) 270 { 271 Header hd (header); 272 insertChannels (hd, rgbaChannels, name); 273 hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); 274 _outputFile = new TiledOutputFile (name, hd, numThreads); 275 276 if (rgbaChannels & WRITE_Y) 277 _toYa = new ToYa (*_outputFile, rgbaChannels); 278 } 279 280 281 282 TiledRgbaOutputFile::TiledRgbaOutputFile 283 (OStream &os, 284 const Header &header, 285 RgbaChannels rgbaChannels, 286 int tileXSize, 287 int tileYSize, 288 LevelMode mode, 289 LevelRoundingMode rmode, 290 int numThreads) 291 : 292 _outputFile (0), 293 _toYa (0) 294 { 295 Header hd (header); 296 insertChannels (hd, rgbaChannels, os.fileName()); 297 hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); 298 _outputFile = new TiledOutputFile (os, hd, numThreads); 299 300 if (rgbaChannels & WRITE_Y) 301 _toYa = new ToYa (*_outputFile, rgbaChannels); 302 } 303 304 305 306 TiledRgbaOutputFile::TiledRgbaOutputFile 307 (const char name[], 308 int tileXSize, 309 int tileYSize, 310 LevelMode mode, 311 LevelRoundingMode rmode, 312 const Imath::Box2i &displayWindow, 313 const Imath::Box2i &dataWindow, 314 RgbaChannels rgbaChannels, 315 float pixelAspectRatio, 316 const Imath::V2f screenWindowCenter, 317 float screenWindowWidth, 318 LineOrder lineOrder, 319 Compression compression, 320 int numThreads) 321 : 322 _outputFile (0), 323 _toYa (0) 324 { 325 Header hd (displayWindow, 326 dataWindow.isEmpty()? displayWindow: dataWindow, 327 pixelAspectRatio, 328 screenWindowCenter, 329 screenWindowWidth, 330 lineOrder, 331 compression); 332 333 insertChannels (hd, rgbaChannels, name); 334 hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); 335 _outputFile = new TiledOutputFile (name, hd, numThreads); 336 337 if (rgbaChannels & WRITE_Y) 338 _toYa = new ToYa (*_outputFile, rgbaChannels); 339 } 340 341 342 TiledRgbaOutputFile::TiledRgbaOutputFile 343 (const char name[], 344 int width, 345 int height, 346 int tileXSize, 347 int tileYSize, 348 LevelMode mode, 349 LevelRoundingMode rmode, 350 RgbaChannels rgbaChannels, 351 float pixelAspectRatio, 352 const Imath::V2f screenWindowCenter, 353 float screenWindowWidth, 354 LineOrder lineOrder, 355 Compression compression, 356 int numThreads) 357 : 358 _outputFile (0), 359 _toYa (0) 360 { 361 Header hd (width, 362 height, 363 pixelAspectRatio, 364 screenWindowCenter, 365 screenWindowWidth, 366 lineOrder, 367 compression); 368 369 insertChannels (hd, rgbaChannels, name); 370 hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); 371 _outputFile = new TiledOutputFile (name, hd, numThreads); 372 373 if (rgbaChannels & WRITE_Y) 374 _toYa = new ToYa (*_outputFile, rgbaChannels); 375 } 376 377 378 TiledRgbaOutputFile::~TiledRgbaOutputFile () 379 { 380 delete _outputFile; 381 delete _toYa; 382 } 383 384 385 void 386 TiledRgbaOutputFile::setFrameBuffer (const Rgba *base, 387 size_t xStride, 388 size_t yStride) 389 { 390 if (_toYa) 391 { 392 Lock lock (*_toYa); 393 _toYa->setFrameBuffer (base, xStride, yStride); 394 } 395 else 396 { 397 size_t xs = xStride * sizeof (Rgba); 398 size_t ys = yStride * sizeof (Rgba); 399 400 FrameBuffer fb; 401 402 fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys)); 403 fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys)); 404 fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys)); 405 fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys)); 406 407 _outputFile->setFrameBuffer (fb); 408 } 409 } 410 411 412 const Header & 413 TiledRgbaOutputFile::header () const 414 { 415 return _outputFile->header(); 416 } 417 418 419 const FrameBuffer & 420 TiledRgbaOutputFile::frameBuffer () const 421 { 422 return _outputFile->frameBuffer(); 423 } 424 425 426 const Imath::Box2i & 427 TiledRgbaOutputFile::displayWindow () const 428 { 429 return _outputFile->header().displayWindow(); 430 } 431 432 433 const Imath::Box2i & 434 TiledRgbaOutputFile::dataWindow () const 435 { 436 return _outputFile->header().dataWindow(); 437 } 438 439 440 float 441 TiledRgbaOutputFile::pixelAspectRatio () const 442 { 443 return _outputFile->header().pixelAspectRatio(); 444 } 445 446 447 const Imath::V2f 448 TiledRgbaOutputFile::screenWindowCenter () const 449 { 450 return _outputFile->header().screenWindowCenter(); 451 } 452 453 454 float 455 TiledRgbaOutputFile::screenWindowWidth () const 456 { 457 return _outputFile->header().screenWindowWidth(); 458 } 459 460 461 LineOrder 462 TiledRgbaOutputFile::lineOrder () const 463 { 464 return _outputFile->header().lineOrder(); 465 } 466 467 468 Compression 469 TiledRgbaOutputFile::compression () const 470 { 471 return _outputFile->header().compression(); 472 } 473 474 475 RgbaChannels 476 TiledRgbaOutputFile::channels () const 477 { 478 return rgbaChannels (_outputFile->header().channels()); 479 } 480 481 482 unsigned int 483 TiledRgbaOutputFile::tileXSize () const 484 { 485 return _outputFile->tileXSize(); 486 } 487 488 489 unsigned int 490 TiledRgbaOutputFile::tileYSize () const 491 { 492 return _outputFile->tileYSize(); 493 } 494 495 496 LevelMode 497 TiledRgbaOutputFile::levelMode () const 498 { 499 return _outputFile->levelMode(); 500 } 501 502 503 LevelRoundingMode 504 TiledRgbaOutputFile::levelRoundingMode () const 505 { 506 return _outputFile->levelRoundingMode(); 507 } 508 509 510 int 511 TiledRgbaOutputFile::numLevels () const 512 { 513 return _outputFile->numLevels(); 514 } 515 516 517 int 518 TiledRgbaOutputFile::numXLevels () const 519 { 520 return _outputFile->numXLevels(); 521 } 522 523 524 int 525 TiledRgbaOutputFile::numYLevels () const 526 { 527 return _outputFile->numYLevels(); 528 } 529 530 531 bool 532 TiledRgbaOutputFile::isValidLevel (int lx, int ly) const 533 { 534 return _outputFile->isValidLevel (lx, ly); 535 } 536 537 538 int 539 TiledRgbaOutputFile::levelWidth (int lx) const 540 { 541 return _outputFile->levelWidth (lx); 542 } 543 544 545 int 546 TiledRgbaOutputFile::levelHeight (int ly) const 547 { 548 return _outputFile->levelHeight (ly); 549 } 550 551 552 int 553 TiledRgbaOutputFile::numXTiles (int lx) const 554 { 555 return _outputFile->numXTiles (lx); 556 } 557 558 559 int 560 TiledRgbaOutputFile::numYTiles (int ly) const 561 { 562 return _outputFile->numYTiles (ly); 563 } 564 565 566 Imath::Box2i 567 TiledRgbaOutputFile::dataWindowForLevel (int l) const 568 { 569 return _outputFile->dataWindowForLevel (l); 570 } 571 572 573 Imath::Box2i 574 TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const 575 { 576 return _outputFile->dataWindowForLevel (lx, ly); 577 } 578 579 580 Imath::Box2i 581 TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const 582 { 583 return _outputFile->dataWindowForTile (dx, dy, l); 584 } 585 586 587 Imath::Box2i 588 TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const 589 { 590 return _outputFile->dataWindowForTile (dx, dy, lx, ly); 591 } 592 593 594 void 595 TiledRgbaOutputFile::writeTile (int dx, int dy, int l) 596 { 597 if (_toYa) 598 { 599 Lock lock (*_toYa); 600 _toYa->writeTile (dx, dy, l, l); 601 } 602 else 603 { 604 _outputFile->writeTile (dx, dy, l); 605 } 606 } 607 608 609 void 610 TiledRgbaOutputFile::writeTile (int dx, int dy, int lx, int ly) 611 { 612 if (_toYa) 613 { 614 Lock lock (*_toYa); 615 _toYa->writeTile (dx, dy, lx, ly); 616 } 617 else 618 { 619 _outputFile->writeTile (dx, dy, lx, ly); 620 } 621 } 622 623 624 void 625 TiledRgbaOutputFile::writeTiles 626 (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly) 627 { 628 if (_toYa) 629 { 630 Lock lock (*_toYa); 631 632 for (int dy = dyMin; dy <= dyMax; dy++) 633 for (int dx = dxMin; dx <= dxMax; dx++) 634 _toYa->writeTile (dx, dy, lx, ly); 635 } 636 else 637 { 638 _outputFile->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); 639 } 640 } 641 642 void 643 TiledRgbaOutputFile::writeTiles 644 (int dxMin, int dxMax, int dyMin, int dyMax, int l) 645 { 646 writeTiles (dxMin, dxMax, dyMin, dyMax, l, l); 647 } 648 649 650 class TiledRgbaInputFile::FromYa: public Mutex 651 { 652 public: 653 654 FromYa (TiledInputFile &inputFile); 655 656 void setFrameBuffer (Rgba *base, 657 size_t xStride, 658 size_t yStride, 659 const string &channelNamePrefix); 660 661 void readTile (int dx, int dy, int lx, int ly); 662 663 private: 664 665 TiledInputFile & _inputFile; 666 unsigned int _tileXSize; 667 unsigned int _tileYSize; 668 V3f _yw; 669 Array2D <Rgba> _buf; 670 Rgba * _fbBase; 671 size_t _fbXStride; 672 size_t _fbYStride; 673 }; 674 675 676 TiledRgbaInputFile::FromYa::FromYa (TiledInputFile &inputFile) 677 : 678 _inputFile (inputFile) 679 { 680 const TileDescription &td = inputFile.header().tileDescription(); 681 682 _tileXSize = td.xSize; 683 _tileYSize = td.ySize; 684 _yw = ywFromHeader (_inputFile.header()); 685 _buf.resizeErase (_tileYSize, _tileXSize); 686 _fbBase = 0; 687 _fbXStride = 0; 688 _fbYStride = 0; 689 } 690 691 692 void 693 TiledRgbaInputFile::FromYa::setFrameBuffer (Rgba *base, 694 size_t xStride, 695 size_t yStride, 696 const string &channelNamePrefix) 697 { 698 if (_fbBase == 0) 699 { 700 FrameBuffer fb; 701 702 fb.insert (channelNamePrefix + "Y", 703 Slice (HALF, // type 704 (char *) &_buf[0][0].g, // base 705 sizeof (Rgba), // xStride 706 sizeof (Rgba) * _tileXSize, // yStride 707 1, 1, // sampling 708 0.0, // fillValue 709 true, true)); // tileCoordinates 710 711 fb.insert (channelNamePrefix + "A", 712 Slice (HALF, // type 713 (char *) &_buf[0][0].a, // base 714 sizeof (Rgba), // xStride 715 sizeof (Rgba) * _tileXSize, // yStride 716 1, 1, // sampling 717 1.0, // fillValue 718 true, true)); // tileCoordinates 719 720 _inputFile.setFrameBuffer (fb); 721 } 722 723 _fbBase = base; 724 _fbXStride = xStride; 725 _fbYStride = yStride; 726 } 727 728 729 void 730 TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly) 731 { 732 if (_fbBase == 0) 733 { 734 THROW (Iex::ArgExc, "No frame buffer was specified as the " 735 "pixel data destination for image file " 736 "\"" << _inputFile.fileName() << "\"."); 737 } 738 739 // 740 // Read the tile requested by the caller into _buf. 741 // 742 743 _inputFile.readTile (dx, dy, lx, ly); 744 745 // 746 // Convert the luminance/alpha pixels to RGBA 747 // and copy them into the caller's frame buffer. 748 // 749 750 Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly); 751 int width = dw.max.x - dw.min.x + 1; 752 753 for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) 754 { 755 for (int x1 = 0; x1 < width; ++x1) 756 { 757 _buf[y1][x1].r = 0; 758 _buf[y1][x1].b = 0; 759 } 760 761 YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]); 762 763 for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) 764 { 765 _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1]; 766 } 767 } 768 } 769 770 771 TiledRgbaInputFile::TiledRgbaInputFile (const char name[], int numThreads): 772 _inputFile (new TiledInputFile (name, numThreads)), 773 _fromYa (0), 774 _channelNamePrefix ("") 775 { 776 if (channels() & WRITE_Y) 777 _fromYa = new FromYa (*_inputFile); 778 } 779 780 781 TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, int numThreads): 782 _inputFile (new TiledInputFile (is, numThreads)), 783 _fromYa (0), 784 _channelNamePrefix ("") 785 { 786 if (channels() & WRITE_Y) 787 _fromYa = new FromYa (*_inputFile); 788 } 789 790 791 TiledRgbaInputFile::TiledRgbaInputFile (const char name[], 792 const string &layerName, 793 int numThreads) 794 : 795 _inputFile (new TiledInputFile (name, numThreads)), 796 _fromYa (0), 797 _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header())) 798 { 799 if (channels() & WRITE_Y) 800 _fromYa = new FromYa (*_inputFile); 801 } 802 803 804 TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, 805 const string &layerName, 806 int numThreads) 807 : 808 _inputFile (new TiledInputFile (is, numThreads)), 809 _fromYa (0), 810 _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header())) 811 { 812 if (channels() & WRITE_Y) 813 _fromYa = new FromYa (*_inputFile); 814 } 815 816 817 TiledRgbaInputFile::~TiledRgbaInputFile () 818 { 819 delete _inputFile; 820 delete _fromYa; 821 } 822 823 824 void 825 TiledRgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) 826 { 827 if (_fromYa) 828 { 829 Lock lock (*_fromYa); 830 _fromYa->setFrameBuffer (base, xStride, yStride, _channelNamePrefix); 831 } 832 else 833 { 834 size_t xs = xStride * sizeof (Rgba); 835 size_t ys = yStride * sizeof (Rgba); 836 837 FrameBuffer fb; 838 839 fb.insert (_channelNamePrefix + "R", 840 Slice (HALF, 841 (char *) &base[0].r, 842 xs, ys, 843 1, 1, // xSampling, ySampling 844 0.0)); // fillValue 845 846 fb.insert (_channelNamePrefix + "G", 847 Slice (HALF, 848 (char *) &base[0].g, 849 xs, ys, 850 1, 1, // xSampling, ySampling 851 0.0)); // fillValue 852 853 fb.insert (_channelNamePrefix + "B", 854 Slice (HALF, 855 (char *) &base[0].b, 856 xs, ys, 857 1, 1, // xSampling, ySampling 858 0.0)); // fillValue 859 860 fb.insert (_channelNamePrefix + "A", 861 Slice (HALF, 862 (char *) &base[0].a, 863 xs, ys, 864 1, 1, // xSampling, ySampling 865 1.0)); // fillValue 866 867 _inputFile->setFrameBuffer (fb); 868 } 869 } 870 871 872 void 873 TiledRgbaInputFile::setLayerName (const std::string &layerName) 874 { 875 delete _fromYa; 876 _fromYa = 0; 877 878 _channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header()); 879 880 if (channels() & WRITE_Y) 881 _fromYa = new FromYa (*_inputFile); 882 883 FrameBuffer fb; 884 _inputFile->setFrameBuffer (fb); 885 } 886 887 888 const Header & 889 TiledRgbaInputFile::header () const 890 { 891 return _inputFile->header(); 892 } 893 894 895 const char * 896 TiledRgbaInputFile::fileName () const 897 { 898 return _inputFile->fileName(); 899 } 900 901 902 const FrameBuffer & 903 TiledRgbaInputFile::frameBuffer () const 904 { 905 return _inputFile->frameBuffer(); 906 } 907 908 909 const Imath::Box2i & 910 TiledRgbaInputFile::displayWindow () const 911 { 912 return _inputFile->header().displayWindow(); 913 } 914 915 916 const Imath::Box2i & 917 TiledRgbaInputFile::dataWindow () const 918 { 919 return _inputFile->header().dataWindow(); 920 } 921 922 923 float 924 TiledRgbaInputFile::pixelAspectRatio () const 925 { 926 return _inputFile->header().pixelAspectRatio(); 927 } 928 929 930 const Imath::V2f 931 TiledRgbaInputFile::screenWindowCenter () const 932 { 933 return _inputFile->header().screenWindowCenter(); 934 } 935 936 937 float 938 TiledRgbaInputFile::screenWindowWidth () const 939 { 940 return _inputFile->header().screenWindowWidth(); 941 } 942 943 944 LineOrder 945 TiledRgbaInputFile::lineOrder () const 946 { 947 return _inputFile->header().lineOrder(); 948 } 949 950 951 Compression 952 TiledRgbaInputFile::compression () const 953 { 954 return _inputFile->header().compression(); 955 } 956 957 958 RgbaChannels 959 TiledRgbaInputFile::channels () const 960 { 961 return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix); 962 } 963 964 965 int 966 TiledRgbaInputFile::version () const 967 { 968 return _inputFile->version(); 969 } 970 971 972 bool 973 TiledRgbaInputFile::isComplete () const 974 { 975 return _inputFile->isComplete(); 976 } 977 978 979 unsigned int 980 TiledRgbaInputFile::tileXSize () const 981 { 982 return _inputFile->tileXSize(); 983 } 984 985 986 unsigned int 987 TiledRgbaInputFile::tileYSize () const 988 { 989 return _inputFile->tileYSize(); 990 } 991 992 993 LevelMode 994 TiledRgbaInputFile::levelMode () const 995 { 996 return _inputFile->levelMode(); 997 } 998 999 1000 LevelRoundingMode 1001 TiledRgbaInputFile::levelRoundingMode () const 1002 { 1003 return _inputFile->levelRoundingMode(); 1004 } 1005 1006 1007 int 1008 TiledRgbaInputFile::numLevels () const 1009 { 1010 return _inputFile->numLevels(); 1011 } 1012 1013 1014 int 1015 TiledRgbaInputFile::numXLevels () const 1016 { 1017 return _inputFile->numXLevels(); 1018 } 1019 1020 1021 int 1022 TiledRgbaInputFile::numYLevels () const 1023 { 1024 return _inputFile->numYLevels(); 1025 } 1026 1027 1028 bool 1029 TiledRgbaInputFile::isValidLevel (int lx, int ly) const 1030 { 1031 return _inputFile->isValidLevel (lx, ly); 1032 } 1033 1034 1035 int 1036 TiledRgbaInputFile::levelWidth (int lx) const 1037 { 1038 return _inputFile->levelWidth (lx); 1039 } 1040 1041 1042 int 1043 TiledRgbaInputFile::levelHeight (int ly) const 1044 { 1045 return _inputFile->levelHeight (ly); 1046 } 1047 1048 1049 int 1050 TiledRgbaInputFile::numXTiles (int lx) const 1051 { 1052 return _inputFile->numXTiles(lx); 1053 } 1054 1055 1056 int 1057 TiledRgbaInputFile::numYTiles (int ly) const 1058 { 1059 return _inputFile->numYTiles(ly); 1060 } 1061 1062 1063 Imath::Box2i 1064 TiledRgbaInputFile::dataWindowForLevel (int l) const 1065 { 1066 return _inputFile->dataWindowForLevel (l); 1067 } 1068 1069 1070 Imath::Box2i 1071 TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const 1072 { 1073 return _inputFile->dataWindowForLevel (lx, ly); 1074 } 1075 1076 1077 Imath::Box2i 1078 TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const 1079 { 1080 return _inputFile->dataWindowForTile (dx, dy, l); 1081 } 1082 1083 1084 Imath::Box2i 1085 TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const 1086 { 1087 return _inputFile->dataWindowForTile (dx, dy, lx, ly); 1088 } 1089 1090 1091 void 1092 TiledRgbaInputFile::readTile (int dx, int dy, int l) 1093 { 1094 if (_fromYa) 1095 { 1096 Lock lock (*_fromYa); 1097 _fromYa->readTile (dx, dy, l, l); 1098 } 1099 else 1100 { 1101 _inputFile->readTile (dx, dy, l); 1102 } 1103 } 1104 1105 1106 void 1107 TiledRgbaInputFile::readTile (int dx, int dy, int lx, int ly) 1108 { 1109 if (_fromYa) 1110 { 1111 Lock lock (*_fromYa); 1112 _fromYa->readTile (dx, dy, lx, ly); 1113 } 1114 else 1115 { 1116 _inputFile->readTile (dx, dy, lx, ly); 1117 } 1118 } 1119 1120 1121 void 1122 TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, 1123 int lx, int ly) 1124 { 1125 if (_fromYa) 1126 { 1127 Lock lock (*_fromYa); 1128 1129 for (int dy = dyMin; dy <= dyMax; dy++) 1130 for (int dx = dxMin; dx <= dxMax; dx++) 1131 _fromYa->readTile (dx, dy, lx, ly); 1132 } 1133 else 1134 { 1135 _inputFile->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); 1136 } 1137 } 1138 1139 void 1140 TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, 1141 int l) 1142 { 1143 readTiles (dxMin, dxMax, dyMin, dyMax, l, l); 1144 } 1145 1146 1147 void 1148 TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) 1149 { 1150 _outputFile->updatePreviewImage (newPixels); 1151 } 1152 1153 1154 void 1155 TiledRgbaOutputFile::breakTile (int dx, int dy, int lx, int ly, 1156 int offset, int length, char c) 1157 { 1158 _outputFile->breakTile (dx, dy, lx, ly, offset, length, c); 1159 } 1160 1161 1162 } // namespace Imf 1163