1 #ifndef INCLUDED_IMF_RGBA_YCA_H
2 #define INCLUDED_IMF_RGBA_YCA_H
4 //////////////////////////////////////////////////////////////////////////////
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.
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
14 // * Redistributions of source code must retain the above
15 // copyright notice, this list of conditions and the following
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
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.
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.
40 //////////////////////////////////////////////////////////////////////////////
42 //-----------------------------------------------------------------------------
44 // Conversion between RGBA (red, green, blue alpha)
45 // and YCA (luminance, subsampled chroma, alpha) data:
47 // Luminance, Y, is computed as a weighted sum of R, G, and B:
49 // Y = yw.x * R + yw.y * G + yw.z * B
51 // Function computeYw() computes a set of RGB-to-Y weights, yw,
52 // from a set of primary and white point chromaticities.
54 // Chroma, C, consists of two components, RY and BY:
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.
63 // Starting with an image that has RGBA data for all pixels,
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
70 // RGBA RGBA RGBA RGBA ... RGBA RGBA
71 // RGBA RGBA RGBA RGBA ... RGBA RGBA
73 // function RGBAtoYCA() converts the pixels to YCA format:
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
80 // YCA YCA YCA YCA ... YCA YCA
81 // YCA YCA YCA YCA ... YCA YCA
83 // Next, decimateChomaHoriz() eliminates the chroma values from
84 // the odd-numbered pixels in every scan line:
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
91 // YCA YA YCA YA ... YCA YA
92 // YCA YA YCA YA ... YCA YA
94 // decimateChromaVert() eliminates all chroma values from the
95 // odd-numbered scan lines:
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
102 // YCA YA YCA YA ... YCA YA
103 // YA YA YA YA ... YA YA
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.
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
115 //-----------------------------------------------------------------------------
118 #include <ImfChromaticities.h>
125 // Width of the chroma subsampling and reconstruction filters
128 static const int N = 27;
129 static const int N2 = N / 2;
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
137 Imath::V3f computeYw (const Chromaticities &cr);
141 // Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha):
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
148 // yw is a set of RGB-to-Y weighting factors, as computed by computeYw().
151 void RGBAtoYCA (const Imath::V3f &yw,
154 const Rgba rgbaIn[/*n*/],
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.
167 void decimateChromaHoriz (int n,
168 const Rgba ycaIn[/*n+N-1*/],
172 // Perform vertical chroma channel low-pass filtering and subsampling.
173 // N scan lines of input pixels are combined into a single scan line
177 void decimateChromaVert (int n,
178 const Rgba * const ycaIn[N],
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.
188 void roundYCA (int n,
191 const Rgba ycaIn[/*n*/],
195 // For a scan line that has valid chroma data only for every other pixel,
196 // reconstruct the missing chroma values.
199 void reconstructChromaHoriz (int n,
200 const Rgba ycaIn[/*n+N-1*/],
204 // For a scan line that has only luminance and no valid chroma data,
205 // reconstruct chroma from the surronding N scan lines.
208 void reconstructChromaVert (int n,
209 const Rgba * const ycaIn[N],
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().
218 void YCAtoRGBA (const Imath::V3f &yw,
220 const Rgba ycaIn[/*n*/],
221 Rgba rgbaOut[/*n*/]);
224 // Eliminate super-saturated pixels:
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.)
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.
240 void fixSaturation (const Imath::V3f &yw,
242 const Rgba * const rgbaIn[3],
243 Rgba rgbaOut[/*n*/]);
245 } // namespace RgbaYca