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