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
insertChannels(Header & header,RgbaChannels rgbaChannels,const char fileName[])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
rgbaChannels(const ChannelList & ch,const string & channelNamePrefix="")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
prefixFromLayerName(const string & layerName,const Header & header)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
ywFromHeader(const Header & header)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 
ToYa(TiledOutputFile & outputFile,RgbaChannels rgbaChannels)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
setFrameBuffer(const Rgba * base,size_t xStride,size_t yStride)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
writeTile(int dx,int dy,int lx,int ly)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 
TiledRgbaOutputFile(const char name[],const Header & header,RgbaChannels rgbaChannels,int tileXSize,int tileYSize,LevelMode mode,LevelRoundingMode rmode,int numThreads)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 
TiledRgbaOutputFile(OStream & os,const Header & header,RgbaChannels rgbaChannels,int tileXSize,int tileYSize,LevelMode mode,LevelRoundingMode rmode,int numThreads)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 
TiledRgbaOutputFile(const char name[],int tileXSize,int tileYSize,LevelMode mode,LevelRoundingMode rmode,const Imath::Box2i & displayWindow,const Imath::Box2i & dataWindow,RgbaChannels rgbaChannels,float pixelAspectRatio,const Imath::V2f screenWindowCenter,float screenWindowWidth,LineOrder lineOrder,Compression compression,int numThreads)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 
TiledRgbaOutputFile(const char name[],int width,int height,int tileXSize,int tileYSize,LevelMode mode,LevelRoundingMode rmode,RgbaChannels rgbaChannels,float pixelAspectRatio,const Imath::V2f screenWindowCenter,float screenWindowWidth,LineOrder lineOrder,Compression compression,int numThreads)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 
~TiledRgbaOutputFile()378 TiledRgbaOutputFile::~TiledRgbaOutputFile ()
379 {
380     delete _outputFile;
381     delete _toYa;
382 }
383 
384 
385 void
setFrameBuffer(const Rgba * base,size_t xStride,size_t yStride)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 &
header() const413 TiledRgbaOutputFile::header () const
414 {
415     return _outputFile->header();
416 }
417 
418 
419 const FrameBuffer &
frameBuffer() const420 TiledRgbaOutputFile::frameBuffer () const
421 {
422     return _outputFile->frameBuffer();
423 }
424 
425 
426 const Imath::Box2i &
displayWindow() const427 TiledRgbaOutputFile::displayWindow () const
428 {
429     return _outputFile->header().displayWindow();
430 }
431 
432 
433 const Imath::Box2i &
dataWindow() const434 TiledRgbaOutputFile::dataWindow () const
435 {
436     return _outputFile->header().dataWindow();
437 }
438 
439 
440 float
pixelAspectRatio() const441 TiledRgbaOutputFile::pixelAspectRatio () const
442 {
443     return _outputFile->header().pixelAspectRatio();
444 }
445 
446 
447 const Imath::V2f
screenWindowCenter() const448 TiledRgbaOutputFile::screenWindowCenter () const
449 {
450     return _outputFile->header().screenWindowCenter();
451 }
452 
453 
454 float
screenWindowWidth() const455 TiledRgbaOutputFile::screenWindowWidth () const
456 {
457     return _outputFile->header().screenWindowWidth();
458 }
459 
460 
461 LineOrder
lineOrder() const462 TiledRgbaOutputFile::lineOrder () const
463 {
464     return _outputFile->header().lineOrder();
465 }
466 
467 
468 Compression
compression() const469 TiledRgbaOutputFile::compression () const
470 {
471     return _outputFile->header().compression();
472 }
473 
474 
475 RgbaChannels
channels() const476 TiledRgbaOutputFile::channels () const
477 {
478     return rgbaChannels (_outputFile->header().channels());
479 }
480 
481 
482 unsigned int
tileXSize() const483 TiledRgbaOutputFile::tileXSize () const
484 {
485      return _outputFile->tileXSize();
486 }
487 
488 
489 unsigned int
tileYSize() const490 TiledRgbaOutputFile::tileYSize () const
491 {
492      return _outputFile->tileYSize();
493 }
494 
495 
496 LevelMode
levelMode() const497 TiledRgbaOutputFile::levelMode () const
498 {
499      return _outputFile->levelMode();
500 }
501 
502 
503 LevelRoundingMode
levelRoundingMode() const504 TiledRgbaOutputFile::levelRoundingMode () const
505 {
506      return _outputFile->levelRoundingMode();
507 }
508 
509 
510 int
numLevels() const511 TiledRgbaOutputFile::numLevels () const
512 {
513      return _outputFile->numLevels();
514 }
515 
516 
517 int
numXLevels() const518 TiledRgbaOutputFile::numXLevels () const
519 {
520      return _outputFile->numXLevels();
521 }
522 
523 
524 int
numYLevels() const525 TiledRgbaOutputFile::numYLevels () const
526 {
527      return _outputFile->numYLevels();
528 }
529 
530 
531 bool
isValidLevel(int lx,int ly) const532 TiledRgbaOutputFile::isValidLevel (int lx, int ly) const
533 {
534     return _outputFile->isValidLevel (lx, ly);
535 }
536 
537 
538 int
levelWidth(int lx) const539 TiledRgbaOutputFile::levelWidth (int lx) const
540 {
541      return _outputFile->levelWidth (lx);
542 }
543 
544 
545 int
levelHeight(int ly) const546 TiledRgbaOutputFile::levelHeight (int ly) const
547 {
548      return _outputFile->levelHeight (ly);
549 }
550 
551 
552 int
numXTiles(int lx) const553 TiledRgbaOutputFile::numXTiles (int lx) const
554 {
555      return _outputFile->numXTiles (lx);
556 }
557 
558 
559 int
numYTiles(int ly) const560 TiledRgbaOutputFile::numYTiles (int ly) const
561 {
562      return _outputFile->numYTiles (ly);
563 }
564 
565 
566 Imath::Box2i
dataWindowForLevel(int l) const567 TiledRgbaOutputFile::dataWindowForLevel (int l) const
568 {
569      return _outputFile->dataWindowForLevel (l);
570 }
571 
572 
573 Imath::Box2i
dataWindowForLevel(int lx,int ly) const574 TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const
575 {
576      return _outputFile->dataWindowForLevel (lx, ly);
577 }
578 
579 
580 Imath::Box2i
dataWindowForTile(int dx,int dy,int l) const581 TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const
582 {
583      return _outputFile->dataWindowForTile (dx, dy, l);
584 }
585 
586 
587 Imath::Box2i
dataWindowForTile(int dx,int dy,int lx,int ly) const588 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
writeTile(int dx,int dy,int l)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
writeTile(int dx,int dy,int lx,int ly)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
writeTiles(int dxMin,int dxMax,int dyMin,int dyMax,int lx,int ly)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
writeTiles(int dxMin,int dxMax,int dyMin,int dyMax,int l)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 
FromYa(TiledInputFile & inputFile)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
setFrameBuffer(Rgba * base,size_t xStride,size_t yStride,const string & channelNamePrefix)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
readTile(int dx,int dy,int lx,int ly)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 
TiledRgbaInputFile(const char name[],int numThreads)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 
TiledRgbaInputFile(IStream & is,int numThreads)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 
TiledRgbaInputFile(const char name[],const string & layerName,int numThreads)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 
TiledRgbaInputFile(IStream & is,const string & layerName,int numThreads)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 
~TiledRgbaInputFile()817 TiledRgbaInputFile::~TiledRgbaInputFile ()
818 {
819     delete _inputFile;
820     delete _fromYa;
821 }
822 
823 
824 void
setFrameBuffer(Rgba * base,size_t xStride,size_t yStride)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
setLayerName(const std::string & layerName)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 &
header() const889 TiledRgbaInputFile::header () const
890 {
891     return _inputFile->header();
892 }
893 
894 
895 const char *
fileName() const896 TiledRgbaInputFile::fileName () const
897 {
898     return _inputFile->fileName();
899 }
900 
901 
902 const FrameBuffer &
frameBuffer() const903 TiledRgbaInputFile::frameBuffer () const
904 {
905     return _inputFile->frameBuffer();
906 }
907 
908 
909 const Imath::Box2i &
displayWindow() const910 TiledRgbaInputFile::displayWindow () const
911 {
912     return _inputFile->header().displayWindow();
913 }
914 
915 
916 const Imath::Box2i &
dataWindow() const917 TiledRgbaInputFile::dataWindow () const
918 {
919     return _inputFile->header().dataWindow();
920 }
921 
922 
923 float
pixelAspectRatio() const924 TiledRgbaInputFile::pixelAspectRatio () const
925 {
926     return _inputFile->header().pixelAspectRatio();
927 }
928 
929 
930 const Imath::V2f
screenWindowCenter() const931 TiledRgbaInputFile::screenWindowCenter () const
932 {
933     return _inputFile->header().screenWindowCenter();
934 }
935 
936 
937 float
screenWindowWidth() const938 TiledRgbaInputFile::screenWindowWidth () const
939 {
940     return _inputFile->header().screenWindowWidth();
941 }
942 
943 
944 LineOrder
lineOrder() const945 TiledRgbaInputFile::lineOrder () const
946 {
947     return _inputFile->header().lineOrder();
948 }
949 
950 
951 Compression
compression() const952 TiledRgbaInputFile::compression () const
953 {
954     return _inputFile->header().compression();
955 }
956 
957 
958 RgbaChannels
channels() const959 TiledRgbaInputFile::channels () const
960 {
961     return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
962 }
963 
964 
965 int
version() const966 TiledRgbaInputFile::version () const
967 {
968     return _inputFile->version();
969 }
970 
971 
972 bool
isComplete() const973 TiledRgbaInputFile::isComplete () const
974 {
975     return _inputFile->isComplete();
976 }
977 
978 
979 unsigned int
tileXSize() const980 TiledRgbaInputFile::tileXSize () const
981 {
982      return _inputFile->tileXSize();
983 }
984 
985 
986 unsigned int
tileYSize() const987 TiledRgbaInputFile::tileYSize () const
988 {
989      return _inputFile->tileYSize();
990 }
991 
992 
993 LevelMode
levelMode() const994 TiledRgbaInputFile::levelMode () const
995 {
996      return _inputFile->levelMode();
997 }
998 
999 
1000 LevelRoundingMode
levelRoundingMode() const1001 TiledRgbaInputFile::levelRoundingMode () const
1002 {
1003      return _inputFile->levelRoundingMode();
1004 }
1005 
1006 
1007 int
numLevels() const1008 TiledRgbaInputFile::numLevels () const
1009 {
1010      return _inputFile->numLevels();
1011 }
1012 
1013 
1014 int
numXLevels() const1015 TiledRgbaInputFile::numXLevels () const
1016 {
1017      return _inputFile->numXLevels();
1018 }
1019 
1020 
1021 int
numYLevels() const1022 TiledRgbaInputFile::numYLevels () const
1023 {
1024      return _inputFile->numYLevels();
1025 }
1026 
1027 
1028 bool
isValidLevel(int lx,int ly) const1029 TiledRgbaInputFile::isValidLevel (int lx, int ly) const
1030 {
1031     return _inputFile->isValidLevel (lx, ly);
1032 }
1033 
1034 
1035 int
levelWidth(int lx) const1036 TiledRgbaInputFile::levelWidth (int lx) const
1037 {
1038      return _inputFile->levelWidth (lx);
1039 }
1040 
1041 
1042 int
levelHeight(int ly) const1043 TiledRgbaInputFile::levelHeight (int ly) const
1044 {
1045      return _inputFile->levelHeight (ly);
1046 }
1047 
1048 
1049 int
numXTiles(int lx) const1050 TiledRgbaInputFile::numXTiles (int lx) const
1051 {
1052      return _inputFile->numXTiles(lx);
1053 }
1054 
1055 
1056 int
numYTiles(int ly) const1057 TiledRgbaInputFile::numYTiles (int ly) const
1058 {
1059      return _inputFile->numYTiles(ly);
1060 }
1061 
1062 
1063 Imath::Box2i
dataWindowForLevel(int l) const1064 TiledRgbaInputFile::dataWindowForLevel (int l) const
1065 {
1066      return _inputFile->dataWindowForLevel (l);
1067 }
1068 
1069 
1070 Imath::Box2i
dataWindowForLevel(int lx,int ly) const1071 TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const
1072 {
1073      return _inputFile->dataWindowForLevel (lx, ly);
1074 }
1075 
1076 
1077 Imath::Box2i
dataWindowForTile(int dx,int dy,int l) const1078 TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const
1079 {
1080      return _inputFile->dataWindowForTile (dx, dy, l);
1081 }
1082 
1083 
1084 Imath::Box2i
dataWindowForTile(int dx,int dy,int lx,int ly) const1085 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
readTile(int dx,int dy,int l)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
readTile(int dx,int dy,int lx,int ly)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
readTiles(int dxMin,int dxMax,int dyMin,int dyMax,int lx,int ly)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
readTiles(int dxMin,int dxMax,int dyMin,int dyMax,int l)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
updatePreviewImage(const PreviewRgba newPixels[])1148 TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
1149 {
1150     _outputFile->updatePreviewImage (newPixels);
1151 }
1152 
1153 
1154 void
breakTile(int dx,int dy,int lx,int ly,int offset,int length,char c)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