PageRenderTime 110ms CodeModel.GetById 12ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 1162 lines | 852 code | 257 blank | 53 comment | 49 complexity | de0d2bc225205dc30471caf6e96d8110 MD5 | raw file
   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
  55namespace Imf {
  56
  57using namespace std;
  58using namespace Imath;
  59using namespace RgbaYca;
  60using namespace IlmThread;
  61
  62namespace {
  63
  64void
  65insertChannels (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
 104RgbaChannels
 105rgbaChannels (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
 128string
 129prefixFromLayerName (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
 141V3f
 142ywFromHeader (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
 155class 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
 181TiledRgbaOutputFile::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
 200void
 201TiledRgbaOutputFile::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
 211void
 212TiledRgbaOutputFile::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
 258TiledRgbaOutputFile::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
 282TiledRgbaOutputFile::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
 306TiledRgbaOutputFile::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
 342TiledRgbaOutputFile::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
 378TiledRgbaOutputFile::~TiledRgbaOutputFile ()
 379{
 380    delete _outputFile;
 381    delete _toYa;
 382}
 383
 384
 385void
 386TiledRgbaOutputFile::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
 412const Header &
 413TiledRgbaOutputFile::header () const
 414{
 415    return _outputFile->header();
 416}
 417
 418
 419const FrameBuffer &
 420TiledRgbaOutputFile::frameBuffer () const
 421{
 422    return _outputFile->frameBuffer();
 423}
 424
 425
 426const Imath::Box2i &
 427TiledRgbaOutputFile::displayWindow () const
 428{
 429    return _outputFile->header().displayWindow();
 430}
 431
 432
 433const Imath::Box2i &
 434TiledRgbaOutputFile::dataWindow () const
 435{
 436    return _outputFile->header().dataWindow();
 437}
 438
 439
 440float	
 441TiledRgbaOutputFile::pixelAspectRatio () const
 442{
 443    return _outputFile->header().pixelAspectRatio();
 444}
 445
 446
 447const Imath::V2f
 448TiledRgbaOutputFile::screenWindowCenter () const
 449{
 450    return _outputFile->header().screenWindowCenter();
 451}
 452
 453
 454float	
 455TiledRgbaOutputFile::screenWindowWidth () const
 456{
 457    return _outputFile->header().screenWindowWidth();
 458}
 459
 460
 461LineOrder
 462TiledRgbaOutputFile::lineOrder () const
 463{
 464    return _outputFile->header().lineOrder();
 465}
 466
 467
 468Compression
 469TiledRgbaOutputFile::compression () const
 470{
 471    return _outputFile->header().compression();
 472}
 473
 474
 475RgbaChannels
 476TiledRgbaOutputFile::channels () const
 477{
 478    return rgbaChannels (_outputFile->header().channels());
 479}
 480
 481
 482unsigned int
 483TiledRgbaOutputFile::tileXSize () const
 484{
 485     return _outputFile->tileXSize();
 486}
 487
 488
 489unsigned int
 490TiledRgbaOutputFile::tileYSize () const
 491{
 492     return _outputFile->tileYSize();
 493}
 494
 495
 496LevelMode
 497TiledRgbaOutputFile::levelMode () const
 498{
 499     return _outputFile->levelMode();
 500}
 501
 502
 503LevelRoundingMode
 504TiledRgbaOutputFile::levelRoundingMode () const
 505{
 506     return _outputFile->levelRoundingMode();
 507}
 508
 509
 510int
 511TiledRgbaOutputFile::numLevels () const
 512{
 513     return _outputFile->numLevels();
 514}
 515
 516
 517int
 518TiledRgbaOutputFile::numXLevels () const
 519{
 520     return _outputFile->numXLevels();
 521}
 522
 523
 524int
 525TiledRgbaOutputFile::numYLevels () const
 526{
 527     return _outputFile->numYLevels();
 528}
 529
 530
 531bool
 532TiledRgbaOutputFile::isValidLevel (int lx, int ly) const
 533{
 534    return _outputFile->isValidLevel (lx, ly);
 535}
 536
 537
 538int
 539TiledRgbaOutputFile::levelWidth (int lx) const
 540{
 541     return _outputFile->levelWidth (lx);
 542}
 543
 544
 545int
 546TiledRgbaOutputFile::levelHeight (int ly) const
 547{
 548     return _outputFile->levelHeight (ly);
 549}
 550
 551
 552int
 553TiledRgbaOutputFile::numXTiles (int lx) const
 554{
 555     return _outputFile->numXTiles (lx);
 556}
 557
 558
 559int
 560TiledRgbaOutputFile::numYTiles (int ly) const
 561{
 562     return _outputFile->numYTiles (ly);
 563}
 564
 565
 566Imath::Box2i
 567TiledRgbaOutputFile::dataWindowForLevel (int l) const
 568{
 569     return _outputFile->dataWindowForLevel (l);
 570}
 571
 572
 573Imath::Box2i
 574TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const
 575{
 576     return _outputFile->dataWindowForLevel (lx, ly);
 577}
 578
 579
 580Imath::Box2i
 581TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const
 582{
 583     return _outputFile->dataWindowForTile (dx, dy, l);
 584}
 585
 586
 587Imath::Box2i
 588TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
 589{
 590     return _outputFile->dataWindowForTile (dx, dy, lx, ly);
 591}
 592
 593
 594void
 595TiledRgbaOutputFile::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
 609void
 610TiledRgbaOutputFile::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
 624void	
 625TiledRgbaOutputFile::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
 642void	
 643TiledRgbaOutputFile::writeTiles
 644    (int dxMin, int dxMax, int dyMin, int dyMax, int l)
 645{
 646    writeTiles (dxMin, dxMax, dyMin, dyMax, l, l);
 647}
 648
 649
 650class 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
 676TiledRgbaInputFile::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
 692void
 693TiledRgbaInputFile::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
 729void
 730TiledRgbaInputFile::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
 771TiledRgbaInputFile::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
 781TiledRgbaInputFile::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
 791TiledRgbaInputFile::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
 804TiledRgbaInputFile::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
 817TiledRgbaInputFile::~TiledRgbaInputFile ()
 818{
 819    delete _inputFile;
 820    delete _fromYa;
 821}
 822
 823
 824void	
 825TiledRgbaInputFile::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
 872void		
 873TiledRgbaInputFile::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
 888const Header &
 889TiledRgbaInputFile::header () const
 890{
 891    return _inputFile->header();
 892}
 893
 894
 895const char *
 896TiledRgbaInputFile::fileName () const
 897{
 898    return _inputFile->fileName();
 899}
 900
 901
 902const FrameBuffer &	
 903TiledRgbaInputFile::frameBuffer () const
 904{
 905    return _inputFile->frameBuffer();
 906}
 907
 908
 909const Imath::Box2i &
 910TiledRgbaInputFile::displayWindow () const
 911{
 912    return _inputFile->header().displayWindow();
 913}
 914
 915
 916const Imath::Box2i &
 917TiledRgbaInputFile::dataWindow () const
 918{
 919    return _inputFile->header().dataWindow();
 920}
 921
 922
 923float	
 924TiledRgbaInputFile::pixelAspectRatio () const
 925{
 926    return _inputFile->header().pixelAspectRatio();
 927}
 928
 929
 930const Imath::V2f	
 931TiledRgbaInputFile::screenWindowCenter () const
 932{
 933    return _inputFile->header().screenWindowCenter();
 934}
 935
 936
 937float	
 938TiledRgbaInputFile::screenWindowWidth () const
 939{
 940    return _inputFile->header().screenWindowWidth();
 941}
 942
 943
 944LineOrder
 945TiledRgbaInputFile::lineOrder () const
 946{
 947    return _inputFile->header().lineOrder();
 948}
 949
 950
 951Compression
 952TiledRgbaInputFile::compression () const
 953{
 954    return _inputFile->header().compression();
 955}
 956
 957
 958RgbaChannels	
 959TiledRgbaInputFile::channels () const
 960{
 961    return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
 962}
 963
 964
 965int
 966TiledRgbaInputFile::version () const
 967{
 968    return _inputFile->version();
 969}
 970
 971
 972bool
 973TiledRgbaInputFile::isComplete () const
 974{
 975    return _inputFile->isComplete();
 976}
 977
 978
 979unsigned int
 980TiledRgbaInputFile::tileXSize () const
 981{
 982     return _inputFile->tileXSize();
 983}
 984
 985
 986unsigned int
 987TiledRgbaInputFile::tileYSize () const
 988{
 989     return _inputFile->tileYSize();
 990}
 991
 992
 993LevelMode
 994TiledRgbaInputFile::levelMode () const
 995{
 996     return _inputFile->levelMode();
 997}
 998
 999
1000LevelRoundingMode
1001TiledRgbaInputFile::levelRoundingMode () const
1002{
1003     return _inputFile->levelRoundingMode();
1004}
1005
1006
1007int
1008TiledRgbaInputFile::numLevels () const
1009{
1010     return _inputFile->numLevels();
1011}
1012
1013
1014int
1015TiledRgbaInputFile::numXLevels () const
1016{
1017     return _inputFile->numXLevels();
1018}
1019
1020
1021int
1022TiledRgbaInputFile::numYLevels () const
1023{
1024     return _inputFile->numYLevels();
1025}
1026
1027
1028bool
1029TiledRgbaInputFile::isValidLevel (int lx, int ly) const
1030{
1031    return _inputFile->isValidLevel (lx, ly);
1032}
1033
1034
1035int
1036TiledRgbaInputFile::levelWidth (int lx) const
1037{
1038     return _inputFile->levelWidth (lx);
1039}
1040
1041
1042int
1043TiledRgbaInputFile::levelHeight (int ly) const
1044{
1045     return _inputFile->levelHeight (ly);
1046}
1047
1048
1049int
1050TiledRgbaInputFile::numXTiles (int lx) const
1051{
1052     return _inputFile->numXTiles(lx);
1053}
1054
1055
1056int
1057TiledRgbaInputFile::numYTiles (int ly) const
1058{
1059     return _inputFile->numYTiles(ly);
1060}
1061
1062
1063Imath::Box2i
1064TiledRgbaInputFile::dataWindowForLevel (int l) const
1065{
1066     return _inputFile->dataWindowForLevel (l);
1067}
1068
1069
1070Imath::Box2i
1071TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const
1072{
1073     return _inputFile->dataWindowForLevel (lx, ly);
1074}
1075
1076
1077Imath::Box2i
1078TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const
1079{
1080     return _inputFile->dataWindowForTile (dx, dy, l);
1081}
1082
1083
1084Imath::Box2i
1085TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
1086{
1087     return _inputFile->dataWindowForTile (dx, dy, lx, ly);
1088}
1089
1090
1091void
1092TiledRgbaInputFile::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
1106void
1107TiledRgbaInputFile::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
1121void	
1122TiledRgbaInputFile::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
1139void	
1140TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
1141                               int l)
1142{
1143    readTiles (dxMin, dxMax, dyMin, dyMax, l, l);
1144}
1145
1146
1147void		
1148TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
1149{
1150    _outputFile->updatePreviewImage (newPixels);
1151}
1152
1153
1154void	
1155TiledRgbaOutputFile::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