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 #include "ImfNamespace.h" 120 121 OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER 122 123 namespace RgbaYca { 124 125 126 // 127 // Width of the chroma subsampling and reconstruction filters 128 // 129 130 static const int N = 27; 131 static const int N2 = N / 2; 132 133 134 // 135 // Convert a set of primary chromaticities into a set of weighting 136 // factors for computing a pixels's luminance, Y, from R, G and B 137 // 138 139 IMF_EXPORT 140 IMATH_NAMESPACE::V3f computeYw (const Chromaticities &cr); 141 142 143 // 144 // Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha): 145 // 146 // ycaOut[i].g = Y (rgbaIn[i]); 147 // ycaOut[i].r = RY (rgbaIn[i]); 148 // ycaOut[i].b = BY (rgbaIn[i]); 149 // ycaOut[i].a = aIsValid? rgbaIn[i].a: 1 150 // 151 // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 152 // 153 154 IMF_EXPORT 155 void RGBAtoYCA (const IMATH_NAMESPACE::V3f &yw, 156 int n, 157 bool aIsValid, 158 const Rgba rgbaIn[/*n*/], 159 Rgba ycaOut[/*n*/]); 160 161 // 162 // Perform horizontal low-pass filtering and subsampling of 163 // the chroma channels of an array of n pixels. In order 164 // to avoid indexing off the ends of the input array during 165 // low-pass filtering, ycaIn must have N2 extra pixels at 166 // both ends. Before calling decimateChromaHoriz(), the extra 167 // pixels should be filled with copies of the first and last 168 // "real" input pixel. 169 // 170 171 IMF_EXPORT 172 void decimateChromaHoriz (int n, 173 const Rgba ycaIn[/*n+N-1*/], 174 Rgba ycaOut[/*n*/]); 175 176 // 177 // Perform vertical chroma channel low-pass filtering and subsampling. 178 // N scan lines of input pixels are combined into a single scan line 179 // of output pixels. 180 // 181 182 IMF_EXPORT 183 void decimateChromaVert (int n, 184 const Rgba * const ycaIn[N], 185 Rgba ycaOut[/*n*/]); 186 187 // 188 // Round the luminance and chroma channels of an array of YCA 189 // pixels that has already been filtered and subsampled. 190 // The signifcands of the pixels' luminance and chroma values 191 // are rounded to roundY and roundC bits respectively. 192 // 193 194 IMF_EXPORT 195 void roundYCA (int n, 196 unsigned int roundY, 197 unsigned int roundC, 198 const Rgba ycaIn[/*n*/], 199 Rgba ycaOut[/*n*/]); 200 201 // 202 // For a scan line that has valid chroma data only for every other pixel, 203 // reconstruct the missing chroma values. 204 // 205 206 IMF_EXPORT 207 void reconstructChromaHoriz (int n, 208 const Rgba ycaIn[/*n+N-1*/], 209 Rgba ycaOut[/*n*/]); 210 211 // 212 // For a scan line that has only luminance and no valid chroma data, 213 // reconstruct chroma from the surronding N scan lines. 214 // 215 216 IMF_EXPORT 217 void reconstructChromaVert (int n, 218 const Rgba * const ycaIn[N], 219 Rgba ycaOut[/*n*/]); 220 221 // 222 // Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA. 223 // This function is the inverse of RGBAtoYCA(). 224 // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 225 // 226 227 IMF_EXPORT 228 void YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw, 229 int n, 230 const Rgba ycaIn[/*n*/], 231 Rgba rgbaOut[/*n*/]); 232 233 // 234 // Eliminate super-saturated pixels: 235 // 236 // Converting an image from RGBA to YCA, low-pass filtering chroma, 237 // and converting the result back to RGBA can produce pixels with 238 // super-saturated colors, where one or two of the RGB components 239 // become zero or negative. (The low-pass and reconstruction filters 240 // introduce some amount of ringing into the chroma components. 241 // This can lead to negative RGB values near high-contrast edges.) 242 // 243 // The fixSaturation() function finds super-saturated pixels and 244 // corrects them by desaturating their colors while maintaining 245 // their luminance. fixSaturation() takes three adjacent input 246 // scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the 247 // saturation of rgbaIn[1], and stores the result in rgbaOut. 248 // 249 250 IMF_EXPORT 251 void fixSaturation (const IMATH_NAMESPACE::V3f &yw, 252 int n, 253 const Rgba * const rgbaIn[3], 254 Rgba rgbaOut[/*n*/]); 255 256 } // namespace RgbaYca 257 OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT 258 259 #endif 260