PBRT
|
00001 #ifndef INCLUDED_IMF_RGBA_YCA_H 00002 #define INCLUDED_IMF_RGBA_YCA_H 00003 00005 // 00006 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm 00007 // Entertainment Company Ltd. Portions contributed and copyright held by 00008 // others as indicated. All rights reserved. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // * Redistributions of source code must retain the above 00015 // copyright notice, this list of conditions and the following 00016 // disclaimer. 00017 // 00018 // * Redistributions in binary form must reproduce the above 00019 // copyright notice, this list of conditions and the following 00020 // disclaimer in the documentation and/or other materials provided with 00021 // the distribution. 00022 // 00023 // * Neither the name of Industrial Light & Magic nor the names of 00024 // any other contributors to this software may be used to endorse or 00025 // promote products derived from this software without specific prior 00026 // written permission. 00027 // 00028 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00029 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00030 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00031 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00032 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00033 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00034 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00035 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00036 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00037 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00038 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00039 // 00041 00042 //----------------------------------------------------------------------------- 00043 // 00044 // Conversion between RGBA (red, green, blue alpha) 00045 // and YCA (luminance, subsampled chroma, alpha) data: 00046 // 00047 // Luminance, Y, is computed as a weighted sum of R, G, and B: 00048 // 00049 // Y = yw.x * R + yw.y * G + yw.z * B 00050 // 00051 // Function computeYw() computes a set of RGB-to-Y weights, yw, 00052 // from a set of primary and white point chromaticities. 00053 // 00054 // Chroma, C, consists of two components, RY and BY: 00055 // 00056 // RY = (R - Y) / Y 00057 // BY = (B - Y) / Y 00058 // 00059 // For efficiency, the x and y subsampling rates for chroma are 00060 // hardwired to 2, and the chroma subsampling and reconstruction 00061 // filters are fixed 27-pixel wide windowed sinc functions. 00062 // 00063 // Starting with an image that has RGBA data for all pixels, 00064 // 00065 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00066 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00067 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00068 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00069 // ... 00070 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00071 // RGBA RGBA RGBA RGBA ... RGBA RGBA 00072 // 00073 // function RGBAtoYCA() converts the pixels to YCA format: 00074 // 00075 // YCA YCA YCA YCA ... YCA YCA 00076 // YCA YCA YCA YCA ... YCA YCA 00077 // YCA YCA YCA YCA ... YCA YCA 00078 // YCA YCA YCA YCA ... YCA YCA 00079 // ... 00080 // YCA YCA YCA YCA ... YCA YCA 00081 // YCA YCA YCA YCA ... YCA YCA 00082 // 00083 // Next, decimateChomaHoriz() eliminates the chroma values from 00084 // the odd-numbered pixels in every scan line: 00085 // 00086 // YCA YA YCA YA ... YCA YA 00087 // YCA YA YCA YA ... YCA YA 00088 // YCA YA YCA YA ... YCA YA 00089 // YCA YA YCA YA ... YCA YA 00090 // ... 00091 // YCA YA YCA YA ... YCA YA 00092 // YCA YA YCA YA ... YCA YA 00093 // 00094 // decimateChromaVert() eliminates all chroma values from the 00095 // odd-numbered scan lines: 00096 // 00097 // YCA YA YCA YA ... YCA YA 00098 // YA YA YA YA ... YA YA 00099 // YCA YA YCA YA ... YCA YA 00100 // YA YA YA YA ... YA YA 00101 // ... 00102 // YCA YA YCA YA ... YCA YA 00103 // YA YA YA YA ... YA YA 00104 // 00105 // Finally, roundYCA() reduces the precision of the luminance 00106 // and chroma values so that the pixel data shrink more when 00107 // they are saved in a compressed file. 00108 // 00109 // The output of roundYCA() can be converted back to a set 00110 // of RGBA pixel data that is visually very similar to the 00111 // original RGBA image, by calling reconstructChromaHoriz(), 00112 // reconstructChromaVert(), YCAtoRGBA(), and finally 00113 // fixSaturation(). 00114 // 00115 //----------------------------------------------------------------------------- 00116 00117 #include <ImfRgba.h> 00118 #include <ImfChromaticities.h> 00119 00120 namespace Imf { 00121 namespace RgbaYca { 00122 00123 00124 // 00125 // Width of the chroma subsampling and reconstruction filters 00126 // 00127 00128 static const int N = 27; 00129 static const int N2 = N / 2; 00130 00131 00132 // 00133 // Convert a set of primary chromaticities into a set of weighting 00134 // factors for computing a pixels's luminance, Y, from R, G and B 00135 // 00136 00137 Imath::V3f computeYw (const Chromaticities &cr); 00138 00139 00140 // 00141 // Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha): 00142 // 00143 // ycaOut[i].g = Y (rgbaIn[i]); 00144 // ycaOut[i].r = RY (rgbaIn[i]); 00145 // ycaOut[i].b = BY (rgbaIn[i]); 00146 // ycaOut[i].a = aIsValid? rgbaIn[i].a: 1 00147 // 00148 // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 00149 // 00150 00151 void RGBAtoYCA (const Imath::V3f &yw, 00152 int n, 00153 bool aIsValid, 00154 const Rgba rgbaIn[/*n*/], 00155 Rgba ycaOut[/*n*/]); 00156 00157 // 00158 // Perform horizontal low-pass filtering and subsampling of 00159 // the chroma channels of an array of n pixels. In order 00160 // to avoid indexing off the ends of the input array during 00161 // low-pass filtering, ycaIn must have N2 extra pixels at 00162 // both ends. Before calling decimateChromaHoriz(), the extra 00163 // pixels should be filled with copies of the first and last 00164 // "real" input pixel. 00165 // 00166 00167 void decimateChromaHoriz (int n, 00168 const Rgba ycaIn[/*n+N-1*/], 00169 Rgba ycaOut[/*n*/]); 00170 00171 // 00172 // Perform vertical chroma channel low-pass filtering and subsampling. 00173 // N scan lines of input pixels are combined into a single scan line 00174 // of output pixels. 00175 // 00176 00177 void decimateChromaVert (int n, 00178 const Rgba * const ycaIn[N], 00179 Rgba ycaOut[/*n*/]); 00180 00181 // 00182 // Round the luminance and chroma channels of an array of YCA 00183 // pixels that has already been filtered and subsampled. 00184 // The signifcands of the pixels' luminance and chroma values 00185 // are rounded to roundY and roundC bits respectively. 00186 // 00187 00188 void roundYCA (int n, 00189 unsigned int roundY, 00190 unsigned int roundC, 00191 const Rgba ycaIn[/*n*/], 00192 Rgba ycaOut[/*n*/]); 00193 00194 // 00195 // For a scan line that has valid chroma data only for every other pixel, 00196 // reconstruct the missing chroma values. 00197 // 00198 00199 void reconstructChromaHoriz (int n, 00200 const Rgba ycaIn[/*n+N-1*/], 00201 Rgba ycaOut[/*n*/]); 00202 00203 // 00204 // For a scan line that has only luminance and no valid chroma data, 00205 // reconstruct chroma from the surronding N scan lines. 00206 // 00207 00208 void reconstructChromaVert (int n, 00209 const Rgba * const ycaIn[N], 00210 Rgba ycaOut[/*n*/]); 00211 00212 // 00213 // Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA. 00214 // This function is the inverse of RGBAtoYCA(). 00215 // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). 00216 // 00217 00218 void YCAtoRGBA (const Imath::V3f &yw, 00219 int n, 00220 const Rgba ycaIn[/*n*/], 00221 Rgba rgbaOut[/*n*/]); 00222 00223 // 00224 // Eliminate super-saturated pixels: 00225 // 00226 // Converting an image from RGBA to YCA, low-pass filtering chroma, 00227 // and converting the result back to RGBA can produce pixels with 00228 // super-saturated colors, where one or two of the RGB components 00229 // become zero or negative. (The low-pass and reconstruction filters 00230 // introduce some amount of ringing into the chroma components. 00231 // This can lead to negative RGB values near high-contrast edges.) 00232 // 00233 // The fixSaturation() function finds super-saturated pixels and 00234 // corrects them by desaturating their colors while maintaining 00235 // their luminance. fixSaturation() takes three adjacent input 00236 // scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the 00237 // saturation of rgbaIn[1], and stores the result in rgbaOut. 00238 // 00239 00240 void fixSaturation (const Imath::V3f &yw, 00241 int n, 00242 const Rgba * const rgbaIn[3], 00243 Rgba rgbaOut[/*n*/]); 00244 00245 } // namespace RgbaYca 00246 } // namespace Imf 00247 00248 #endif