[855] | 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 |
---|