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 249