ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

yuva_to_rgba.cpp

Go to the documentation of this file.
00001 /* Residual - A 3D game interpreter
00002  *
00003  * Residual is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // The YUV to RGB conversion code is derived from SDL's YUV overlay code, which
00024 // in turn appears to be derived from mpeg_play. The following copyright
00025 // notices have been included in accordance with the original license. Please
00026 // note that the term "software" in this context only applies to the
00027 // buildLookup() and plotYUV*() functions below.
00028 
00029 // Copyright (c) 1995 The Regents of the University of California.
00030 // All rights reserved.
00031 //
00032 // Permission to use, copy, modify, and distribute this software and its
00033 // documentation for any purpose, without fee, and without written agreement is
00034 // hereby granted, provided that the above copyright notice and the following
00035 // two paragraphs appear in all copies of this software.
00036 //
00037 // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00038 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00039 // OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00040 // CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00041 //
00042 // THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00043 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00044 // AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00045 // ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00046 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00047 
00048 // Copyright (c) 1995 Erik Corry
00049 // All rights reserved.
00050 //
00051 // Permission to use, copy, modify, and distribute this software and its
00052 // documentation for any purpose, without fee, and without written agreement is
00053 // hereby granted, provided that the above copyright notice and the following
00054 // two paragraphs appear in all copies of this software.
00055 //
00056 // IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
00057 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
00058 // THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
00059 // OF THE POSSIBILITY OF SUCH DAMAGE.
00060 //
00061 // ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
00062 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00063 // PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
00064 // BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
00065 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00066 
00067 // Portions of this software Copyright (c) 1995 Brown University.
00068 // All rights reserved.
00069 //
00070 // Permission to use, copy, modify, and distribute this software and its
00071 // documentation for any purpose, without fee, and without written agreement
00072 // is hereby granted, provided that the above copyright notice and the
00073 // following two paragraphs appear in all copies of this software.
00074 //
00075 // IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
00076 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00077 // OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
00078 // UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00079 //
00080 // BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
00081 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00082 // PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
00083 // BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
00084 // SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00085 
00086 #include "graphics/surface.h"
00087 #include "graphics/yuva_to_rgba.h"
00088 
00089 namespace Common {
00090 DECLARE_SINGLETON(Graphics::YUVAToRGBAManager);
00091 }
00092 
00093 namespace Graphics {
00094 
00095 class YUVAToRGBALookup {
00096 public:
00097     YUVAToRGBALookup(Graphics::PixelFormat format, YUVAToRGBAManager::LuminanceScale scale);
00098 
00099     Graphics::PixelFormat getFormat() const { return _format; }
00100     YUVAToRGBAManager::LuminanceScale getScale() const { return _scale; }
00101     const uint32 *getRGBToPix() const { return _rgbToPix; }
00102     const uint32 *getAlphaToPix() const { return _alphaToPix; }
00103 
00104 private:
00105     Graphics::PixelFormat _format;
00106     YUVAToRGBAManager::LuminanceScale _scale;
00107     uint32 _rgbToPix[3 * 768]; // 9216 bytes
00108     uint32 _alphaToPix[256];   // 958 bytes
00109 };
00110 
00111 YUVAToRGBALookup::YUVAToRGBALookup(Graphics::PixelFormat format, YUVAToRGBAManager::LuminanceScale scale) {
00112     _format = format;
00113     _scale = scale;
00114 
00115     uint32 *r_2_pix_alloc = &_rgbToPix[0 * 768];
00116     uint32 *g_2_pix_alloc = &_rgbToPix[1 * 768];
00117     uint32 *b_2_pix_alloc = &_rgbToPix[2 * 768];
00118 
00119     if (scale == YUVAToRGBAManager::kScaleFull) {
00120         // Set up entries 0-255 in rgb-to-pixel value tables.
00121         for (int i = 0; i < 256; i++) {
00122             r_2_pix_alloc[i + 256] = format.ARGBToColor(0, i, 0, 0);
00123             g_2_pix_alloc[i + 256] = format.ARGBToColor(0, 0, i, 0);
00124             b_2_pix_alloc[i + 256] = format.ARGBToColor(0, 0, 0, i);
00125         }
00126 
00127         // Spread out the values we have to the rest of the array so that we do
00128         // not need to check for overflow.
00129         for (int i = 0; i < 256; i++) {
00130             r_2_pix_alloc[i] = r_2_pix_alloc[256];
00131             r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
00132             g_2_pix_alloc[i] = g_2_pix_alloc[256];
00133             g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
00134             b_2_pix_alloc[i] = b_2_pix_alloc[256];
00135             b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
00136         }
00137     } else {
00138         // Set up entries 16-235 in rgb-to-pixel value tables
00139         for (int i = 16; i < 236; i++) {
00140             int scaledValue = (i - 16) * 255 / 219;
00141             r_2_pix_alloc[i + 256] = format.ARGBToColor(0, scaledValue, 0, 0);
00142             g_2_pix_alloc[i + 256] = format.ARGBToColor(0, 0, scaledValue, 0);
00143             b_2_pix_alloc[i + 256] = format.ARGBToColor(0, 0, 0, scaledValue);
00144         }
00145 
00146         // Spread out the values we have to the rest of the array so that we do
00147         // not need to check for overflow. We have to do it here in two steps.
00148         for (int i = 0; i < 256 + 16; i++) {
00149             r_2_pix_alloc[i] = r_2_pix_alloc[256 + 16];
00150             g_2_pix_alloc[i] = g_2_pix_alloc[256 + 16];
00151             b_2_pix_alloc[i] = b_2_pix_alloc[256 + 16];
00152         }
00153 
00154         for (int i = 256 + 236; i < 768; i++) {
00155             r_2_pix_alloc[i] = r_2_pix_alloc[256 + 236 - 1];
00156             g_2_pix_alloc[i] = g_2_pix_alloc[256 + 236 - 1];
00157             b_2_pix_alloc[i] = b_2_pix_alloc[256 + 236 - 1];
00158         }
00159     }
00160 
00161     // Set up entries 0-255 in alpha-to-pixel value table.
00162     for (int i = 0; i < 256; i++) {
00163         _alphaToPix[i] = format.ARGBToColor(i, 0, 0, 0);
00164     }
00165 }
00166 
00167 YUVAToRGBAManager::YUVAToRGBAManager() {
00168     _lookup = 0;
00169 
00170     int16 *Cr_r_tab = &_colorTab[0 * 256];
00171     int16 *Cr_g_tab = &_colorTab[1 * 256];
00172     int16 *Cb_g_tab = &_colorTab[2 * 256];
00173     int16 *Cb_b_tab = &_colorTab[3 * 256];
00174 
00175     // Generate the tables for the display surface
00176 
00177     for (int i = 0; i < 256; i++) {
00178         // Gamma correction (luminescence table) and chroma correction
00179         // would be done here. See the Berkeley mpeg_play sources.
00180 
00181         int16 CR = (i - 128), CB = CR;
00182         Cr_r_tab[i] = (int16) ( (0.419 / 0.299) * CR) + 0 * 768 + 256;
00183         Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR) + 1 * 768 + 256;
00184         Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB);
00185         Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB) + 2 * 768 + 256;
00186     }
00187 }
00188 
00189 YUVAToRGBAManager::~YUVAToRGBAManager() {
00190     delete _lookup;
00191 }
00192 
00193 const YUVAToRGBALookup *YUVAToRGBAManager::getLookup(Graphics::PixelFormat format, YUVAToRGBAManager::LuminanceScale scale) {
00194     if (_lookup && _lookup->getFormat() == format && _lookup->getScale() == scale)
00195         return _lookup;
00196 
00197     delete _lookup;
00198     _lookup = new YUVAToRGBALookup(format, scale);
00199     return _lookup;
00200 }
00201 
00202 #define PUT_PIXELA(s, a, d) \
00203     L = &rgbToPix[(s)]; \
00204     *((PixelInt *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b] | aToPix[a])
00205 
00206 template<typename PixelInt>
00207 void convertYUVA420ToRGBA(byte *dstPtr, int dstPitch, const YUVAToRGBALookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, const byte *aSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
00208     int halfHeight = yHeight >> 1;
00209     int halfWidth = yWidth >> 1;
00210 
00211     // Keep the tables in pointers here to avoid a dereference on each pixel
00212     const int16 *Cr_r_tab = colorTab;
00213     const int16 *Cr_g_tab = Cr_r_tab + 256;
00214     const int16 *Cb_g_tab = Cr_g_tab + 256;
00215     const int16 *Cb_b_tab = Cb_g_tab + 256;
00216     const uint32 *rgbToPix = lookup->getRGBToPix();
00217     const uint32 *aToPix = lookup->getAlphaToPix();
00218 
00219     for (int h = 0; h < halfHeight; h++) {
00220         for (int w = 0; w < halfWidth; w++) {
00221             register const uint32 *L;
00222 
00223             int16 cr_r  = Cr_r_tab[*vSrc];
00224             int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc];
00225             int16 cb_b  = Cb_b_tab[*uSrc];
00226             ++uSrc;
00227             ++vSrc;
00228 
00229             PUT_PIXELA(*ySrc, *aSrc, dstPtr);
00230             PUT_PIXELA(*(ySrc + yPitch), *(aSrc + yPitch), dstPtr + dstPitch);
00231             ySrc++;
00232             aSrc++;
00233             dstPtr += sizeof(PixelInt);
00234             PUT_PIXELA(*ySrc, *aSrc, dstPtr);
00235             PUT_PIXELA(*(ySrc + yPitch), *(aSrc + yPitch), dstPtr + dstPitch);
00236             ySrc++;
00237             aSrc++;
00238             dstPtr += sizeof(PixelInt);
00239         }
00240 
00241         dstPtr += dstPitch;
00242         ySrc += (yPitch << 1) - yWidth;
00243         aSrc += (yPitch << 1) - yWidth;
00244         uSrc += uvPitch - halfWidth;
00245         vSrc += uvPitch - halfWidth;
00246     }
00247 }
00248 
00249 void YUVAToRGBAManager::convert420(Graphics::Surface *dst, YUVAToRGBAManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, const byte *aSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
00250     // Sanity checks
00251     assert(dst && dst->getPixels());
00252     assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
00253     assert(ySrc && uSrc && vSrc);
00254     assert((yWidth & 1) == 0);
00255     assert((yHeight & 1) == 0);
00256 
00257     const YUVAToRGBALookup *lookup = getLookup(dst->format, scale);
00258 
00259     // Use a templated function to avoid an if check on every pixel
00260     if (dst->format.bytesPerPixel == 2)
00261         convertYUVA420ToRGBA<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, aSrc, yWidth, yHeight, yPitch, uvPitch);
00262     else
00263         convertYUVA420ToRGBA<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, aSrc, yWidth, yHeight, yPitch, uvPitch);
00264 }
00265 
00266 } // End of namespace Graphics


Generated on Sat Feb 16 2019 05:01:12 for ResidualVM by doxygen 1.7.1
curved edge   curved edge