Blame IlmImf/ImfRgbaYca.cpp

Packit 0d464f
//////////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
Packit 0d464f
// Entertainment Company Ltd.  Portions contributed and copyright held by
Packit 0d464f
// others as indicated.  All rights reserved.
Packit 0d464f
//
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
//
Packit 0d464f
//     * Redistributions of source code must retain the above
Packit 0d464f
//       copyright notice, this list of conditions and the following
Packit 0d464f
//       disclaimer.
Packit 0d464f
//
Packit 0d464f
//     * Redistributions in binary form must reproduce the above
Packit 0d464f
//       copyright notice, this list of conditions and the following
Packit 0d464f
//       disclaimer in the documentation and/or other materials provided with
Packit 0d464f
//       the distribution.
Packit 0d464f
//
Packit 0d464f
//     * Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
//       any other contributors to this software may be used to endorse or
Packit 0d464f
//       promote products derived from this software without specific prior
Packit 0d464f
//       written permission.
Packit 0d464f
//
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
Packit 0d464f
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
Packit 0d464f
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Packit 0d464f
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
Packit 0d464f
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit 0d464f
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit 0d464f
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 0d464f
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 0d464f
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 0d464f
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 0d464f
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
//////////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
//
Packit 0d464f
//	Conversion between RGBA and YCA data.
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <ImfRgbaYca.h>
Packit 0d464f
#include <assert.h>
Packit 0d464f
#include <algorithm>
Packit 0d464f
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
using namespace std;
Packit 0d464f
#include "ImfNamespace.h"
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 0d464f
Packit 0d464f
namespace RgbaYca {
Packit 0d464f
Packit 0d464f
Packit 0d464f
V3f
Packit 0d464f
computeYw (const Chromaticities &cr)
Packit 0d464f
{
Packit 0d464f
    M44f m = RGBtoXYZ (cr, 1);
Packit 0d464f
    return V3f (m[0][1], m[1][1], m[2][1]) / (m[0][1] + m[1][1] + m[2][1]);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
RGBAtoYCA (const V3f &yw,
Packit 0d464f
	   int n,
Packit 0d464f
	   bool aIsValid,
Packit 0d464f
	   const Rgba rgbaIn[/*n*/],
Packit 0d464f
	   Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	Rgba in = rgbaIn[i];
Packit 0d464f
	Rgba &out = ycaOut[i];
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Conversion to YCA and subsequent chroma subsampling
Packit 0d464f
	// work only if R, G and B are finite and non-negative.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	if (!in.r.isFinite() || in.r < 0)
Packit 0d464f
	    in.r = 0;
Packit 0d464f
Packit 0d464f
	if (!in.g.isFinite() || in.g < 0)
Packit 0d464f
	    in.g = 0;
Packit 0d464f
Packit 0d464f
	if (!in.b.isFinite() || in.b < 0)
Packit 0d464f
	    in.b = 0;
Packit 0d464f
Packit 0d464f
	if (in.r == in.g && in.g == in.b)
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // Special case -- R, G and B are equal. To avoid rounding
Packit 0d464f
	    // errors, we explicitly set the output luminance channel
Packit 0d464f
	    // to G, and the chroma channels to 0.
Packit 0d464f
	    //
Packit 0d464f
	    // The special cases here and in YCAtoRGBA() ensure that
Packit 0d464f
	    // converting black-and white images from RGBA to YCA and
Packit 0d464f
	    // back is lossless.
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    out.r = 0;
Packit 0d464f
	    out.g = in.g;
Packit 0d464f
	    out.b = 0;
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    out.g = in.r * yw.x + in.g * yw.y + in.b * yw.z;
Packit 0d464f
Packit 0d464f
	    float Y = out.g;
Packit 0d464f
Packit 0d464f
	    if (abs (in.r - Y) < HALF_MAX * Y)
Packit 0d464f
		out.r = (in.r - Y) / Y;
Packit 0d464f
	    else
Packit 0d464f
		out.r = 0;
Packit 0d464f
Packit 0d464f
	    if (abs (in.b - Y) < HALF_MAX * Y)
Packit 0d464f
		out.b = (in.b - Y) / Y;
Packit 0d464f
	    else
Packit 0d464f
		out.b = 0;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	if (aIsValid)
Packit 0d464f
	    out.a = in.a;
Packit 0d464f
	else
Packit 0d464f
	    out.a = 1;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
decimateChromaHoriz (int n,
Packit 0d464f
		     const Rgba ycaIn[/*n+N-1*/],
Packit 0d464f
		     Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    #ifdef DEBUG
Packit 0d464f
	assert (ycaIn != ycaOut);
Packit 0d464f
    #endif
Packit 0d464f
Packit 0d464f
    int begin = N2;
Packit 0d464f
    int end = begin + n;
Packit 0d464f
Packit 0d464f
    for (int i = begin, j = 0; i < end; ++i, ++j)
Packit 0d464f
    {
Packit 0d464f
	if ((j & 1) == 0)
Packit 0d464f
	{
Packit 0d464f
	    ycaOut[j].r = ycaIn[i - 13].r *  0.001064f +
Packit 0d464f
			  ycaIn[i - 11].r * -0.003771f +
Packit 0d464f
			  ycaIn[i -  9].r *  0.009801f +
Packit 0d464f
			  ycaIn[i -  7].r * -0.021586f +
Packit 0d464f
			  ycaIn[i -  5].r *  0.043978f +
Packit 0d464f
			  ycaIn[i -  3].r * -0.093067f +
Packit 0d464f
			  ycaIn[i -  1].r *  0.313659f +
Packit 0d464f
			  ycaIn[i     ].r *  0.499846f +
Packit 0d464f
			  ycaIn[i +  1].r *  0.313659f +
Packit 0d464f
			  ycaIn[i +  3].r * -0.093067f +
Packit 0d464f
			  ycaIn[i +  5].r *  0.043978f +
Packit 0d464f
			  ycaIn[i +  7].r * -0.021586f +
Packit 0d464f
			  ycaIn[i +  9].r *  0.009801f +
Packit 0d464f
			  ycaIn[i + 11].r * -0.003771f +
Packit 0d464f
			  ycaIn[i + 13].r *  0.001064f;
Packit 0d464f
Packit 0d464f
	    ycaOut[j].b = ycaIn[i - 13].b *  0.001064f +
Packit 0d464f
			  ycaIn[i - 11].b * -0.003771f +
Packit 0d464f
			  ycaIn[i -  9].b *  0.009801f +
Packit 0d464f
			  ycaIn[i -  7].b * -0.021586f +
Packit 0d464f
			  ycaIn[i -  5].b *  0.043978f +
Packit 0d464f
			  ycaIn[i -  3].b * -0.093067f +
Packit 0d464f
			  ycaIn[i -  1].b *  0.313659f +
Packit 0d464f
			  ycaIn[i     ].b *  0.499846f +
Packit 0d464f
			  ycaIn[i +  1].b *  0.313659f +
Packit 0d464f
			  ycaIn[i +  3].b * -0.093067f +
Packit 0d464f
			  ycaIn[i +  5].b *  0.043978f +
Packit 0d464f
			  ycaIn[i +  7].b * -0.021586f +
Packit 0d464f
			  ycaIn[i +  9].b *  0.009801f +
Packit 0d464f
			  ycaIn[i + 11].b * -0.003771f +
Packit 0d464f
			  ycaIn[i + 13].b *  0.001064f;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	ycaOut[j].g = ycaIn[i].g;
Packit 0d464f
	ycaOut[j].a = ycaIn[i].a;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
decimateChromaVert (int n,
Packit 0d464f
		    const Rgba * const ycaIn[N],
Packit 0d464f
		    Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	if ((i & 1) == 0)
Packit 0d464f
	{
Packit 0d464f
	    ycaOut[i].r = ycaIn[ 0][i].r *  0.001064f +
Packit 0d464f
			  ycaIn[ 2][i].r * -0.003771f +
Packit 0d464f
			  ycaIn[ 4][i].r *  0.009801f +
Packit 0d464f
			  ycaIn[ 6][i].r * -0.021586f +
Packit 0d464f
			  ycaIn[ 8][i].r *  0.043978f +
Packit 0d464f
			  ycaIn[10][i].r * -0.093067f +
Packit 0d464f
			  ycaIn[12][i].r *  0.313659f +
Packit 0d464f
			  ycaIn[13][i].r *  0.499846f +
Packit 0d464f
			  ycaIn[14][i].r *  0.313659f +
Packit 0d464f
			  ycaIn[16][i].r * -0.093067f +
Packit 0d464f
			  ycaIn[18][i].r *  0.043978f +
Packit 0d464f
			  ycaIn[20][i].r * -0.021586f +
Packit 0d464f
			  ycaIn[22][i].r *  0.009801f +
Packit 0d464f
			  ycaIn[24][i].r * -0.003771f +
Packit 0d464f
			  ycaIn[26][i].r *  0.001064f;
Packit 0d464f
Packit 0d464f
	    ycaOut[i].b = ycaIn[ 0][i].b *  0.001064f +
Packit 0d464f
			  ycaIn[ 2][i].b * -0.003771f +
Packit 0d464f
			  ycaIn[ 4][i].b *  0.009801f +
Packit 0d464f
			  ycaIn[ 6][i].b * -0.021586f +
Packit 0d464f
			  ycaIn[ 8][i].b *  0.043978f +
Packit 0d464f
			  ycaIn[10][i].b * -0.093067f +
Packit 0d464f
			  ycaIn[12][i].b *  0.313659f +
Packit 0d464f
			  ycaIn[13][i].b *  0.499846f +
Packit 0d464f
			  ycaIn[14][i].b *  0.313659f +
Packit 0d464f
			  ycaIn[16][i].b * -0.093067f +
Packit 0d464f
			  ycaIn[18][i].b *  0.043978f +
Packit 0d464f
			  ycaIn[20][i].b * -0.021586f +
Packit 0d464f
			  ycaIn[22][i].b *  0.009801f +
Packit 0d464f
			  ycaIn[24][i].b * -0.003771f +
Packit 0d464f
			  ycaIn[26][i].b *  0.001064f;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	ycaOut[i].g = ycaIn[13][i].g;
Packit 0d464f
	ycaOut[i].a = ycaIn[13][i].a;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
roundYCA (int n,
Packit 0d464f
	  unsigned int roundY,
Packit 0d464f
	  unsigned int roundC,
Packit 0d464f
	  const Rgba ycaIn[/*n*/],
Packit 0d464f
	  Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	ycaOut[i].g = ycaIn[i].g.round (roundY);
Packit 0d464f
	ycaOut[i].a = ycaIn[i].a;
Packit 0d464f
Packit 0d464f
	if ((i & 1) == 0)
Packit 0d464f
	{
Packit 0d464f
	    ycaOut[i].r = ycaIn[i].r.round (roundC);
Packit 0d464f
	    ycaOut[i].b = ycaIn[i].b.round (roundC);
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
reconstructChromaHoriz (int n,
Packit 0d464f
			const Rgba ycaIn[/*n+N-1*/],
Packit 0d464f
			Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    #ifdef DEBUG
Packit 0d464f
	assert (ycaIn != ycaOut);
Packit 0d464f
    #endif
Packit 0d464f
Packit 0d464f
    int begin = N2;
Packit 0d464f
    int end = begin + n;
Packit 0d464f
Packit 0d464f
    for (int i = begin, j = 0; i < end; ++i, ++j)
Packit 0d464f
    {
Packit 0d464f
	if (j & 1)
Packit 0d464f
	{
Packit 0d464f
	    ycaOut[j].r = ycaIn[i - 13].r *  0.002128f +
Packit 0d464f
			  ycaIn[i - 11].r * -0.007540f +
Packit 0d464f
			  ycaIn[i -  9].r *  0.019597f +
Packit 0d464f
			  ycaIn[i -  7].r * -0.043159f +
Packit 0d464f
			  ycaIn[i -  5].r *  0.087929f +
Packit 0d464f
			  ycaIn[i -  3].r * -0.186077f +
Packit 0d464f
			  ycaIn[i -  1].r *  0.627123f +
Packit 0d464f
			  ycaIn[i +  1].r *  0.627123f +
Packit 0d464f
			  ycaIn[i +  3].r * -0.186077f +
Packit 0d464f
			  ycaIn[i +  5].r *  0.087929f +
Packit 0d464f
			  ycaIn[i +  7].r * -0.043159f +
Packit 0d464f
			  ycaIn[i +  9].r *  0.019597f +
Packit 0d464f
			  ycaIn[i + 11].r * -0.007540f +
Packit 0d464f
			  ycaIn[i + 13].r *  0.002128f;
Packit 0d464f
Packit 0d464f
	    ycaOut[j].b = ycaIn[i - 13].b *  0.002128f +
Packit 0d464f
			  ycaIn[i - 11].b * -0.007540f +
Packit 0d464f
			  ycaIn[i -  9].b *  0.019597f +
Packit 0d464f
			  ycaIn[i -  7].b * -0.043159f +
Packit 0d464f
			  ycaIn[i -  5].b *  0.087929f +
Packit 0d464f
			  ycaIn[i -  3].b * -0.186077f +
Packit 0d464f
			  ycaIn[i -  1].b *  0.627123f +
Packit 0d464f
			  ycaIn[i +  1].b *  0.627123f +
Packit 0d464f
			  ycaIn[i +  3].b * -0.186077f +
Packit 0d464f
			  ycaIn[i +  5].b *  0.087929f +
Packit 0d464f
			  ycaIn[i +  7].b * -0.043159f +
Packit 0d464f
			  ycaIn[i +  9].b *  0.019597f +
Packit 0d464f
			  ycaIn[i + 11].b * -0.007540f +
Packit 0d464f
			  ycaIn[i + 13].b *  0.002128f;
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    ycaOut[j].r = ycaIn[i].r;
Packit 0d464f
	    ycaOut[j].b = ycaIn[i].b;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	ycaOut[j].g = ycaIn[i].g;
Packit 0d464f
	ycaOut[j].a = ycaIn[i].a;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
reconstructChromaVert (int n,
Packit 0d464f
		       const Rgba * const ycaIn[N],
Packit 0d464f
		       Rgba ycaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	ycaOut[i].r = ycaIn[ 0][i].r *  0.002128f +
Packit 0d464f
		      ycaIn[ 2][i].r * -0.007540f +
Packit 0d464f
		      ycaIn[ 4][i].r *  0.019597f +
Packit 0d464f
		      ycaIn[ 6][i].r * -0.043159f +
Packit 0d464f
		      ycaIn[ 8][i].r *  0.087929f +
Packit 0d464f
		      ycaIn[10][i].r * -0.186077f +
Packit 0d464f
		      ycaIn[12][i].r *  0.627123f +
Packit 0d464f
		      ycaIn[14][i].r *  0.627123f +
Packit 0d464f
		      ycaIn[16][i].r * -0.186077f +
Packit 0d464f
		      ycaIn[18][i].r *  0.087929f +
Packit 0d464f
		      ycaIn[20][i].r * -0.043159f +
Packit 0d464f
		      ycaIn[22][i].r *  0.019597f +
Packit 0d464f
		      ycaIn[24][i].r * -0.007540f +
Packit 0d464f
		      ycaIn[26][i].r *  0.002128f;
Packit 0d464f
Packit 0d464f
	ycaOut[i].b = ycaIn[ 0][i].b *  0.002128f +
Packit 0d464f
		      ycaIn[ 2][i].b * -0.007540f +
Packit 0d464f
		      ycaIn[ 4][i].b *  0.019597f +
Packit 0d464f
		      ycaIn[ 6][i].b * -0.043159f +
Packit 0d464f
		      ycaIn[ 8][i].b *  0.087929f +
Packit 0d464f
		      ycaIn[10][i].b * -0.186077f +
Packit 0d464f
		      ycaIn[12][i].b *  0.627123f +
Packit 0d464f
		      ycaIn[14][i].b *  0.627123f +
Packit 0d464f
		      ycaIn[16][i].b * -0.186077f +
Packit 0d464f
		      ycaIn[18][i].b *  0.087929f +
Packit 0d464f
		      ycaIn[20][i].b * -0.043159f +
Packit 0d464f
		      ycaIn[22][i].b *  0.019597f +
Packit 0d464f
		      ycaIn[24][i].b * -0.007540f +
Packit 0d464f
		      ycaIn[26][i].b *  0.002128f;
Packit 0d464f
Packit 0d464f
	ycaOut[i].g = ycaIn[13][i].g;
Packit 0d464f
	ycaOut[i].a = ycaIn[13][i].a;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
			 
Packit 0d464f
void
Packit 0d464f
YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw,
Packit 0d464f
	   int n,
Packit 0d464f
	   const Rgba ycaIn[/*n*/],
Packit 0d464f
	   Rgba rgbaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	const Rgba &in = ycaIn[i];
Packit 0d464f
	Rgba &out = rgbaOut[i];
Packit 0d464f
Packit 0d464f
	if (in.r == 0 && in.b == 0)
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // Special case -- both chroma channels are 0.  To avoid
Packit 0d464f
	    // rounding errors, we explicitly set the output R, G and B
Packit 0d464f
	    // channels equal to the input luminance.
Packit 0d464f
	    //
Packit 0d464f
	    // The special cases here and in RGBAtoYCA() ensure that
Packit 0d464f
	    // converting black-and white images from RGBA to YCA and
Packit 0d464f
	    // back is lossless.
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    out.r = in.g;
Packit 0d464f
	    out.g = in.g;
Packit 0d464f
	    out.b = in.g;
Packit 0d464f
	    out.a = in.a;
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    float Y =  in.g;
Packit 0d464f
	    float r = (in.r + 1) * Y;
Packit 0d464f
	    float b = (in.b + 1) * Y;
Packit 0d464f
	    float g = (Y - r * yw.x - b * yw.z) / yw.y;
Packit 0d464f
Packit 0d464f
	    out.r = r;
Packit 0d464f
	    out.g = g;
Packit 0d464f
	    out.b = b;
Packit 0d464f
	    out.a = in.a;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
inline float
Packit 0d464f
saturation (const Rgba &in)
Packit 0d464f
{
Packit 0d464f
    float rgbMax = max (in.r, max (in.g, in.b));
Packit 0d464f
    float rgbMin = min (in.r, min (in.g, in.b));
Packit 0d464f
Packit 0d464f
    if (rgbMax > 0)
Packit 0d464f
	return 1 - rgbMin / rgbMax;
Packit 0d464f
    else
Packit 0d464f
	return 0;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
desaturate (const Rgba &in, float f, const V3f &yw, Rgba &out)
Packit 0d464f
{
Packit 0d464f
    float rgbMax = max (in.r, max (in.g, in.b));
Packit 0d464f
Packit 0d464f
    out.r = max (float (rgbMax - (rgbMax - in.r) * f), 0.0f);
Packit 0d464f
    out.g = max (float (rgbMax - (rgbMax - in.g) * f), 0.0f);
Packit 0d464f
    out.b = max (float (rgbMax - (rgbMax - in.b) * f), 0.0f);
Packit 0d464f
    out.a = in.a;
Packit 0d464f
Packit 0d464f
    float Yin  = in.r  * yw.x + in.g  * yw.y + in.b  * yw.z;
Packit 0d464f
    float Yout = out.r * yw.x + out.g * yw.y + out.b * yw.z;
Packit 0d464f
Packit 0d464f
    if (Yout > 0)
Packit 0d464f
    {
Packit 0d464f
	out.r *= Yin / Yout;
Packit 0d464f
	out.g *= Yin / Yout;
Packit 0d464f
	out.b *= Yin / Yout;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
			 
Packit 0d464f
void
Packit 0d464f
fixSaturation (const IMATH_NAMESPACE::V3f &yw,
Packit 0d464f
	       int n,
Packit 0d464f
	       const Rgba * const rgbaIn[3],
Packit 0d464f
	       Rgba rgbaOut[/*n*/])
Packit 0d464f
{
Packit 0d464f
    float neighborA2 = saturation (rgbaIn[0][0]);
Packit 0d464f
    float neighborA1 = neighborA2;
Packit 0d464f
Packit 0d464f
    float neighborB2 = saturation (rgbaIn[2][0]);
Packit 0d464f
    float neighborB1 = neighborB2;
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
    {
Packit 0d464f
	float neighborA0 = neighborA1;
Packit 0d464f
	neighborA1 = neighborA2;
Packit 0d464f
Packit 0d464f
	float neighborB0 = neighborB1;
Packit 0d464f
	neighborB1 = neighborB2;
Packit 0d464f
Packit 0d464f
	if (i < n - 1)
Packit 0d464f
	{
Packit 0d464f
	    neighborA2 = saturation (rgbaIn[0][i + 1]);
Packit 0d464f
	    neighborB2 = saturation (rgbaIn[2][i + 1]);
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// A0       A1       A2
Packit 0d464f
	//      rgbaOut[i]
Packit 0d464f
	// B0       B1       B2
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	float sMean = min (1.0f, 0.25f * (neighborA0 + neighborA2 +
Packit 0d464f
					  neighborB0 + neighborB2));
Packit 0d464f
Packit 0d464f
	const Rgba &in  = rgbaIn[1][i];
Packit 0d464f
	Rgba &out = rgbaOut[i];
Packit 0d464f
Packit 0d464f
	float s = saturation (in);
Packit 0d464f
Packit 0d464f
	if (s > sMean)
Packit 0d464f
	{
Packit 0d464f
	    float sMax = min (1.0f, 1 - (1 - sMean) * 0.25f);
Packit 0d464f
Packit 0d464f
	    if (s > sMax)
Packit 0d464f
	    {
Packit 0d464f
		desaturate (in, sMax / s, yw, out);
Packit 0d464f
		continue;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	out = in;
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace RgbaYca
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT