--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/thumbnailengine/TneProcessorSrc/yuv2rgb24.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,418 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+* Description: Implementation of class CYuv2Rgb24.
+* YUV to EColor16M colorspace converter concrete classes
+*
+*/
+
+
+
+
+
+// EXTERNAL RESOURCES
+
+
+// Include Files
+
+#include <e32math.h>
+#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