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 | |
---|
120 | namespace Imf { |
---|
121 | namespace RgbaYca { |
---|
122 | |
---|
123 | |
---|
124 | // |
---|
125 | // Width of the chroma subsampling and reconstruction filters |
---|
126 | // |
---|
127 | |
---|
128 | static const int N = 27; |
---|
129 | static 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 | |
---|
137 | Imath::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 | |
---|
151 | void 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 | |
---|
167 | void 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 | |
---|
177 | void 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 | |
---|
188 | void 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 | |
---|
199 | void 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 | |
---|
208 | void 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 | |
---|
218 | void 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 | |
---|
240 | void 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 |
---|