1#ifndef INCLUDED_IMF_RGBA_YCA_H 2#define INCLUDED_IMF_RGBA_YCA_H 3 4////////////////////////////////////////////////////////////////////////////// 5// 6// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm 7// Entertainment Company Ltd. Portions contributed and copyright held by 8// others as indicated. All rights reserved. 9// 10// Redistribution and use in source and binary forms, with or without 11// modification, are permitted provided that the following conditions are 12// met: 13// 14// * Redistributions of source code must retain the above 15// copyright notice, this list of conditions and the following 16// disclaimer. 17// 18// * Redistributions in binary form must reproduce the above 19// copyright notice, this list of conditions and the following 20// disclaimer in the documentation and/or other materials provided with 21// the distribution. 22// 23// * Neither the name of Industrial Light & Magic nor the names of 24// any other contributors to this software may be used to endorse or 25// promote products derived from this software without specific prior 26// written permission. 27// 28// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 29// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 30// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 32// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 33// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 34// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 35// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 37// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39// 40////////////////////////////////////////////////////////////////////////////// 41 42//----------------------------------------------------------------------------- 43// 44// Conversion between RGBA (red, green, blue alpha) 45// and YCA (luminance, subsampled chroma, alpha) data: 46// 47// Luminance, Y, is computed as a weighted sum of R, G, and B: 48// 49// Y = yw.x * R + yw.y * G + yw.z * B 50// 51// Function computeYw() computes a set of RGB-to-Y weights, yw, 52// from a set of primary and white point chromaticities. 53// 54// Chroma, C, consists of two components, RY and BY: 55// 56// RY = (R - Y) / Y 57// BY = (B - Y) / Y 58// 59// For efficiency, the x and y subsampling rates for chroma are 60// hardwired to 2, and the chroma subsampling and reconstruction 61// filters are fixed 27-pixel wide windowed sinc functions. 62// 63// Starting with an image that has RGBA data for all pixels, 64// 65// RGBA RGBA RGBA RGBA ... RGBA RGBA 66// RGBA RGBA RGBA RGBA ... RGBA RGBA 67// RGBA RGBA RGBA RGBA ... RGBA RGBA 68// RGBA RGBA RGBA RGBA ... RGBA RGBA 69// ... 70// RGBA RGBA RGBA RGBA ... RGBA RGBA 71// RGBA RGBA RGBA RGBA ... RGBA RGBA 72// 73// function RGBAtoYCA() converts the pixels to YCA format: 74// 75// YCA YCA YCA YCA ... YCA YCA 76// YCA YCA YCA YCA ... YCA YCA 77// YCA YCA YCA YCA ... YCA YCA 78// YCA YCA YCA YCA ... YCA YCA 79// ... 80// YCA YCA YCA YCA ... YCA YCA 81// YCA YCA YCA YCA ... YCA YCA 82// 83// Next, decimateChomaHoriz() eliminates the chroma values from 84// the odd-numbered pixels in every scan line: 85// 86// YCA YA YCA YA ... YCA YA 87// YCA YA YCA YA ... YCA YA 88// YCA YA YCA YA ... YCA YA 89// YCA YA YCA YA ... YCA YA 90// ... 91// YCA YA YCA YA ... YCA YA 92// YCA YA YCA YA ... YCA YA 93// 94// decimateChromaVert() eliminates all chroma values from the 95// odd-numbered scan lines: 96// 97// YCA YA YCA YA ... YCA YA 98// YA YA YA YA ... YA YA 99// YCA YA YCA YA ... YCA YA 100// YA YA YA YA ... YA YA 101// ... 102// YCA YA YCA YA ... YCA YA 103// YA YA YA YA ... YA YA 104// 105// Finally, roundYCA() reduces the precision of the luminance 106// and chroma values so that the pixel data shrink more when 107// they are saved in a compressed file. 108// 109// The output of roundYCA() can be converted back to a set 110// of RGBA pixel data that is visually very similar to the 111// original RGBA image, by calling reconstructChromaHoriz(), 112// reconstructChromaVert(), YCAtoRGBA(), and finally 113// fixSaturation(). 114// 115//----------------------------------------------------------------------------- 116 117#include <ImfRgba.h> 118#include <ImfChromaticities.h> 119 120namespace Imf { 121namespace RgbaYca { 122 123 124// 125// Width of the chroma subsampling and reconstruction filters 126// 127 128static const int N = 27; 129static const int N2 = N / 2; 130 131 132// 133// Convert a set of primary chromaticities into a set of weighting 134// factors for computing a pixels's luminance, Y, from R, G and B 135// 136 137Imath::V3f computeYw (const Chromaticities &cr); 138 139 140// 141// Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha): 142// 143// ycaOut[i].g = Y (rgbaIn[i]); 144// ycaOut[i].r = RY (rgbaIn[i]); 145// ycaOut[i].b = BY (rgbaIn[i]); 146// ycaOut[i].a = aIsValid? rgbaIn[i].a: 1 147// 148// yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 149// 150 151void RGBAtoYCA (const Imath::V3f &yw, 152 int n, 153 bool aIsValid, 154 const Rgba rgbaIn[/*n*/], 155 Rgba ycaOut[/*n*/]); 156 157// 158// Perform horizontal low-pass filtering and subsampling of 159// the chroma channels of an array of n pixels. In order 160// to avoid indexing off the ends of the input array during 161// low-pass filtering, ycaIn must have N2 extra pixels at 162// both ends. Before calling decimateChromaHoriz(), the extra 163// pixels should be filled with copies of the first and last 164// "real" input pixel. 165// 166 167void decimateChromaHoriz (int n, 168 const Rgba ycaIn[/*n+N-1*/], 169 Rgba ycaOut[/*n*/]); 170 171// 172// Perform vertical chroma channel low-pass filtering and subsampling. 173// N scan lines of input pixels are combined into a single scan line 174// of output pixels. 175// 176 177void decimateChromaVert (int n, 178 const Rgba * const ycaIn[N], 179 Rgba ycaOut[/*n*/]); 180 181// 182// Round the luminance and chroma channels of an array of YCA 183// pixels that has already been filtered and subsampled. 184// The signifcands of the pixels' luminance and chroma values 185// are rounded to roundY and roundC bits respectively. 186// 187 188void roundYCA (int n, 189 unsigned int roundY, 190 unsigned int roundC, 191 const Rgba ycaIn[/*n*/], 192 Rgba ycaOut[/*n*/]); 193 194// 195// For a scan line that has valid chroma data only for every other pixel, 196// reconstruct the missing chroma values. 197// 198 199void reconstructChromaHoriz (int n, 200 const Rgba ycaIn[/*n+N-1*/], 201 Rgba ycaOut[/*n*/]); 202 203// 204// For a scan line that has only luminance and no valid chroma data, 205// reconstruct chroma from the surronding N scan lines. 206// 207 208void reconstructChromaVert (int n, 209 const Rgba * const ycaIn[N], 210 Rgba ycaOut[/*n*/]); 211 212// 213// Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA. 214// This function is the inverse of RGBAtoYCA(). 215// yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 216// 217 218void YCAtoRGBA (const Imath::V3f &yw, 219 int n, 220 const Rgba ycaIn[/*n*/], 221 Rgba rgbaOut[/*n*/]); 222 223// 224// Eliminate super-saturated pixels: 225// 226// Converting an image from RGBA to YCA, low-pass filtering chroma, 227// and converting the result back to RGBA can produce pixels with 228// super-saturated colors, where one or two of the RGB components 229// become zero or negative. (The low-pass and reconstruction filters 230// introduce some amount of ringing into the chroma components. 231// This can lead to negative RGB values near high-contrast edges.) 232// 233// The fixSaturation() function finds super-saturated pixels and 234// corrects them by desaturating their colors while maintaining 235// their luminance. fixSaturation() takes three adjacent input 236// scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the 237// saturation of rgbaIn[1], and stores the result in rgbaOut. 238// 239 240void fixSaturation (const Imath::V3f &yw, 241 int n, 242 const Rgba * const rgbaIn[3], 243 Rgba rgbaOut[/*n*/]); 244 245} // namespace RgbaYca 246} // namespace Imf 247 248#endif 249