Blame IlmImf/ImfRgbaFile.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
Packit Service 6754ca
// Digital Ltd. LLC
Packit Service 6754ca
// 
Packit Service 6754ca
// All rights reserved.
Packit Service 6754ca
// 
Packit Service 6754ca
// Redistribution and use in source and binary forms, with or without
Packit Service 6754ca
// modification, are permitted provided that the following conditions are
Packit Service 6754ca
// met:
Packit Service 6754ca
// *       Redistributions of source code must retain the above copyright
Packit Service 6754ca
// notice, this list of conditions and the following disclaimer.
Packit Service 6754ca
// *       Redistributions in binary form must reproduce the above
Packit Service 6754ca
// copyright notice, this list of conditions and the following disclaimer
Packit Service 6754ca
// in the documentation and/or other materials provided with the
Packit Service 6754ca
// distribution.
Packit Service 6754ca
// *       Neither the name of Industrial Light & Magic nor the names of
Packit Service 6754ca
// its contributors may be used to endorse or promote products derived
Packit Service 6754ca
// from this software without specific prior written permission. 
Packit Service 6754ca
// 
Packit Service 6754ca
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6754ca
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 6754ca
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 6754ca
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 6754ca
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 6754ca
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 6754ca
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 6754ca
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 6754ca
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 6754ca
//
Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
//
Packit Service 6754ca
//	class RgbaOutputFile
Packit Service 6754ca
//	class RgbaInputFile
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include <ImfRgbaFile.h>
Packit Service 6754ca
#include <ImfOutputFile.h>
Packit Service 6754ca
#include <ImfInputFile.h>
Packit Service 6754ca
#include <ImfChannelList.h>
Packit Service 6754ca
#include <ImfRgbaYca.h>
Packit Service 6754ca
#include <ImfStandardAttributes.h>
Packit Service 6754ca
#include <ImathFun.h>
Packit Service 6754ca
#include <IlmThreadMutex.h>
Packit Service 6754ca
#include <Iex.h>
Packit Service 6754ca
#include <string.h>
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
Packit Service 6754ca
using namespace std;
Packit Service 6754ca
using namespace IMATH_NAMESPACE;
Packit Service 6754ca
using namespace RgbaYca;
Packit Service 6754ca
using namespace ILMTHREAD_NAMESPACE;
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
insertChannels (Header &header, RgbaChannels rgbaChannels)
Packit Service 6754ca
{
Packit Service 6754ca
    ChannelList ch;
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
    {
Packit Service 6754ca
	if (rgbaChannels & WRITE_Y)
Packit Service 6754ca
	{
Packit Service 6754ca
	    ch.insert ("Y", Channel (HALF, 1, 1));
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	if (rgbaChannels & WRITE_C)
Packit Service 6754ca
	{
Packit Service 6754ca
	    ch.insert ("RY", Channel (HALF, 2, 2, true));
Packit Service 6754ca
	    ch.insert ("BY", Channel (HALF, 2, 2, true));
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	if (rgbaChannels & WRITE_R)
Packit Service 6754ca
	    ch.insert ("R", Channel (HALF, 1, 1));
Packit Service 6754ca
Packit Service 6754ca
	if (rgbaChannels & WRITE_G)
Packit Service 6754ca
	    ch.insert ("G", Channel (HALF, 1, 1));
Packit Service 6754ca
Packit Service 6754ca
	if (rgbaChannels & WRITE_B)
Packit Service 6754ca
	    ch.insert ("B", Channel (HALF, 1, 1));
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & WRITE_A)
Packit Service 6754ca
	ch.insert ("A", Channel (HALF, 1, 1));
Packit Service 6754ca
Packit Service 6754ca
    header.channels() = ch;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaChannels
Packit Service 6754ca
rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "")
Packit Service 6754ca
{
Packit Service 6754ca
    int i = 0;
Packit Service 6754ca
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "R"))
Packit Service 6754ca
	i |= WRITE_R;
Packit Service 6754ca
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "G"))
Packit Service 6754ca
	i |= WRITE_G;
Packit Service 6754ca
    
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "B"))
Packit Service 6754ca
	i |= WRITE_B;
Packit Service 6754ca
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "A"))
Packit Service 6754ca
	i |= WRITE_A;
Packit Service 6754ca
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "Y"))
Packit Service 6754ca
	i |= WRITE_Y;
Packit Service 6754ca
Packit Service 6754ca
    if (ch.findChannel (channelNamePrefix + "RY") ||
Packit Service 6754ca
	ch.findChannel (channelNamePrefix + "BY"))
Packit Service 6754ca
	i |= WRITE_C;
Packit Service 6754ca
Packit Service 6754ca
    return RgbaChannels (i);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
string
Packit Service 6754ca
prefixFromLayerName (const string &layerName, const Header &header)
Packit Service 6754ca
{
Packit Service 6754ca
    if (layerName.empty())
Packit Service 6754ca
	return "";
Packit Service 6754ca
Packit Service 6754ca
    if (hasMultiView (header) && multiView(header)[0] == layerName)
Packit Service 6754ca
	return "";
Packit Service 6754ca
Packit Service 6754ca
    return layerName + ".";
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
V3f
Packit Service 6754ca
ywFromHeader (const Header &header)
Packit Service 6754ca
{
Packit Service 6754ca
    Chromaticities cr;
Packit Service 6754ca
Packit Service 6754ca
    if (hasChromaticities (header))
Packit Service 6754ca
	cr = chromaticities (header);
Packit Service 6754ca
Packit Service 6754ca
    return computeYw (cr);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
ptrdiff_t
Packit Service 6754ca
cachePadding (ptrdiff_t size)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Some of the buffers that are allocated by classes ToYca and
Packit Service 6754ca
    // FromYca, below, may need to be padded to avoid cache thrashing.
Packit Service 6754ca
    // If the difference between the buffer size and the nearest power
Packit Service 6754ca
    // of two is less than CACHE_LINE_SIZE, then we add an appropriate
Packit Service 6754ca
    // amount of padding.
Packit Service 6754ca
    //
Packit Service 6754ca
    // CACHE_LINE_SIZE must be a power of two, and it must be at
Packit Service 6754ca
    // least as big as the true size of a cache line on the machine
Packit Service 6754ca
    // we are running on.  (It is ok if CACHE_LINE_SIZE is larger
Packit Service 6754ca
    // than a real cache line.)
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    static int LOG2_CACHE_LINE_SIZE = 8;
Packit Service 6754ca
    static const ptrdiff_t CACHE_LINE_SIZE = (1 << LOG2_CACHE_LINE_SIZE);
Packit Service 6754ca
Packit Service 6754ca
    int i = LOG2_CACHE_LINE_SIZE + 2;
Packit Service 6754ca
Packit Service 6754ca
    while ((size >> i) > 1)
Packit Service 6754ca
	++i;
Packit Service 6754ca
Packit Service 6754ca
    if (size > (1 << (i + 1)) - 64)
Packit Service 6754ca
	return 64 + ((1 << (i + 1)) - size);
Packit Service 6754ca
Packit Service 6754ca
    if (size < (1 << i) + 64)
Packit Service 6754ca
	return 64 + ((1 << i) - size);
Packit Service 6754ca
Packit Service 6754ca
    return 0;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
class RgbaOutputFile::ToYca: public Mutex
Packit Service 6754ca
{
Packit Service 6754ca
  public:
Packit Service 6754ca
Packit Service 6754ca
     ToYca (OutputFile &outputFile, RgbaChannels rgbaChannels);
Packit Service 6754ca
    ~ToYca ();
Packit Service 6754ca
Packit Service 6754ca
    void		setYCRounding (unsigned int roundY,
Packit Service 6754ca
	    			       unsigned int roundC);
Packit Service 6754ca
Packit Service 6754ca
    void		setFrameBuffer (const Rgba *base,
Packit Service 6754ca
					size_t xStride,
Packit Service 6754ca
					size_t yStride);
Packit Service 6754ca
Packit Service 6754ca
    void		writePixels (int numScanLines);
Packit Service 6754ca
    int			currentScanLine () const;
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    void		padTmpBuf ();
Packit Service 6754ca
    void		rotateBuffers ();
Packit Service 6754ca
    void		duplicateLastBuffer ();
Packit Service 6754ca
    void		duplicateSecondToLastBuffer ();
Packit Service 6754ca
    void		decimateChromaVertAndWriteScanLine ();
Packit Service 6754ca
Packit Service 6754ca
    OutputFile &	_outputFile;
Packit Service 6754ca
    bool		_writeY;
Packit Service 6754ca
    bool		_writeC;
Packit Service 6754ca
    bool		_writeA;
Packit Service 6754ca
    int			_xMin;
Packit Service 6754ca
    int			_width;
Packit Service 6754ca
    int			_height;
Packit Service 6754ca
    int			_linesConverted;
Packit Service 6754ca
    LineOrder		_lineOrder;
Packit Service 6754ca
    int			_currentScanLine;
Packit Service 6754ca
    V3f			_yw;
Packit Service 6754ca
    Rgba *		_bufBase;
Packit Service 6754ca
    Rgba *		_buf[N];
Packit Service 6754ca
    Rgba *		_tmpBuf;
Packit Service 6754ca
    const Rgba *	_fbBase;
Packit Service 6754ca
    size_t		_fbXStride;
Packit Service 6754ca
    size_t		_fbYStride;
Packit Service 6754ca
    int			_roundY;
Packit Service 6754ca
    int			_roundC;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile,
Packit Service 6754ca
			      RgbaChannels rgbaChannels)
Packit Service 6754ca
:
Packit Service 6754ca
    _outputFile (outputFile)
Packit Service 6754ca
{
Packit Service 6754ca
    _writeY = (rgbaChannels & WRITE_Y)? true: false;
Packit Service 6754ca
    _writeC = (rgbaChannels & WRITE_C)? true: false;
Packit Service 6754ca
    _writeA = (rgbaChannels & WRITE_A)? true: false;
Packit Service 6754ca
Packit Service 6754ca
    const Box2i dw = _outputFile.header().dataWindow();
Packit Service 6754ca
Packit Service 6754ca
    _xMin = dw.min.x;
Packit Service 6754ca
    _width  = dw.max.x - dw.min.x + 1;
Packit Service 6754ca
    _height = dw.max.y - dw.min.y + 1;
Packit Service 6754ca
Packit Service 6754ca
    _linesConverted = 0;
Packit Service 6754ca
    _lineOrder = _outputFile.header().lineOrder();
Packit Service 6754ca
    
Packit Service 6754ca
    if (_lineOrder == INCREASING_Y)
Packit Service 6754ca
	_currentScanLine = dw.min.y;
Packit Service 6754ca
    else
Packit Service 6754ca
	_currentScanLine = dw.max.y;
Packit Service 6754ca
Packit Service 6754ca
    _yw = ywFromHeader (_outputFile.header());
Packit Service 6754ca
Packit Service 6754ca
    ptrdiff_t pad = cachePadding (_width * sizeof (Rgba)) / sizeof (Rgba);
Packit Service 6754ca
Packit Service 6754ca
    _bufBase = new Rgba[(_width + pad) * N];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < N; ++i)
Packit Service 6754ca
	_buf[i] = _bufBase + (i * (_width + pad));
Packit Service 6754ca
Packit Service 6754ca
    _tmpBuf = new Rgba[_width + N - 1];
Packit Service 6754ca
Packit Service 6754ca
    _fbBase = 0;
Packit Service 6754ca
    _fbXStride = 0;
Packit Service 6754ca
    _fbYStride = 0;
Packit Service 6754ca
Packit Service 6754ca
    _roundY = 7;
Packit Service 6754ca
    _roundC = 5;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::ToYca::~ToYca ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete [] _bufBase;
Packit Service 6754ca
    delete [] _tmpBuf;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::setYCRounding (unsigned int roundY,
Packit Service 6754ca
				      unsigned int roundC)
Packit Service 6754ca
{
Packit Service 6754ca
    _roundY = roundY;
Packit Service 6754ca
    _roundC = roundC;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::setFrameBuffer (const Rgba *base,
Packit Service 6754ca
				       size_t xStride,
Packit Service 6754ca
				       size_t yStride)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fbBase == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
	FrameBuffer fb;
Packit Service 6754ca
Packit Service 6754ca
	if (_writeY)
Packit Service 6754ca
	{
Packit Service 6754ca
	    fb.insert ("Y",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[-_xMin].g,	// base
Packit Service 6754ca
			      sizeof (Rgba),			// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      1,				// xSampling
Packit Service 6754ca
			      1));				// ySampling
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	if (_writeC)
Packit Service 6754ca
	{
Packit Service 6754ca
	    fb.insert ("RY",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[-_xMin].r,	// base
Packit Service 6754ca
			      sizeof (Rgba) * 2,		// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      2,				// xSampling
Packit Service 6754ca
			      2));				// ySampling
Packit Service 6754ca
Packit Service 6754ca
	    fb.insert ("BY",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[-_xMin].b,	// base
Packit Service 6754ca
			      sizeof (Rgba) * 2,		// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      2,				// xSampling
Packit Service 6754ca
			      2));				// ySampling
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	if (_writeA)
Packit Service 6754ca
	{
Packit Service 6754ca
	    fb.insert ("A",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[-_xMin].a,	// base
Packit Service 6754ca
			      sizeof (Rgba),			// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      1,				// xSampling
Packit Service 6754ca
			      1));				// ySampling
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	_outputFile.setFrameBuffer (fb);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    _fbBase = base;
Packit Service 6754ca
    _fbXStride = xStride;
Packit Service 6754ca
    _fbYStride = yStride;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::writePixels (int numScanLines)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fbBase == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
	THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the "
Packit Service 6754ca
			    "pixel data source for image file "
Packit Service 6754ca
			    "\"" << _outputFile.fileName() << "\".");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (_writeY && !_writeC)
Packit Service 6754ca
    {
Packit Service 6754ca
	//
Packit Service 6754ca
	// We are writing only luminance; filtering
Packit Service 6754ca
	// and subsampling are not necessary.
Packit Service 6754ca
	//
Packit Service 6754ca
Packit Service 6754ca
	for (int i = 0; i < numScanLines; ++i)
Packit Service 6754ca
	{
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Copy the next scan line from the caller's
Packit Service 6754ca
	    // frame buffer into _tmpBuf.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    for (int j = 0; j < _width; ++j)
Packit Service 6754ca
	    {
Packit Service 6754ca
		_tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine +
Packit Service 6754ca
				     _fbXStride * (j + _xMin)];
Packit Service 6754ca
	    }
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Convert the scan line from RGB to luminance/chroma,
Packit Service 6754ca
	    // and store the result in the output file.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf);
Packit Service 6754ca
	    _outputFile.writePixels (1);
Packit Service 6754ca
Packit Service 6754ca
	    ++_linesConverted;
Packit Service 6754ca
Packit Service 6754ca
	    if (_lineOrder == INCREASING_Y)
Packit Service 6754ca
		++_currentScanLine;
Packit Service 6754ca
	    else
Packit Service 6754ca
		--_currentScanLine;
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	//
Packit Service 6754ca
	// We are writing chroma; the pixels must be filtered and subsampled.
Packit Service 6754ca
	//
Packit Service 6754ca
Packit Service 6754ca
	for (int i = 0; i < numScanLines; ++i)
Packit Service 6754ca
	{
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Copy the next scan line from the caller's
Packit Service 6754ca
	    // frame buffer into _tmpBuf.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    for (int j = 0; j < _width; ++j)
Packit Service 6754ca
	    {
Packit Service 6754ca
		_tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine +
Packit Service 6754ca
					  _fbXStride * (j + _xMin)];
Packit Service 6754ca
	    }
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Convert the scan line from RGB to luminance/chroma.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2);
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Append N2 copies of the first and last pixel to the
Packit Service 6754ca
	    // beginning and end of the scan line.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    padTmpBuf ();
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // Filter and subsample the scan line's chroma channels
Packit Service 6754ca
	    // horizontally; store the result in _buf.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    rotateBuffers();
Packit Service 6754ca
	    decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]);
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // If this is the first scan line in the image,
Packit Service 6754ca
	    // store N2 more copies of the scan line in _buf.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    if (_linesConverted == 0)
Packit Service 6754ca
	    {
Packit Service 6754ca
		for (int j = 0; j < N2; ++j)
Packit Service 6754ca
		    duplicateLastBuffer();
Packit Service 6754ca
	    }
Packit Service 6754ca
Packit Service 6754ca
	    ++_linesConverted;
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // If we have have converted at least N2 scan lines from
Packit Service 6754ca
	    // RGBA to luminance/chroma, then we can start to filter
Packit Service 6754ca
	    // and subsample vertically, and store pixels in the
Packit Service 6754ca
	    // output file.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    if (_linesConverted > N2)
Packit Service 6754ca
		decimateChromaVertAndWriteScanLine();
Packit Service 6754ca
Packit Service 6754ca
	    //
Packit Service 6754ca
	    // If we have already converted the last scan line in
Packit Service 6754ca
	    // the image to luminance/chroma, filter, subsample and
Packit Service 6754ca
	    // store the remaining scan lines in _buf.
Packit Service 6754ca
	    //
Packit Service 6754ca
Packit Service 6754ca
	    if (_linesConverted >= _height)
Packit Service 6754ca
	    {
Packit Service 6754ca
		for (int j = 0; j < N2 - _height; ++j)
Packit Service 6754ca
		    duplicateLastBuffer();
Packit Service 6754ca
Packit Service 6754ca
		duplicateSecondToLastBuffer();
Packit Service 6754ca
		++_linesConverted;
Packit Service 6754ca
		decimateChromaVertAndWriteScanLine();
Packit Service 6754ca
Packit Service 6754ca
		for (int j = 1; j < min (_height, N2); ++j)
Packit Service 6754ca
		{
Packit Service 6754ca
		    duplicateLastBuffer();
Packit Service 6754ca
		    ++_linesConverted;
Packit Service 6754ca
		    decimateChromaVertAndWriteScanLine();
Packit Service 6754ca
		}
Packit Service 6754ca
	    }
Packit Service 6754ca
Packit Service 6754ca
	    if (_lineOrder == INCREASING_Y)
Packit Service 6754ca
		++_currentScanLine;
Packit Service 6754ca
	    else
Packit Service 6754ca
		--_currentScanLine;
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
RgbaOutputFile::ToYca::currentScanLine () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _currentScanLine;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::padTmpBuf ()
Packit Service 6754ca
{
Packit Service 6754ca
    for (int i = 0; i < N2; ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
	_tmpBuf[i] = _tmpBuf[N2];
Packit Service 6754ca
	_tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::rotateBuffers ()
Packit Service 6754ca
{
Packit Service 6754ca
    Rgba *tmp = _buf[0];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < N - 1; ++i)
Packit Service 6754ca
	_buf[i] = _buf[i + 1];
Packit Service 6754ca
Packit Service 6754ca
    _buf[N - 1] = tmp;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::duplicateLastBuffer ()
Packit Service 6754ca
{
Packit Service 6754ca
    rotateBuffers();
Packit Service 6754ca
    memcpy (_buf[N - 1], _buf[N - 2], _width * sizeof (Rgba));
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::duplicateSecondToLastBuffer ()
Packit Service 6754ca
{
Packit Service 6754ca
    rotateBuffers();
Packit Service 6754ca
    memcpy (_buf[N - 1], _buf[N - 3], _width * sizeof (Rgba));
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::ToYca::decimateChromaVertAndWriteScanLine ()
Packit Service 6754ca
{
Packit Service 6754ca
    if (_linesConverted & 1)
Packit Service 6754ca
	memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba));
Packit Service 6754ca
    else
Packit Service 6754ca
	decimateChromaVert (_width, _buf, _tmpBuf);
Packit Service 6754ca
Packit Service 6754ca
    if (_writeY && _writeC)
Packit Service 6754ca
	roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf);
Packit Service 6754ca
Packit Service 6754ca
    _outputFile.writePixels (1);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::RgbaOutputFile (const char name[],
Packit Service 6754ca
				const Header &header,
Packit Service 6754ca
				RgbaChannels rgbaChannels,
Packit Service 6754ca
                                int numThreads):
Packit Service 6754ca
    _outputFile (0),
Packit Service 6754ca
    _toYca (0)
Packit Service 6754ca
{
Packit Service 6754ca
    Header hd (header);
Packit Service 6754ca
    insertChannels (hd, rgbaChannels);
Packit Service 6754ca
    _outputFile = new OutputFile (name, hd, numThreads);
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_toYca = new ToYca (*_outputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::RgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
Packit Service 6754ca
				const Header &header,
Packit Service 6754ca
				RgbaChannels rgbaChannels,
Packit Service 6754ca
                                int numThreads):
Packit Service 6754ca
    _outputFile (0),
Packit Service 6754ca
    _toYca (0)
Packit Service 6754ca
{
Packit Service 6754ca
    Header hd (header);
Packit Service 6754ca
    insertChannels (hd, rgbaChannels);
Packit Service 6754ca
    _outputFile = new OutputFile (os, hd, numThreads);
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_toYca = new ToYca (*_outputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::RgbaOutputFile (const char name[],
Packit Service 6754ca
				const IMATH_NAMESPACE::Box2i &displayWindow,
Packit Service 6754ca
				const IMATH_NAMESPACE::Box2i &dataWindow,
Packit Service 6754ca
				RgbaChannels rgbaChannels,
Packit Service 6754ca
				float pixelAspectRatio,
Packit Service 6754ca
				const IMATH_NAMESPACE::V2f screenWindowCenter,
Packit Service 6754ca
				float screenWindowWidth,
Packit Service 6754ca
				LineOrder lineOrder,
Packit Service 6754ca
				Compression compression,
Packit Service 6754ca
                                int numThreads):
Packit Service 6754ca
    _outputFile (0),
Packit Service 6754ca
    _toYca (0)
Packit Service 6754ca
{
Packit Service 6754ca
    Header hd (displayWindow,
Packit Service 6754ca
	       dataWindow.isEmpty()? displayWindow: dataWindow,
Packit Service 6754ca
	       pixelAspectRatio,
Packit Service 6754ca
	       screenWindowCenter,
Packit Service 6754ca
	       screenWindowWidth,
Packit Service 6754ca
	       lineOrder,
Packit Service 6754ca
	       compression);
Packit Service 6754ca
Packit Service 6754ca
    insertChannels (hd, rgbaChannels);
Packit Service 6754ca
    _outputFile = new OutputFile (name, hd, numThreads);
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_toYca = new ToYca (*_outputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::RgbaOutputFile (const char name[],
Packit Service 6754ca
				int width,
Packit Service 6754ca
				int height,
Packit Service 6754ca
				RgbaChannels rgbaChannels,
Packit Service 6754ca
				float pixelAspectRatio,
Packit Service 6754ca
				const IMATH_NAMESPACE::V2f screenWindowCenter,
Packit Service 6754ca
				float screenWindowWidth,
Packit Service 6754ca
				LineOrder lineOrder,
Packit Service 6754ca
				Compression compression,
Packit Service 6754ca
                                int numThreads):
Packit Service 6754ca
    _outputFile (0),
Packit Service 6754ca
    _toYca (0)
Packit Service 6754ca
{
Packit Service 6754ca
    Header hd (width,
Packit Service 6754ca
	       height,
Packit Service 6754ca
	       pixelAspectRatio,
Packit Service 6754ca
	       screenWindowCenter,
Packit Service 6754ca
	       screenWindowWidth,
Packit Service 6754ca
	       lineOrder,
Packit Service 6754ca
	       compression);
Packit Service 6754ca
Packit Service 6754ca
    insertChannels (hd, rgbaChannels);
Packit Service 6754ca
    _outputFile = new OutputFile (name, hd, numThreads);
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_toYca = new ToYca (*_outputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaOutputFile::~RgbaOutputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete _toYca;
Packit Service 6754ca
    delete _outputFile;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaOutputFile::setFrameBuffer (const Rgba *base,
Packit Service 6754ca
				size_t xStride,
Packit Service 6754ca
				size_t yStride)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_toYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_toYca);
Packit Service 6754ca
	_toYca->setFrameBuffer (base, xStride, yStride);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	size_t xs = xStride * sizeof (Rgba);
Packit Service 6754ca
	size_t ys = yStride * sizeof (Rgba);
Packit Service 6754ca
Packit Service 6754ca
	FrameBuffer fb;
Packit Service 6754ca
Packit Service 6754ca
	fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));
Packit Service 6754ca
	fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));
Packit Service 6754ca
	fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));
Packit Service 6754ca
	fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));
Packit Service 6754ca
Packit Service 6754ca
	_outputFile->setFrameBuffer (fb);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaOutputFile::writePixels (int numScanLines)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_toYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_toYca);
Packit Service 6754ca
	_toYca->writePixels (numScanLines);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	_outputFile->writePixels (numScanLines);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int	
Packit Service 6754ca
RgbaOutputFile::currentScanLine () const
Packit Service 6754ca
{
Packit Service 6754ca
    if (_toYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_toYca);
Packit Service 6754ca
	return _toYca->currentScanLine();
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	return _outputFile->currentScanLine();
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
RgbaOutputFile::header () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const FrameBuffer &
Packit Service 6754ca
RgbaOutputFile::frameBuffer () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->frameBuffer();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::Box2i &
Packit Service 6754ca
RgbaOutputFile::displayWindow () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().displayWindow();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::Box2i &
Packit Service 6754ca
RgbaOutputFile::dataWindow () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().dataWindow();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
float	
Packit Service 6754ca
RgbaOutputFile::pixelAspectRatio () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().pixelAspectRatio();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::V2f
Packit Service 6754ca
RgbaOutputFile::screenWindowCenter () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().screenWindowCenter();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
float	
Packit Service 6754ca
RgbaOutputFile::screenWindowWidth () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().screenWindowWidth();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineOrder
Packit Service 6754ca
RgbaOutputFile::lineOrder () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().lineOrder();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Compression
Packit Service 6754ca
RgbaOutputFile::compression () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _outputFile->header().compression();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaChannels
Packit Service 6754ca
RgbaOutputFile::channels () const
Packit Service 6754ca
{
Packit Service 6754ca
    return rgbaChannels (_outputFile->header().channels());
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void		
Packit Service 6754ca
RgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
Packit Service 6754ca
{
Packit Service 6754ca
    _outputFile->updatePreviewImage (newPixels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void		
Packit Service 6754ca
RgbaOutputFile::setYCRounding (unsigned int roundY, unsigned int roundC)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_toYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_toYca);
Packit Service 6754ca
	_toYca->setYCRounding (roundY, roundC);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaOutputFile::breakScanLine  (int y, int offset, int length, char c)
Packit Service 6754ca
{
Packit Service 6754ca
    _outputFile->breakScanLine (y, offset, length, c);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
class RgbaInputFile::FromYca: public Mutex
Packit Service 6754ca
{
Packit Service 6754ca
  public:
Packit Service 6754ca
Packit Service 6754ca
     FromYca (InputFile &inputFile, RgbaChannels rgbaChannels);
Packit Service 6754ca
    ~FromYca ();
Packit Service 6754ca
Packit Service 6754ca
    void		setFrameBuffer (Rgba *base,
Packit Service 6754ca
					size_t xStride,
Packit Service 6754ca
					size_t yStride,
Packit Service 6754ca
					const string &channelNamePrefix);
Packit Service 6754ca
Packit Service 6754ca
    void		readPixels (int scanLine1, int scanLine2);
Packit Service 6754ca
Packit Service 6754ca
  private:
Packit Service 6754ca
Packit Service 6754ca
    void		readPixels (int scanLine);
Packit Service 6754ca
    void		rotateBuf1 (int d);
Packit Service 6754ca
    void		rotateBuf2 (int d);
Packit Service 6754ca
    void		readYCAScanLine (int y, Rgba buf[]);
Packit Service 6754ca
    void		padTmpBuf ();
Packit Service 6754ca
Packit Service 6754ca
    InputFile &		_inputFile;
Packit Service 6754ca
    bool		_readC;
Packit Service 6754ca
    int			_xMin;
Packit Service 6754ca
    int			_yMin;
Packit Service 6754ca
    int 		_yMax;
Packit Service 6754ca
    int			_width;
Packit Service 6754ca
    int			_height;
Packit Service 6754ca
    int			_currentScanLine;
Packit Service 6754ca
    LineOrder		_lineOrder;
Packit Service 6754ca
    V3f			_yw;
Packit Service 6754ca
    Rgba *		_bufBase;
Packit Service 6754ca
    Rgba *		_buf1[N + 2];
Packit Service 6754ca
    Rgba *		_buf2[3];
Packit Service 6754ca
    Rgba *		_tmpBuf;
Packit Service 6754ca
    Rgba *		_fbBase;
Packit Service 6754ca
    size_t		_fbXStride;
Packit Service 6754ca
    size_t		_fbYStride;
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::FromYca::FromYca (InputFile &inputFile,
Packit Service 6754ca
				 RgbaChannels rgbaChannels)
Packit Service 6754ca
:
Packit Service 6754ca
    _inputFile (inputFile)
Packit Service 6754ca
{
Packit Service 6754ca
    _readC = (rgbaChannels & WRITE_C)? true: false;
Packit Service 6754ca
Packit Service 6754ca
    const Box2i dw = _inputFile.header().dataWindow();
Packit Service 6754ca
Packit Service 6754ca
    _xMin = dw.min.x;
Packit Service 6754ca
    _yMin = dw.min.y;
Packit Service 6754ca
    _yMax = dw.max.y;
Packit Service 6754ca
    _width  = dw.max.x - dw.min.x + 1;
Packit Service 6754ca
    _height = dw.max.y - dw.min.y + 1;
Packit Service 6754ca
    _currentScanLine = dw.min.y - N - 2;
Packit Service 6754ca
    _lineOrder = _inputFile.header().lineOrder();
Packit Service 6754ca
    _yw = ywFromHeader (_inputFile.header());
Packit Service 6754ca
Packit Service 6754ca
    ptrdiff_t pad = cachePadding (_width * sizeof (Rgba)) / sizeof (Rgba);
Packit Service 6754ca
Packit Service 6754ca
    _bufBase = new Rgba[(_width + pad) * (N + 2 + 3)];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < N + 2; ++i)
Packit Service 6754ca
	_buf1[i] = _bufBase + (i * (_width + pad));
Packit Service 6754ca
    
Packit Service 6754ca
    for (int i = 0; i < 3; ++i)
Packit Service 6754ca
	_buf2[i] = _bufBase + ((i + N + 2) * (_width + pad));
Packit Service 6754ca
Packit Service 6754ca
    _tmpBuf = new Rgba[_width + N - 1];
Packit Service 6754ca
Packit Service 6754ca
    _fbBase = 0;
Packit Service 6754ca
    _fbXStride = 0;
Packit Service 6754ca
    _fbYStride = 0;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::FromYca::~FromYca ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete [] _bufBase;
Packit Service 6754ca
    delete [] _tmpBuf;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::FromYca::setFrameBuffer (Rgba *base,
Packit Service 6754ca
					size_t xStride,
Packit Service 6754ca
					size_t yStride,
Packit Service 6754ca
					const string &channelNamePrefix)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fbBase == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
	FrameBuffer fb;
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (channelNamePrefix + "Y",
Packit Service 6754ca
		   Slice (HALF,					// type
Packit Service 6754ca
			  (char *) &_tmpBuf[N2 - _xMin].g,	// base
Packit Service 6754ca
			  sizeof (Rgba),			// xStride
Packit Service 6754ca
			  0,					// yStride
Packit Service 6754ca
			  1,					// xSampling
Packit Service 6754ca
			  1,					// ySampling
Packit Service 6754ca
			  0.5));				// fillValue
Packit Service 6754ca
Packit Service 6754ca
	if (_readC)
Packit Service 6754ca
	{
Packit Service 6754ca
	    fb.insert (channelNamePrefix + "RY",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[N2 - _xMin].r,	// base
Packit Service 6754ca
			      sizeof (Rgba) * 2,		// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      2,				// xSampling
Packit Service 6754ca
			      2,				// ySampling
Packit Service 6754ca
			      0.0));				// fillValue
Packit Service 6754ca
Packit Service 6754ca
	    fb.insert (channelNamePrefix + "BY",
Packit Service 6754ca
		       Slice (HALF,				// type
Packit Service 6754ca
			      (char *) &_tmpBuf[N2 - _xMin].b,	// base
Packit Service 6754ca
			      sizeof (Rgba) * 2,		// xStride
Packit Service 6754ca
			      0,				// yStride
Packit Service 6754ca
			      2,				// xSampling
Packit Service 6754ca
			      2,				// ySampling
Packit Service 6754ca
			      0.0));				// fillValue
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (channelNamePrefix + "A",
Packit Service 6754ca
		   Slice (HALF,					// type
Packit Service 6754ca
			  (char *) &_tmpBuf[N2 - _xMin].a,	// base
Packit Service 6754ca
			  sizeof (Rgba),			// xStride
Packit Service 6754ca
			  0,					// yStride
Packit Service 6754ca
			  1,					// xSampling
Packit Service 6754ca
			  1,					// ySampling
Packit Service 6754ca
			  1.0));				// fillValue
Packit Service 6754ca
Packit Service 6754ca
	_inputFile.setFrameBuffer (fb);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    _fbBase = base;
Packit Service 6754ca
    _fbXStride = xStride;
Packit Service 6754ca
    _fbYStride = yStride;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2)
Packit Service 6754ca
{
Packit Service 6754ca
    int minY = min (scanLine1, scanLine2);
Packit Service 6754ca
    int maxY = max (scanLine1, scanLine2);
Packit Service 6754ca
Packit Service 6754ca
    if (_lineOrder == INCREASING_Y)
Packit Service 6754ca
    {
Packit Service 6754ca
	for (int y = minY; y <= maxY; ++y)
Packit Service 6754ca
	    readPixels (y);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	for (int y = maxY; y >= minY; --y)
Packit Service 6754ca
	    readPixels (y);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaInputFile::FromYca::readPixels (int scanLine)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fbBase == 0)
Packit Service 6754ca
    {
Packit Service 6754ca
	THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the "
Packit Service 6754ca
			    "pixel data destination for image file "
Packit Service 6754ca
			    "\"" << _inputFile.fileName() << "\".");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // In order to convert one scan line to RGB format, we need that
Packit Service 6754ca
    // scan line plus N2+1 extra scan lines above and N2+1 scan lines
Packit Service 6754ca
    // below in luminance/chroma format.
Packit Service 6754ca
    //
Packit Service 6754ca
    // We allow random access to scan lines, but we buffer partially
Packit Service 6754ca
    // processed luminance/chroma data in order to make reading pixels
Packit Service 6754ca
    // in increasing y or decreasing y order reasonably efficient:
Packit Service 6754ca
    //
Packit Service 6754ca
    //	_currentScanLine	holds the y coordinate of the scan line
Packit Service 6754ca
    //				that was most recently read.
Packit Service 6754ca
    //
Packit Service 6754ca
    //	_buf1			contains scan lines _currentScanLine-N2-1
Packit Service 6754ca
    //				through _currentScanLine+N2+1 in
Packit Service 6754ca
    //				luminance/chroma format.  Odd-numbered
Packit Service 6754ca
    //				lines contain no chroma data.  Even-numbered
Packit Service 6754ca
    //				lines have valid chroma data for all pixels.
Packit Service 6754ca
    //
Packit Service 6754ca
    //  _buf2			contains scan lines _currentScanLine-1
Packit Service 6754ca
    //  			through _currentScanLine+1, in RGB format.
Packit Service 6754ca
    //				Super-saturated pixels (see ImfRgbaYca.h)
Packit Service 6754ca
    //				have not yet been eliminated.
Packit Service 6754ca
    //
Packit Service 6754ca
    // If the scan line we are trying to read now is close enough to
Packit Service 6754ca
    // _currentScanLine, we don't have to recompute the contents of _buf1
Packit Service 6754ca
    // and _buf2 from scratch.  We can rotate _buf1 and _buf2, and fill
Packit Service 6754ca
    // in the missing data.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int dy = scanLine - _currentScanLine;
Packit Service 6754ca
Packit Service 6754ca
    if (abs (dy) < N + 2)
Packit Service 6754ca
	rotateBuf1 (dy);
Packit Service 6754ca
Packit Service 6754ca
    if (abs (dy) < 3)
Packit Service 6754ca
	rotateBuf2 (dy);
Packit Service 6754ca
Packit Service 6754ca
    if (dy < 0)
Packit Service 6754ca
    {
Packit Service 6754ca
	{
Packit Service 6754ca
	    int n = min (-dy, N + 2);
Packit Service 6754ca
	    int yMin = scanLine - N2 - 1;
Packit Service 6754ca
Packit Service 6754ca
	    for (int i = n - 1; i >= 0; --i)
Packit Service 6754ca
		readYCAScanLine (yMin + i, _buf1[i]);
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	    int n = min (-dy, 3);
Packit Service 6754ca
Packit Service 6754ca
	    for (int i = 0; i < n; ++i)
Packit Service 6754ca
	    {
Packit Service 6754ca
		if ((scanLine + i) & 1)
Packit Service 6754ca
		{
Packit Service 6754ca
		    YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
Packit Service 6754ca
		}
Packit Service 6754ca
		else
Packit Service 6754ca
		{
Packit Service 6754ca
		    reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
Packit Service 6754ca
		    YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
Packit Service 6754ca
		}
Packit Service 6754ca
	    }
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	{
Packit Service 6754ca
	    int n = min (dy, N + 2);
Packit Service 6754ca
	    int yMax = scanLine + N2 + 1;
Packit Service 6754ca
Packit Service 6754ca
	    for (int i = n - 1; i >= 0; --i)
Packit Service 6754ca
		readYCAScanLine (yMax - i, _buf1[N + 1 - i]);
Packit Service 6754ca
	}
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	    int n = min (dy, 3);
Packit Service 6754ca
Packit Service 6754ca
	    for (int i = 2; i > 2 - n; --i)
Packit Service 6754ca
	    {
Packit Service 6754ca
		if ((scanLine + i) & 1)
Packit Service 6754ca
		{
Packit Service 6754ca
		    YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
Packit Service 6754ca
		}
Packit Service 6754ca
		else
Packit Service 6754ca
		{
Packit Service 6754ca
		    reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
Packit Service 6754ca
		    YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
Packit Service 6754ca
		}
Packit Service 6754ca
	    }
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    fixSaturation (_yw, _width, _buf2, _tmpBuf);
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < _width; ++i)
Packit Service 6754ca
	_fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i];
Packit Service 6754ca
Packit Service 6754ca
    _currentScanLine = scanLine;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::FromYca::rotateBuf1 (int d)
Packit Service 6754ca
{
Packit Service 6754ca
    d = modp (d, N + 2);
Packit Service 6754ca
Packit Service 6754ca
    Rgba *tmp[N + 2];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < N + 2; ++i)
Packit Service 6754ca
	tmp[i] = _buf1[i];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < N + 2; ++i)
Packit Service 6754ca
	_buf1[i] = tmp[(i + d) % (N + 2)];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::FromYca::rotateBuf2 (int d)
Packit Service 6754ca
{
Packit Service 6754ca
    d = modp (d, 3);
Packit Service 6754ca
Packit Service 6754ca
    Rgba *tmp[3];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < 3; ++i)
Packit Service 6754ca
	tmp[i] = _buf2[i];
Packit Service 6754ca
Packit Service 6754ca
    for (int i = 0; i < 3; ++i)
Packit Service 6754ca
	_buf2[i] = tmp[(i + d) % 3];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Clamp y.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (y < _yMin)
Packit Service 6754ca
	y = _yMin;
Packit Service 6754ca
    else if (y > _yMax)
Packit Service 6754ca
	y = _yMax - 1;
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Read scan line y into _tmpBuf.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    _inputFile.readPixels (y);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Reconstruct missing chroma samples and copy
Packit Service 6754ca
    // the scan line into buf.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (!_readC)
Packit Service 6754ca
    {
Packit Service 6754ca
	for (int i = 0; i < _width; ++i)
Packit Service 6754ca
	{
Packit Service 6754ca
	    _tmpBuf[i + N2].r = 0;
Packit Service 6754ca
	    _tmpBuf[i + N2].b = 0;
Packit Service 6754ca
	}
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (y & 1)
Packit Service 6754ca
    {
Packit Service 6754ca
	memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba));
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	padTmpBuf();
Packit Service 6754ca
	reconstructChromaHoriz (_width, _tmpBuf, buf);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::FromYca::padTmpBuf ()
Packit Service 6754ca
{
Packit Service 6754ca
    for (int i = 0; i < N2; ++i)
Packit Service 6754ca
    {
Packit Service 6754ca
	_tmpBuf[i] = _tmpBuf[N2];
Packit Service 6754ca
	_tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::RgbaInputFile (const char name[], int numThreads):
Packit Service 6754ca
    _inputFile (new InputFile (name, numThreads)),
Packit Service 6754ca
    _fromYca (0),
Packit Service 6754ca
    _channelNamePrefix ("")
Packit Service 6754ca
{
Packit Service 6754ca
    RgbaChannels rgbaChannels = channels();
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_fromYca = new FromYca (*_inputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads):
Packit Service 6754ca
    _inputFile (new InputFile (is, numThreads)),
Packit Service 6754ca
    _fromYca (0),
Packit Service 6754ca
    _channelNamePrefix ("")
Packit Service 6754ca
{
Packit Service 6754ca
    RgbaChannels rgbaChannels = channels();
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_fromYca = new FromYca (*_inputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::RgbaInputFile (const char name[],
Packit Service 6754ca
			      const string &layerName,
Packit Service 6754ca
			      int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _inputFile (new InputFile (name, numThreads)),
Packit Service 6754ca
    _fromYca (0),
Packit Service 6754ca
    _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
Packit Service 6754ca
{
Packit Service 6754ca
    RgbaChannels rgbaChannels = channels();
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_fromYca = new FromYca (*_inputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
Packit Service 6754ca
			      const string &layerName,
Packit Service 6754ca
			      int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _inputFile (new InputFile (is, numThreads)),
Packit Service 6754ca
    _fromYca (0),
Packit Service 6754ca
    _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
Packit Service 6754ca
{
Packit Service 6754ca
    RgbaChannels rgbaChannels = channels();
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_fromYca = new FromYca (*_inputFile, rgbaChannels);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaInputFile::~RgbaInputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    delete _inputFile;
Packit Service 6754ca
    delete _fromYca;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fromYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_fromYca);
Packit Service 6754ca
	_fromYca->setFrameBuffer (base, xStride, yStride, _channelNamePrefix);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	size_t xs = xStride * sizeof (Rgba);
Packit Service 6754ca
	size_t ys = yStride * sizeof (Rgba);
Packit Service 6754ca
Packit Service 6754ca
	FrameBuffer fb;
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (_channelNamePrefix + "R",
Packit Service 6754ca
		   Slice (HALF,
Packit Service 6754ca
			  (char *) &base[0].r,
Packit Service 6754ca
			  xs, ys,
Packit Service 6754ca
			  1, 1,		// xSampling, ySampling
Packit Service 6754ca
			  0.0));	// fillValue
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (_channelNamePrefix + "G",
Packit Service 6754ca
		   Slice (HALF,
Packit Service 6754ca
			  (char *) &base[0].g,
Packit Service 6754ca
			  xs, ys,
Packit Service 6754ca
			  1, 1,		// xSampling, ySampling
Packit Service 6754ca
			  0.0));	// fillValue
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (_channelNamePrefix + "B",
Packit Service 6754ca
		   Slice (HALF,
Packit Service 6754ca
			  (char *) &base[0].b,
Packit Service 6754ca
			  xs, ys,
Packit Service 6754ca
			  1, 1,		// xSampling, ySampling
Packit Service 6754ca
			  0.0));	// fillValue
Packit Service 6754ca
Packit Service 6754ca
	fb.insert (_channelNamePrefix + "A",
Packit Service 6754ca
		   Slice (HALF,
Packit Service 6754ca
			  (char *) &base[0].a,
Packit Service 6754ca
			  xs, ys,
Packit Service 6754ca
			  1, 1,		// xSampling, ySampling
Packit Service 6754ca
			  1.0));	// fillValue
Packit Service 6754ca
Packit Service 6754ca
	_inputFile->setFrameBuffer (fb);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
RgbaInputFile::setLayerName (const string &layerName)
Packit Service 6754ca
{
Packit Service 6754ca
    delete _fromYca;
Packit Service 6754ca
    _fromYca = 0;
Packit Service 6754ca
Packit Service 6754ca
    _channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header());
Packit Service 6754ca
Packit Service 6754ca
    RgbaChannels rgbaChannels = channels();
Packit Service 6754ca
Packit Service 6754ca
    if (rgbaChannels & (WRITE_Y | WRITE_C))
Packit Service 6754ca
	_fromYca = new FromYca (*_inputFile, rgbaChannels);
Packit Service 6754ca
Packit Service 6754ca
    FrameBuffer fb;
Packit Service 6754ca
    _inputFile->setFrameBuffer (fb);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaInputFile::readPixels (int scanLine1, int scanLine2)
Packit Service 6754ca
{
Packit Service 6754ca
    if (_fromYca)
Packit Service 6754ca
    {
Packit Service 6754ca
	Lock lock (*_fromYca);
Packit Service 6754ca
	_fromYca->readPixels (scanLine1, scanLine2);
Packit Service 6754ca
    }
Packit Service 6754ca
    else
Packit Service 6754ca
    {
Packit Service 6754ca
	_inputFile->readPixels (scanLine1, scanLine2);
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void	
Packit Service 6754ca
RgbaInputFile::readPixels (int scanLine)
Packit Service 6754ca
{
Packit Service 6754ca
    readPixels (scanLine, scanLine);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool
Packit Service 6754ca
RgbaInputFile::isComplete () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->isComplete();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
RgbaInputFile::header () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const char *
Packit Service 6754ca
RgbaInputFile::fileName () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->fileName();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const FrameBuffer &	
Packit Service 6754ca
RgbaInputFile::frameBuffer () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->frameBuffer();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::Box2i &
Packit Service 6754ca
RgbaInputFile::displayWindow () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().displayWindow();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::Box2i &
Packit Service 6754ca
RgbaInputFile::dataWindow () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().dataWindow();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
float	
Packit Service 6754ca
RgbaInputFile::pixelAspectRatio () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().pixelAspectRatio();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const IMATH_NAMESPACE::V2f	
Packit Service 6754ca
RgbaInputFile::screenWindowCenter () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().screenWindowCenter();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
float	
Packit Service 6754ca
RgbaInputFile::screenWindowWidth () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().screenWindowWidth();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
LineOrder
Packit Service 6754ca
RgbaInputFile::lineOrder () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().lineOrder();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Compression
Packit Service 6754ca
RgbaInputFile::compression () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->header().compression();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
RgbaChannels	
Packit Service 6754ca
RgbaInputFile::channels () const
Packit Service 6754ca
{
Packit Service 6754ca
    return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
RgbaInputFile::version () const
Packit Service 6754ca
{
Packit Service 6754ca
    return _inputFile->version();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT