diff -r 000000000000 -r 951a5db380a0 videoeditorengine/vedengine/videoprocessor/src/yuv2rgb24.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/vedengine/videoprocessor/src/yuv2rgb24.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,419 @@ +/* +* Copyright (c) 2010 Ixonos Plc. +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - Initial contribution +* +* Contributors: +* Ixonos Plc +* +* Description: +* Implementation of class CYuv2Rgb24. +* YUV to EColor16M colorspace converter concrete classes. +* +*/ + + + + +// EXTERNAL RESOURCES + + +// Include Files + +#include +#include "yuvconverter.h" +#include "yuv2rgb24.h" +#include "brightnesscontrast.h" + + +// MEMBER FUNCTIONS + + +//============================================================================= + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + CYuv2Rgb24() + + Standard C++ constructor + +----------------------------------------------------------------------------- +*/ + +CYuv2Rgb24::CYuv2Rgb24() +{ + iRgbLookupTable = 0; + iGamma = 65536; + iBrightnessContrast = KMedBrightnessContrastIndex; + +} + + + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + ~CYuv2Rgb24() + + Standard C++ destructor + +----------------------------------------------------------------------------- +*/ + +CYuv2Rgb24::~CYuv2Rgb24() +{ + User::Free(iRgbLookupTable); +} + + + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + ConstructL() + + Standard Symbian OS second-phase constructor. Initializes the object. + +----------------------------------------------------------------------------- +*/ + +void CYuv2Rgb24::ConstructL(TUint aWidth, TUint aHeight, TUint aMaxWidth, TUint aMaxHeight) +{ + // Remember the dimensions +// __ASSERT_ALWAYS(((aWidth & 1) == 0) && ((aHeight & 1) == 0), +// User::Leave(KErrArgument)); + iWidth = aWidth; + iHeight = aHeight; + if ( iWidth > aMaxWidth ) { + iCropWidth = (iWidth-aMaxWidth)/2; + iWidth = aMaxWidth; + } + else { + iCropWidth = 0; + } + if ( iHeight > aMaxHeight ) { + iCropHeight = (iHeight-aMaxHeight)/2; + iHeight = aMaxHeight; + } + else { + iCropHeight = 0; + } + + // Allocate the RGB saturate/gamma lookup table + iRgbLookupTable = (TUint8*) User::AllocL(ESaturateLength); + + // Initialize brightness & contrast value, this will calculate the conversion table + // Since this uses the median index, it makes no difference if the preferred + // enhancement is this or gamma. Furthermore, changes to the value will be done using + // the appropriate method. + SetBrightnessContrast(KMaxBCInputIndex/2); +} + + + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + SetGamma() + + Sets the conversion gamma value and recalculates the look-up table + +----------------------------------------------------------------------------- +*/ + +void CYuv2Rgb24::SetGamma(TInt aGamma) +{ + TInt i, v; + TReal vNorm; + + // Remember gamma and convert it to floating point + iGamma = aGamma; + TReal fGamma = TReal(iGamma) / TReal(65536); + + // Calculate table entries for all possible RGB values: + for ( i = 0; i < ESaturateLength; i++ ) + { + // Actual RGB value for this table index + v = i - ESaturateOffset; + + // Saturate if <0 or >255, otherwise calculate gamma + if ( v < 0 ) + v = 0; + else if ( v > 255 ) + v = 255; + else + { + // Normalize v: + vNorm = TReal(v) / TReal(255); + + // Gamma-correct: v = v ^ gamma + Math::Pow(vNorm, vNorm, fGamma); + + // Scale back to [0..255] and clamp: + vNorm = (TReal(255) * vNorm) + 0.5; + v = (TInt) vNorm; + if ( v < 0 ) v = 0; + if ( v > 255 ) v = 255; + } + + // 24bpp RGB has range [0..255] for all components, store to table: + iRgbLookupTable[i] = (TUint8) v; + } +} + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + SetBrightnessContrast() + + Sets the index to the predefined brightness&contrast lookup table + (KBrightnessContrastEnhParam) and recalculates the RGB look-up table + The algorithm was developed by IMAAMI for Kenny display. + +----------------------------------------------------------------------------- +*/ +void CYuv2Rgb24::SetBrightnessContrast(TInt aBCIndex) +{ + TInt i, v; + TReal vNorm; + + // Convert & remember brightness-contrast index. aBCIndex == 0 to KMaxBCInputIndex. + iBrightnessContrast = (aBCIndex*KMaxBrightnessContrastIndex)/KMaxBCInputIndex; + + // Calculate table entries for all possible RGB values: + for ( i = 0; i < ESaturateLength; i++ ) + { + // Actual RGB value for this table index + v = 298 * (i - ESaturateOffset - 16) / 256; + // (see Convert()) + + // Saturate if <0 or >255, otherwise calculate value + if ( v < 0 ) + v = 0; + else if ( v > 255 ) + v = 255; + else + { + + // Normalize v: + vNorm = TReal(v) / TReal(255); + + vNorm = KBrightnessContrastEnhParam[iBrightnessContrast].a * vNorm + KBrightnessContrastEnhParam[iBrightnessContrast].b; + if ( vNorm < 0 ) + vNorm = 0; + else if ( vNorm > 1 ) + vNorm = 1; + Math::Pow( vNorm, vNorm, KBrightnessContrastEnhParam[iBrightnessContrast].g ); + + // Scale back to [0..255] and clamp: + vNorm = (TReal(255) * vNorm) + 0.5; + v = (TInt) vNorm; + if ( v < 0 ) v = 0; + if ( v > 255 ) v = 255; + } + + // 24bpp RGB has range [0..255] for all components, store to table: + iRgbLookupTable[i] = (TUint8) v; + } +} + + +/* +----------------------------------------------------------------------------- + + CYuv2Rgb24 + + Convert() + + Converts a YUV frame to a EColor16M frame + +----------------------------------------------------------------------------- +*/ + +void CYuv2Rgb24::Convert(const TUint8 *aYBuf, const TUint8 *aUBuf, + const TUint8 *aVBuf, + TUint aBufWidth, TUint aBufHeight, + TUint8 *aTarget, TUint aTargetScanlineLength) +{ + TUint cols; + TUint rows = iHeight; + TUint8 *target; + TUint8 *target2; + const TUint8 *yb, *yb2; + TInt rc, gc, bc; + TInt y; + TInt uval, vval; + TUint8 val; + + + __ASSERT_ALWAYS((aBufWidth >= iWidth) && (aBufHeight >= iHeight), + User::Invariant()); + + // Cropping needed? + if ( iCropWidth > 0 ) { + //sets offset to buffers; from now on increments below will always result the same offset, since the increment is aBufWidth + aYBuf += iCropWidth; + aUBuf += iCropWidth/2; + aVBuf += iCropWidth/2; + } + if ( iCropHeight > 0 ) { + //skip lines on top + aYBuf += iCropHeight*aBufWidth; + aUBuf += (iCropHeight/2)*aBufWidth/2; + aVBuf += (iCropHeight/2)*aBufWidth/2; + } + // We don't interpolate the chrominance values at all, since that way we + // can save a lot of multiplications. This actually doesn't affect the + // subjective picture quality much, if at all, with natural images. + + // Conversion is done 2x2 pixels at a time + + // Luminance-only conversion? + if ( (aUBuf != NULL) && (aVBuf != NULL) ) + { + // Full conversion + + // Convert all rows, two at a time + while ( rows ) + { + // Convert all pixels in this row, two at a time + cols = iWidth; + target = aTarget; + target2 = aTarget + aTargetScanlineLength; + yb = aYBuf; + yb2 = aYBuf + aBufWidth; + + while ( cols ) + { + // Charles Poynton: Color FAQ + // (http://www.inforamp.net/~poynton/ColorFAQ.html) + // 30. How do I encode Y'CBCR components from computer R'G'B' ? + + // [normalized] + // R = 1.1643828125 * (Y-16) + 1.59602734375 * (Cr-128) + // G = 1.1643828125 * (Y-16) + -0.39178515625 * (Cb-128) + -0.81296875 * (Cr-128) + // B = 1.1643828125 * (Y-16) + 2.01723046875 * (Cb-128) + + // We'll use fixed-point with 16 bits of fractional part for + // accuracy. Besides, 24bpp RGB is not likely to be used in + // low-CPU devices in the near future... + + // Red chrominance part for this 2x2 block: + vval = ((TInt) aVBuf[0]) - 128; + rc = 104597 * vval; + + // Green chrominance: + uval = ((TInt) aUBuf[0]) - 128; + gc = -25676*uval - 53279*vval; + + // Blue chrominance: + bc = 132201 * uval; + + // Upper left pixel y part for all components: + y = 76309 * (((TInt) yb[0]) - 16) + 32768; // round up + + // Calculate components and store: + // Bitmap format: bbbbbbbb gggggggg rrrrrrrr + target[0] = iRgbLookupTable[((y+bc) >> 16) + ESaturateOffset]; + target[1] = iRgbLookupTable[((y+gc) >> 16) + ESaturateOffset]; + target[2] = iRgbLookupTable[((y+rc) >> 16) + ESaturateOffset]; + + // Upper right pixel: + y = 76309 * (((TInt) yb[1]) - 16) + 32768; + target[3] = iRgbLookupTable[((y+bc) >> 16) + ESaturateOffset]; + target[4] = iRgbLookupTable[((y+gc) >> 16) + ESaturateOffset]; + target[5] = iRgbLookupTable[((y+rc) >> 16) + ESaturateOffset]; + + // Lower left: + y = 76309 * (((TInt) yb2[0]) - 16) + 32768; + target2[0] = iRgbLookupTable[((y+bc) >> 16) + ESaturateOffset]; + target2[1] = iRgbLookupTable[((y+gc) >> 16) + ESaturateOffset]; + target2[2] = iRgbLookupTable[((y+rc) >> 16) + ESaturateOffset]; + + // Lower right: + y = 76309 * (((TInt) yb2[1]) - 16) + 32768; + target2[3] = iRgbLookupTable[((y+bc) >> 16) + ESaturateOffset]; + target2[4] = iRgbLookupTable[((y+gc) >> 16) + ESaturateOffset]; + target2[5] = iRgbLookupTable[((y+rc) >> 16) + ESaturateOffset]; + + // Next two pixels: + target += 6; + target2 += 6; + yb += 2; + yb2 += 2; + aUBuf++; + aVBuf++; + cols -= 2; + } + + // Next rows + rows -= 2; + aYBuf += 2*aBufWidth; + aUBuf += (aBufWidth - iWidth)/2; + aVBuf += (aBufWidth - iWidth)/2; + aTarget += 2*aTargetScanlineLength; + } + } + else + { + // No chrominance given, do a luminance-only conversion + + // Convert all rows + while ( rows ) + { + // Convert all pixels in this row, two at a time + cols = iWidth; + target = aTarget; + + while ( cols ) + { + // Do a pixel: + y = 76309 * (((TInt) aYBuf[0]) - 16) + 32768; + val = iRgbLookupTable[(y >> 16) + ESaturateOffset]; + target[0] = val; + target[1] = val; + target[2] = val; + + // And another one: + y = 76309 * (((TInt) aYBuf[1]) - 16) + 32768; + val = iRgbLookupTable[(y >> 16) + ESaturateOffset]; + target[3] = val; + target[4] = val; + target[5] = val; + + // Next two pixels: + target += 6; + aYBuf += 2; + cols -= 2; + } + + // Next row + rows--; + aYBuf += aBufWidth - iWidth; + aTarget += aTargetScanlineLength; + } + } +} + + + + + +// End of File