--- a/engine/collectionframework/thumbnailcreator/src/glxtnimageutility.cpp Mon Sep 27 15:13:20 2010 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,626 +0,0 @@
-/*
-* Copyright (c) 2008-2009 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: Utility for creating bitmaps from video files
-*
-*/
-
-
-
-/**
- * @internal reviewed 31/07/2007 by Simon Brooks
- */
-
-#include "glxtnimageutility.h"
-
-#include <MIHLScaler.h> // MIHLScaler
-#include <fbs.h>
-#include <glxtracer.h>
-#include <glxpanic.h>
-#include <glxthumbnail.h>
-#include <imageconversion.h>
-
-#include "glxtnimagedecoderfactory.h"
-
-// -----------------------------------------------------------------------------
-// Constructor
-// -----------------------------------------------------------------------------
-//
-CGlxtnImageUtility::CGlxtnImageUtility(RFs& aFs) : iFs(aFs)
- {
- TRACER("CGlxtnImageUtility::CGlxtnImageUtility()");
- }
-
-// -----------------------------------------------------------------------------
-// Destructor
-// -----------------------------------------------------------------------------
-//
-CGlxtnImageUtility::~CGlxtnImageUtility()
- {
- TRACER("CGlxtnImageUtility::~CGlxtnImageUtility()");
- delete iDecoder;
- delete iScaler;
- delete iBitGc;
- }
-
-// -----------------------------------------------------------------------------
-// Cancel
-// -----------------------------------------------------------------------------
-//
-void CGlxtnImageUtility::Cancel()
- {
- TRACER("void CGlxtnImageUtility::Cancel()");
- if ( iDecoder )
- {
- iDecoder->Cancel();
- }
- if ( iScaler && iScaler->IsBusy())
- {
- iScaler->CancelProcess();
- }
- }
-
-// -----------------------------------------------------------------------------
-// AdjustSize
-// -----------------------------------------------------------------------------
-//
-void CGlxtnImageUtility::AdjustSize(TSize& aTargetSize, const TSize& aSourceSize)
- {
- TRACER("void CGlxtnImageUtility::AdjustSize()");
- if ( aTargetSize.iHeight * aSourceSize.iWidth
- < aTargetSize.iWidth * aSourceSize.iHeight )
- {
- // Source has taller aspect than target so reduce target width
- aTargetSize.iWidth = ( ( aTargetSize.iHeight * aSourceSize.iWidth )
- / ( aSourceSize.iHeight ) );
- }
- else
- {
- // Source has wider aspect than target so reduce target height
- aTargetSize.iHeight = (aTargetSize.iWidth * aSourceSize.iHeight)
- / aSourceSize.iWidth;
- }
- }
-
-// -----------------------------------------------------------------------------
-// DecodeImageL
-// -----------------------------------------------------------------------------
-//
-CFbsBitmap* CGlxtnImageUtility::DecodeImageL(TRequestStatus& aStatus,
- const TDesC& aFileName, RArray<TSize>& aTargetSizes, TDisplayMode aMode)
- {
- TRACER("CFbsBitmap* CGlxtnImageUtility::DecodeImageL()");
- delete iDecoder;
- iDecoder = NULL;
- iDecoder = GlxtnImageDecoderFactory::NewL( iFs, aFileName );
-
- iOriginalSize = iDecoder->FrameInfo().iOverallSizeInPixels;
- if ( 0 == iOriginalSize.iWidth || 0 == iOriginalSize.iHeight )
- {
- User::Leave(KErrCorrupt);
- }
-
- TInt count = aTargetSizes.Count();
- TSize testSize;
- TSize targetSize;
- for ( TInt i = 0 ; i < count ; i++ )
- {
- testSize = aTargetSizes[i];
- AdjustSize(testSize, iOriginalSize);
- if( ( testSize.iWidth > targetSize.iWidth ) || ( testSize.iHeight > targetSize.iHeight ) )
- {
- targetSize = testSize;
- }
- }
-
- // Find max scaling factor which won't make image smaller than target size
- TInt shift = 3;
- while ( shift
- && ((iOriginalSize.iWidth >> shift) < targetSize.iWidth
- || (iOriginalSize.iHeight >> shift) < targetSize.iHeight ) )
- {
- shift--;
- }
- TInt roundUp = (1 << shift) - 1;
- TSize loadSize((iOriginalSize.iWidth + roundUp) >> shift,
- (iOriginalSize.iHeight + roundUp) >> shift);
-
- CFbsBitmap* image = new (ELeave) CFbsBitmap;
- CleanupStack::PushL(image);
- User::LeaveIfError(image->Create(loadSize, aMode));
-
- iDecoder->Convert(&aStatus, *image);
-
- CleanupStack::Pop(image);
- return image;
- }
-
-// -----------------------------------------------------------------------------
-// FreeDecoder
-// -----------------------------------------------------------------------------
-//
-void CGlxtnImageUtility::FreeDecoder()
- {
- TRACER("void CGlxtnImageUtility::FreeDecoder()");
- delete iDecoder;
- iDecoder = NULL;
- }
-
-// -----------------------------------------------------------------------------
-// OriginalSize
-// -----------------------------------------------------------------------------
-//
-const TSize& CGlxtnImageUtility::OriginalSize() const
- {
- TRACER("TSize& CGlxtnImageUtility::OriginalSize()");
- return iOriginalSize;
- }
-
-//---------------------------------------------------------------------------
-/**
- K-Nearest neighbour scaling for EColor64K.
- Code originally inherited from t_display.cpp by Toni Hemminki.
- Added windowing and further optimized by Jarmo Nikula 2006-2007.
-
- @param aSrc Source buffer pointer
- @param aSrcStride Source buffer stride in bytes
- @param aSrcCols Source columns
- @param aSrcRows Source rows
- @param aX Source window top-left X-coordinate
- @param aY Source window top-left Y-coordinate
- @param aW Source window width
- @param aH Source window height
- @param aDst Destination buffer pointer
- @param aDstStride Destination buffer stride in bytes
- @param aDstCols Destination columns, must be even
- @param aDstRows Destination rows
-*/
-// OPTION's for MMP file:
-// Interleave assembly code with C, output can be found on txt-files on some BUILD directory:
-// OPTION ARMCC --asm --interleave
-// Modify optimization for ARM insturcion set and for maximum speed
-// OPTION_REPLACE ARMCC --arm -Otime
-/* aSource->LockHeap();
- TUint16* sourceAddress = (TUint16*)aSource->DataAddress();
- aSource->UnlockHeap();
- aTarget->LockHeap();
- TUint16* targetAddress = (TUint16*)aTarget->DataAddress();
- aTarget->UnlockHeap();
- ScaleColor64K(sourceAddress, aSource->DataStride(),
- sourceSize.iWidth, sourceSize.iHeight, 0, 0, sourceSize.iWidth, sourceSize.iHeight,
- targetAddress, aTarget->DataStride(),
- targetSize.iWidth, targetSize.iHeight);
-*/
-
-void CGlxtnImageUtility::FilterImageL(TRequestStatus* aStatus, CFbsBitmap* aSource, CFbsBitmap*& aFilteredSource, CFbsBitmap* aTarget)
- {
- TRACER("void CGlxtnImageUtility::FilterImageL()");
- TSize sourceSize(aSource->SizeInPixels());
- TSize targetSize(aTarget->SizeInPixels());
- TInt scalePercent = ((100*sourceSize.iWidth)/targetSize.iWidth) - 100;
-
- // no need to filter if close enough or smaller
- if ( scalePercent >= 2 && ( aTarget->DisplayMode() == EColor64K ) )
- {
- FilterL(aSource, aFilteredSource, scalePercent);
- }
-
- *aStatus = KRequestPending;
- User::RequestComplete(aStatus, KErrNone);
- }
-
-// -----------------------------------------------------------------------------
-// ScaleImageL
-// -----------------------------------------------------------------------------
-//
-void CGlxtnImageUtility::ScaleImageL(TRequestStatus& aStatus, CFbsBitmap& aSrcBitmap,
- const TRect& aSrcRect, CFbsBitmap& aDstBitmap,
- const TRect& aDstRect)
- {
- TRACER("void CGlxtnImageUtility::ScaleImageL(IHL)");
- if (!iScaler)
- {
- TInt option = MIHLScaler::EOptionUseBilinearInterpolation;
-
- iScaler = IHLScaler::CreateL(option);
- }
- User::LeaveIfError(iScaler->Scale(aStatus, aSrcBitmap, aSrcRect, aDstBitmap, aDstRect));
- }
-
-void CGlxtnImageUtility::ScaleImage64kL(TRequestStatus* aStatus, CFbsBitmap* aSource, CFbsBitmap* aFilteredSource, CFbsBitmap* aTarget)
- {
- TRACER("void CGlxtnImageUtility::ScaleImage64kL()");
- TSize sourceSize(aSource->SizeInPixels());
- TSize targetSize(aTarget->SizeInPixels());
- TInt scalePercent = ((100*sourceSize.iWidth)/targetSize.iWidth) - 100;
- TRect targetRect(targetSize);
- TRect sourceRect(sourceSize);
-
- CFbsBitmap* sourceImage = aFilteredSource;
- if ( !aFilteredSource )
- {
- sourceImage = aSource;
- }
- if ( scalePercent < 2 )
- {
- if ( scalePercent > 0 )
- {
- sourceRect = targetRect;
- }
- sourceImage = aSource;
- }
- sourceImage->LockHeap();
- TUint16* sourceAddress = (TUint16*)sourceImage->DataAddress();
- sourceImage->UnlockHeap();
- aTarget->LockHeap();
- TUint16* targetAddress = (TUint16*)aTarget->DataAddress();
- aTarget->UnlockHeap();
- ScaleColor64K(sourceAddress, sourceImage->DataStride(),
- sourceImage->SizeInPixels().iWidth, sourceImage->SizeInPixels().iHeight, 0, 0, sourceImage->SizeInPixels().iWidth, sourceImage->SizeInPixels().iHeight,
- targetAddress, aTarget->DataStride(),
- targetSize.iWidth, targetSize.iHeight);
-
-/* if ( !iBitGc )
- {
- iBitGc = CFbsBitGc::NewL();
- }
- CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(aTarget);
- CleanupStack::PushL(bitmapDevice);
- iBitGc->Activate(bitmapDevice);
- iBitGc->DrawBitmap(targetRect, sourceImage, sourceRect);
- CleanupStack::PopAndDestroy(bitmapDevice);
-*/
- *aStatus = KRequestPending;
- User::RequestComplete(aStatus, KErrNone);
- }
-
-void CGlxtnImageUtility::ScaleColor64K( TUint16* aSrc, TInt aSrcStride, TInt /*aSrcCols*/, TInt /*aSrcRows*/,
- TInt aX, TInt aY, TInt aW, TInt aH,
- TUint16* aDst, TInt aDstStride, TInt aDstCols, TInt aDstRows )
- {
- TRACER("void CGlxtnImageUtility::ScaleColor64K()");
- const TUint KPrecision = 16;
- TUint hInc = ( aW<< KPrecision ) / aDstCols;
- TUint vInc = ( aH << KPrecision ) / aDstRows;
- TUint v = 0;
- for ( TUint row = aDstRows; row > 0; --row )
- {
- TInt h = hInc * (aDstCols - 1);
- TUint linestart = aSrcStride * ( aY + ( v >> KPrecision ) ) / sizeof(TUint16) + aX;
- TUint16* src = &aSrc[ linestart ];
- TUint32* dst = (TUint32*)aDst + aDstCols / 2;
- TUint32 pxl2x;
- // This loop generates 11 assembly instructions per round
- // when using "--arm --Otime" options. Since two pixels are handled per round,
- // it means 5.5 instructions per pixel on average.
- do {
- pxl2x = src[ h >> KPrecision ]<<16;
- h -= hInc;
- pxl2x |= src[ h >> KPrecision ];
- *--dst = pxl2x;
- // Compiler eliminates CMP instruction when substraction
- // is done inside the while () statement.
- } while ( ( h -= hInc ) >= 0 );
- v += vInc;
- aDst += aDstStride / sizeof(TUint16);
- }
- }
-
-void CGlxtnImageUtility::FilterL( CFbsBitmap* aSource, CFbsBitmap*& aFilteredSource, TInt aFilterPercent )
- {
- TRACER("void CGlxtnImageUtility::FilterL()");
- if ( !aFilteredSource )
- {
- TSize imageSize = aSource->SizeInPixels();
- aFilteredSource = new (ELeave) CFbsBitmap;
- aFilteredSource->Create(imageSize, aSource->DisplayMode());
-
- CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(aFilteredSource);
- if ( !iBitGc )
- {
- iBitGc = CFbsBitGc::NewL();
- }
- iBitGc->Activate(bitmapDevice);
- iBitGc->BitBlt(TPoint(), aSource, imageSize);
- delete bitmapDevice;
- }
-
- TSize imageSize = aFilteredSource->SizeInPixels();
- aFilteredSource->LockHeap();
- TUint16* sourceAddress = (TUint16*)aFilteredSource->DataAddress();
- aFilteredSource->UnlockHeap();
- const TInt KGlxScalingNeeds4Filtering = 80; // if scaling more than 1.8 need to filter by 4
- const TInt KGlxScalingNeeds8Filtering = 260; // if scaling more than 3.6 need to filter by 8
- if ( KGlxScalingNeeds8Filtering < aFilterPercent )
- {
- FIRFiltering8(
- sourceAddress, aFilteredSource->DataStride() / sizeof(TUint16),
- imageSize.iWidth, imageSize.iHeight );
- }
- else if ( KGlxScalingNeeds4Filtering < aFilterPercent )
- {
- FIRFiltering4(
- sourceAddress, aFilteredSource->DataStride() / sizeof(TUint16),
- imageSize.iWidth, imageSize.iHeight );
- }
- else
- {
- FIRFiltering(
- sourceAddress, aFilteredSource->DataStride() / sizeof(TUint16),
- imageSize.iWidth, imageSize.iHeight );
- }
- }
-
-#define rmask565 0xf800
-#define gmask565 0x07e0
-#define bmask565 0x001f
-#define rbmask565 (rmask565|bmask565)
-#define rm565( rgb ) ((rgb) & rmask565)
-#define gm565( rgb ) ((rgb) & gmask565)
-#define bm565( rgb ) ((rgb) & bmask565)
-#define rbm565( rgb ) ((rgb) & rbmask565)
-#define r565( rgb ) ((rgb)>>11)
-#define g565( rgb ) (gm565(rgb)>>5)
-#define b565( rgb ) (bm565(rgb))
-#define rgb565( r, g, b ) (((r)<<11)|((g)<<5)|(b))
-
-#define mask32gbr655 0x07e0f81f
-
-// Keep below three defs in sync with each other!
-#define KFIRLen 2
-#define KFIRCen (KFIRLen / 2)
-#define incFIRIndex( i ) i = (i + 1) & (KFIRLen - 1)
-// Keep above three defs in sync with each other!
-
-void CGlxtnImageUtility::FIRFiltering(
- TUint16* aDst, TUint aDstStridep, TUint aDstCols, TUint aDstRows )
- {
- TRACER("void CGlxtnImageUtility::FIRFiltering( )");
- TUint firFifo[ KFIRLen ];
- TUint i; // index for fifo in&out
- TUint16 *p;
- TUint32 px;
- TInt row, col;
- TUint FIRsum;
- // Horizontal scan.
- p = aDst;
- for ( row = aDstRows - 1; row >= 0; row-- )
- {
- // read for cache
- //for ( col = aDstCols - 1; col >= 0; col-- ) TInt temp = p[ col ];
- // Fill in the FIR first.
- // TODO: Fill in with extrapolated values at edges!
- FIRsum = ((KFIRLen / 2)<<21) | ((KFIRLen / 2)<<11) | (KFIRLen / 2); // for correct rounding
- i = 0;
- TUint32 mask1 = mask32gbr655;
- for ( col = 0; col < KFIRLen; col++ )
- {
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex( i );
- }
- TUint32 ave;
- for ( ; col < aDstCols; col++ )
- {
- ave = ( FIRsum / KFIRLen ) & mask1;
- p[ col - KFIRCen ] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex( i );
- }
- p += aDstStridep;
- }
- // Vertical scan.
- for ( col = aDstCols - 1; col >= 0; col-- )
- {
- // Fill in the FIR first.
- FIRsum = ((KFIRLen / 2)<<21) | ((KFIRLen / 2)<<11) | (KFIRLen / 2); // for correct rounding
- TUint32 mask1 = mask32gbr655;
- i = 0;
- p = aDst + col;
- for ( row = 0; row < KFIRLen; row++ )
- {
- px = *p;
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex( i );
- p += aDstStridep;
- }
- TUint32 ave;
- p -= aDstStridep * KFIRCen;
- for ( ; row < aDstRows; row++ )
- {
- ave = ( FIRsum / KFIRLen ) & mask1;
- p[0] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ aDstStridep * KFIRCen ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex( i );
- p += aDstStridep;
- }
- }
- }
-//
-// Keep below three defs in sync with each other!
-#define KFIRLen4 4
-#define KFIRCen4 (KFIRLen4 / 2)
-#define incFIRIndex4( i ) i = (i + 1) & (KFIRLen4 - 1)
-// Keep above three defs in sync with each other!
-
-void CGlxtnImageUtility::FIRFiltering4(
- TUint16* aDst, TUint aDstStridep, TUint aDstCols, TUint aDstRows )
- {
- TRACER("void CGlxtnImageUtility::FIRFiltering4()");
- TUint firFifo[ KFIRLen4 ];
- TUint i; // index for fifo in&out
- TUint16 *p;
- TUint32 px;
- TInt row, col;
- TUint FIRsum;
- // Horizontal scan.
- p = aDst;
- for ( row = aDstRows - 1; row >= 0; row-- )
- {
- // read for cache
- //for ( col = aDstCols - 1; col >= 0; col-- ) TInt temp = p[ col ];
- // Fill in the FIR first.
- // TODO: Fill in with extrapolated values at edges!
- FIRsum = ((KFIRLen4 / 2)<<21) | ((KFIRLen4 / 2)<<11) | (KFIRLen4 / 2); // for correct rounding
- i = 0;
- TUint32 mask1 = mask32gbr655;
- for ( col = 0; col < KFIRLen4; col++ )
- {
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex4( i );
- }
- TUint32 ave;
- for ( ; col < aDstCols; col++ )
- {
- ave = ( FIRsum / KFIRLen4 ) & mask1;
- p[ col - KFIRCen4 ] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex4( i );
- }
- p += aDstStridep;
- }
- // Vertical scan.
- for ( col = aDstCols - 1; col >= 0; col-- )
- {
- // Fill in the FIR first.
- FIRsum = ((KFIRLen4 / 2)<<21) | ((KFIRLen4 / 2)<<11) | (KFIRLen4 / 2); // for correct rounding
- TUint32 mask1 = mask32gbr655;
- i = 0;
- p = aDst + col;
- for ( row = 0; row < KFIRLen4; row++ )
- {
- px = *p;
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex4( i );
- p += aDstStridep;
- }
- TUint32 ave;
- p -= aDstStridep * KFIRCen4;
- for ( ; row < aDstRows; row++ )
- {
- ave = ( FIRsum / KFIRLen4 ) & mask1;
- p[0] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ aDstStridep * KFIRCen4 ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex4( i );
- p += aDstStridep;
- }
- }
- }
-
-// Keep below three defs in sync with each other!
-#define KFIRLen8 8
-#define KFIRCen8 (KFIRLen8 / 2)
-#define incFIRIndex8( i ) i = (i + 1) & (KFIRLen8 - 1)
-// Keep above three defs in sync with each other!
-
-void CGlxtnImageUtility::FIRFiltering8(
- TUint16* aDst, TUint aDstStridep, TUint aDstCols, TUint aDstRows )
- {
- TRACER("void CGlxtnImageUtility::FIRFiltering8()");
- TUint firFifo[ KFIRLen8 ];
- TUint i; // index for fifo in&out
- TUint16 *p;
- TUint32 px;
- TInt row, col;
- TUint FIRsum;
- // Horizontal scan.
- p = aDst;
- for ( row = aDstRows - 1; row >= 0; row-- )
- {
- // read for cache
- //for ( col = aDstCols - 1; col >= 0; col-- ) TInt temp = p[ col ];
- // Fill in the FIR first.
- // TODO: Fill in with extrapolated values at edges!
- FIRsum = ((KFIRLen8 / 2)<<21) | ((KFIRLen8 / 2)<<11) | (KFIRLen8 / 2); // for correct rounding
- i = 0;
- TUint32 mask1 = mask32gbr655;
- for ( col = 0; col < KFIRLen8; col++ )
- {
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex8( i );
- }
- TUint32 ave;
- for ( ; col < aDstCols; col++ )
- {
- ave = ( FIRsum / KFIRLen8 ) & mask1;
- p[ col - KFIRCen8 ] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ col ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex8( i );
- }
- p += aDstStridep;
- }
- // Vertical scan.
- for ( col = aDstCols - 1; col >= 0; col-- )
- {
- // Fill in the FIR first.
- FIRsum = ((KFIRLen8 / 2)<<21) | ((KFIRLen8 / 2)<<11) | (KFIRLen8 / 2); // for correct rounding
- TUint32 mask1 = mask32gbr655;
- i = 0;
- p = aDst + col;
- for ( row = 0; row < KFIRLen8; row++ )
- {
- px = *p;
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex8( i );
- p += aDstStridep;
- }
- TUint32 ave;
- p -= aDstStridep * KFIRCen8;
- for ( ; row < aDstRows; row++ )
- {
- ave = ( FIRsum / KFIRLen8 ) & mask1;
- p[0] = TUint16( ave | (ave>>16) );
- FIRsum -= firFifo[ i ];
- px = p[ aDstStridep * KFIRCen8 ];
- px = ((px<<16) | px) & mask1;
- firFifo[ i ] = px;
- FIRsum += px;
- incFIRIndex8( i );
- p += aDstStridep;
- }
- }
- }