--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/src/CJpeg.cpp Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,2370 @@
+/*
+* 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:
+*
+*/
+
+
+
+#include "CJpeg.h"
+#include <e32svr.h>
+
+
+const TUint8 KQuantIndex[ 3 ] = { 0,1,1 };
+const TUint8 KHuffIndex[ 3 ] = { 0,1,1 };
+
+
+
+
+const TUint8 KZigZag[] = {
+ 0, 8, 1, 2, 9, 16, 24, 17,
+ 10, 3, 4, 11, 18, 25, 32, 40,
+ 33, 26, 19, 12, 5, 6, 13, 20,
+ 27, 34, 41, 48, 56, 49, 42, 35,
+ 28, 21, 14, 7, 15, 22, 29, 36,
+ 43, 50, 57, 58, 51, 44, 37, 30,
+ 23, 31, 38, 45, 52, 59, 60, 53,
+ 46, 39, 47, 54, 61, 62, 55, 63
+ };
+
+
+
+
+
+
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+
+const TUint8 bits_dc_luminance[17] =
+{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+const TUint8 val_dc_luminance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+const TUint8 bits_dc_chrominance[17] =
+{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+const TUint8 val_dc_chrominance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+const TUint8 bits_ac_luminance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+const TUint8 val_ac_luminance[] =
+{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+const TUint8 bits_ac_chrominance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+
+const TUint8 val_ac_chrominance[] =
+{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+const TUint8 KExifHeader[] = "Exif";
+
+class THuffman
+ {
+ public:
+ TInt8 iLength[ 256 ];
+ TUint8 iSymbol[ 256 ];
+ TUint8 iSearch[ 65536 ];
+ };
+
+
+CJpeg* CJpeg::NewL()
+ {
+ CJpeg* self = NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+CJpeg* CJpeg::NewLC()
+ {
+ CJpeg* self = new( ELeave )CJpeg();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+CJpeg::~CJpeg()
+ {
+ delete iHuffman[ 0 ];
+ delete iHuffman[ 1 ];
+ delete iHuffman[ 2 ];
+ delete iHuffman[ 3 ];
+
+ delete iQt[ 0 ];
+ delete iQt[ 1 ];
+ delete iQt[ 2 ];
+ delete iQt[ 3 ];
+
+ iCurrentQt = NULL;
+ iExifData = NULL;
+
+ //iBlock.Reset();
+ delete iBlock;
+
+ delete iBuffer;
+ delete iC[ 0 ];
+ delete iC[ 1 ];
+ delete iC[ 2 ];
+
+ //iDebug.Close();
+ //iFs.Close();
+ }
+
+CJpeg::CJpeg()
+ {
+
+ }
+
+void CJpeg::ConstructL()
+ {
+ }
+
+
+
+
+void CJpeg::OpenL( const TFileName& aFile )
+ {
+ if (iBuffer)
+ {
+ delete iBuffer;
+ iBuffer = NULL;
+ }
+
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL( fs );
+
+ RFile file;
+ TInt err = file.Open( fs, aFile, EFileRead | EFileShareReadersOnly );
+ if (KErrNone != err)
+ {
+ User::LeaveIfError( file.Open( fs, aFile, EFileRead | EFileShareAny ) );
+ }
+ CleanupClosePushL( file );
+
+ TInt size;
+ file.Size( size );
+ iBuffer = new( ELeave )TUint8[ size + 2 ];
+ TPtr8 ptr( iBuffer, size );
+ file.Read( ptr );
+
+ CleanupStack::PopAndDestroy( 2 ); // file, fs
+ OpenL( ptr );
+ }
+
+
+
+void CJpeg::OpenL( const TPtr8& aData )
+ {
+ //iFs.Connect();
+ //iDebug.Replace( iFs, _L("e:\\TestData\\jpdeb.txt"), EFileWrite );
+
+ EnableRgvConv();
+
+ iBuffer = (TUint8*)aData.Ptr();
+
+ // if used again, all variables should be cleared
+ iBuf = 0;
+ iBufBits = 0;
+
+ delete iHuffman[ 0 ];
+ delete iHuffman[ 1 ];
+ delete iHuffman[ 2 ];
+ delete iHuffman[ 3 ];
+ iHuffman[ 0 ] = 0;
+ iHuffman[ 1 ] = 0;
+ iHuffman[ 2 ] = 0;
+ iHuffman[ 3 ] = 0;
+
+ //iDebug.Write( _L8("d1\n") );
+
+ //
+ // This is only needed if no huffman tables found
+ //
+ //CreateDefaultHuffmanL();
+
+
+ iQt[ 0 ] = 0;
+ iQt[ 1 ] = 0;
+ iQt[ 2 ] = 0;
+ iQt[ 3 ] = 0;
+
+ //
+
+ //TBitmapHandle bm;
+ //bm.iData = 0;
+
+ TBool moreChunks = ETrue;
+ TBool possibleChunk = EFalse;
+
+// TInt pos;
+
+ while( moreChunks )
+ {
+ TUint8 b = iBuffer[ iBufPos++ ];
+ if( possibleChunk )
+ {
+ possibleChunk = EFalse;
+ switch( b )
+ {
+ case 0xd8: // start of image
+ {
+ //RDebug::Print( _L("--Jpeg start of image") );
+ //iDebug.Write( _L8("d2\n") );
+ break;
+ }
+ case 0xe0: // JFIF application segment
+ {
+ //RDebug::Print( _L("--Jpeg application segment") );
+ //iDebug.Write( _L8("d3\n") );
+ break;
+ }
+ case 0xe1: // APP1 segment, possible EXIF
+ {
+ //iDebug.Write( _L8("d4\n") );
+ //RDebug::Print( _L("--Jpeg app1 segment") );
+ TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ l -= 2;
+
+ // this could be used to read exif data:
+ //TPtrC8 exifData( iBuffer + iBufPos, l );
+
+ // Check that there is "Exif" header in the data
+ const TUint8* pos = &iBuffer[ iBufPos ];
+ if (Mem::Compare(pos, 2, &KExifHeader[0], 2 ))
+ {
+ iBufPos += l;
+ break;
+ }
+
+ // suppose there is exif here
+ // exif header is 6 bytes ( 45 78 69 66 00 00 "Exif.." )
+ iBufPos += 6;
+ l -= 6;
+
+ iExifData = iBuffer + iBufPos;
+ iExifDataLength = l;
+
+ iBufPos += l;
+ break;
+ }
+ case 0xe2:
+ case 0xe3:
+ case 0xe4:
+ case 0xe5:
+ case 0xe6:
+ case 0xe7:
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef:
+ {
+ //iDebug.Write( _L8("d5\n") );
+ //
+ // Unused segment, skip
+ //
+ //RDebug::Print( _L("--Jpeg unused tag %x"), b );
+ TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+
+ iBufPos += l-2;
+ break;
+ }
+ case 0xdb: // Quantization table
+ {
+ //iDebug.Write( _L8("d6\n") );
+
+ //RDebug::Print( _L("--Jpeg quant table") );
+ TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ ////RDebug::Print( _L("Start:%x length:%d"), iBufPos-2, l );
+ TInt nqt = l / 65;
+ TInt i;
+
+ // one or more quantization table
+ for( i=0; i<nqt; i++ )
+ {
+ TUint8 t = iBuffer[ iBufPos++ ];
+ TInt n = t & 15;
+
+ // not used:
+ // TInt precision = n >> 4;
+
+ if (iQt[ n ])
+ {
+ delete iQt[ n ];
+ iQt[ n ] = NULL;
+ }
+
+ iQt[ n ] = new( ELeave )TUint8[ 64 ];
+ TInt j;
+ for( j=0; j<64; j++ )
+ {
+ iQt[ n ][ j ] = iBuffer[ iBufPos++ ];
+ //RDebug::Print( _L("Quant %d:first=%d"), j, iQt[ n ][ j ] );
+ }
+ }
+
+ break;
+ }
+ case 0xc0: // start of frame ( SOF )
+ {
+ //iDebug.Write( _L8("d7\n") );
+
+ //RDebug::Print( _L("--Jpeg start of frame") );
+
+ //TInt length = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ];
+ iBufPos += 2;
+
+ ////RDebug::Print( _L("Start:%x length:%d"), iBufPos-2, length );
+
+ // not used:
+ // TInt precision = iBuffer[ iBufPos ];
+ iBufPos++;
+
+ // height
+ TInt t = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ iData.iSize.iHeight = t;
+
+ // width
+ t = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ iData.iSize.iWidth = t;
+
+ // component data
+ iNumComponents = iBuffer[ iBufPos++ ];
+
+ TInt i;
+ for( i=0; i<iNumComponents; i++ )
+ {
+ TInt compID = iBuffer[ iBufPos++ ];
+
+ TInt samplingFactor = iBuffer[ iBufPos++ ];
+ TInt quantizationTable = iBuffer[ iBufPos++ ];
+ iComponent[ i ].iXFactor = samplingFactor >> 4;
+ iComponent[ i ].iYFactor = samplingFactor & 15;
+ iComponent[ i ].iQuantTable = quantizationTable;
+ iComponent[ i ].iID = compID;
+ //RDebug::Print( _L("component %d = %d"), i, compID );
+ //RDebug::Print( _L("component %d quanttable=%d"), i, quantizationTable );
+ //RDebug::Print( _L("component %d factor = %d,%d"), iComponent[ i ].iXFactor, iComponent[ i ].iYFactor );
+ }
+
+ TInt xBlocks = 0;
+ TInt yBlocks = 0;
+
+ for( i=0; i<iNumComponents; i++ )
+ {
+ TInt x = iComponent[ i ].iXFactor;
+ TInt y = iComponent[ i ].iYFactor;
+ if( x > xBlocks )
+ {
+ xBlocks = x;
+ }
+ if( y > yBlocks )
+ {
+ yBlocks = y;
+ }
+ }
+
+ iData.iBlockSize.iWidth = xBlocks * 8;
+ iData.iBlockSize.iHeight = yBlocks * 8;
+
+ TSize size = iData.iSize;
+ size.iWidth /= iData.iBlockSize.iWidth;
+ size.iHeight /= iData.iBlockSize.iHeight;
+
+ if( iData.iSize.iWidth & ( iData.iBlockSize.iWidth - 1 ) )
+ {
+ size.iWidth++;
+ }
+
+ if( iData.iSize.iHeight & ( iData.iBlockSize.iHeight - 1 ) )
+ {
+ size.iHeight++;
+ }
+
+ iData.iSizeInBlocks = size;
+
+
+ break;
+ }
+ case 0xc1:
+ {
+ //iDebug.Write( _L8("d8\n") );
+ //RDebug::Print( _L("--Jpeg tag 0xc1, extended sequential, unsupported") );
+
+ // Extended sequential Jpeg, not supported
+ User::Leave( KErrNotSupported );
+ break;
+ };
+ case 0xc2:
+ {
+ //iDebug.Write( _L8("d9\n") );
+ //RDebug::Print( _L("--Jpeg tag 0xc2, Progressive DCT, unsupported") );
+
+ // Progressive DCT jpeg, not supported
+ User::Leave( KErrNotSupported );
+ break;
+ };
+ case 0xc3:
+ {
+ //iDebug.Write( _L8("d10\n") );
+
+ //RDebug::Print( _L("--Jpeg tag 0xc1, Lossless, unsupported") );
+ // Lossless ( sequential ) Jpeg, not supported
+ User::Leave( KErrNotSupported );
+ break;
+ };
+
+ case 0xc5:
+ case 0xc6:
+ case 0xc7:
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ {
+ //iDebug.Write( _L8("d11\n") );
+
+ //RDebug::Print( _L("--Jpeg tag %x, unknown"), b );
+ User::Leave( KErrNotSupported );
+ break;
+ };
+ case 0xc4: // huffman table
+ {
+ //iDebug.Write( _L8("d12\n") );
+
+ //RDebug::Print( _L("--Jpeg huffman table") );
+ TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+
+ TInt table = 0;
+
+ TInt n = 0;
+
+ // one or more huffman tables
+ while( n<l-2 )
+ {
+ THuffman* huff = new( ELeave )THuffman;
+
+ table = iBuffer[ iBufPos++ ];
+ n++;
+ TInt huffSize[ 16 ];
+ TInt numSymbols = 0;
+ TInt i;
+
+ for( i=0; i<16; i++ )
+ {
+ TInt size = iBuffer[ iBufPos++ ];
+ huffSize[ i ] = size;
+ numSymbols += size;
+ n++;
+ }
+
+ ////RDebug::Print( _L(" # of symbols %d"), numSymbols );
+
+ for( i=0; i<numSymbols; i++ )
+ {
+ TUint8 v = iBuffer[ iBufPos++ ];
+ huff->iSymbol[ i ] = v;
+ n++;
+ }
+
+
+ // Generate huffman lookup tables ( huffSize, table )
+
+
+ TInt ll;
+ TInt p = 0;
+ for( ll=0; ll<16; ll++ )
+ {
+ for( i=0; i<huffSize[ ll ]; i++ )
+ {
+ huff->iLength[ p++ ] = ll+1;
+ }
+ }
+
+ TInt code = 0;
+ huff->iLength[ p ] = 0;
+ TInt si = huff->iLength[ 0 ];
+ TInt lastP = p;
+
+ TInt hc[ 256 ];
+ p = 0;
+
+ while( huff->iLength[ p ] )
+ {
+ while( huff->iLength[ p ] == si )
+ {
+ hc[ p++ ] = code++;
+ }
+ code *= 2;
+ si++;
+ }
+
+ ll = 65536;
+ for( i=lastP-1; i>=0; i-- )
+ {
+ TInt t = 16 - huff->iLength[ i ];
+ TInt k = hc[ i ] * ( 1 << t );
+ TInt j;
+ for( j=k; j<ll; j++ )
+ {
+ huff->iSearch[ j ] = i;
+ }
+ ll = k;
+ }
+
+ i = ( table & 16 ) / 8 + ( table & 15 );
+ delete iHuffman[ i ];
+ iHuffman[ i ] = huff;
+ }
+
+ break;
+ }
+//
+ case 0xda: // start of scan ( SOS )
+ {
+ //iDebug.Write( _L8("d13\n") );
+
+ //RDebug::Print( _L("--Jpeg start of scan") );
+ //TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ iBufPos += 2;
+
+ TInt numComponents = iBuffer[ iBufPos++ ];
+ //RDebug::Print( _L("JPEG: number of components=%d"), numComponents );
+ if( numComponents != iNumComponents )
+ {
+ // non-interleaved( planar ) not supported
+ User::Leave( KErrNotSupported );
+ }
+ //RDebug::Print( _L("Number of components=%d"), numComponents );
+
+ TInt componentHt[ 3 ];
+
+ TInt i;
+ for( i=0; i<numComponents; i++ )
+ {
+ TInt componentId = iBuffer[ iBufPos++ ];
+ // find index by ID
+ TInt index = -1;
+ for( TInt j=0; j<iNumComponents; j++ )
+ {
+ if( iComponent[ j ].iID == componentId )
+ {
+ index = j;
+ }
+ }
+ if( index == -1 )
+ {
+ // ID not found
+ User::Leave( KErrNotSupported );
+ }
+ componentHt[ index ] = iBuffer[ iBufPos++ ];
+ //RDebug::Print( _L("id=%d, ht=%d"), componentId, componentHt[ i ] );
+ }
+
+ if( componentHt[ 1 ] == 0 || componentHt[ 2 ] == 0 )
+ {
+ // images with same huffman for all components
+ // not yet supported
+ //RDebug::Print( _L("jpeg not supported") );
+ User::Leave( KErrNotSupported );
+ }
+
+
+ if( iHuffman[ 0 ] == NULL )
+ {
+ // no huffman tables found, create default tables
+ CreateDefaultHuffmanL();
+ }
+
+
+ iBufPos += 3;
+
+ iImageDataStart = iBufPos;
+ iRandomScanned = false;
+
+ moreChunks = EFalse;
+
+ break;
+ }
+ case 0xd9: // end of image ( EOI )
+ {
+ //RDebug::Print( _L("--Jpeg end of image") );
+ // not really used for anything
+ // will exit if picture data is read.
+ break;
+ }
+ case 0xdd: // define restart interval
+ {
+ //RDebug::Print( _L("--Jpeg define restart interval") );
+
+ //TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ iBufPos += 2;
+
+ TInt interval = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
+ //iBufPos += 2;
+ //RDebug::Print( _L(" interval = %d"), interval );
+ iResetInterval = interval;
+
+ // not really used for anything
+ // restart markers are just handled when they come
+ break;
+ }
+ case 0x00: // escaped 0xff
+ {
+ // only comes if file is broken somehow
+ break;
+ }
+ default:
+ {
+ // unknown jpeg tag
+ //RDebug::Print( _L("unknown jpeg tag %x"), b );
+ break;
+ }
+ }
+ }
+ else if( b == 255 )
+ {
+ possibleChunk = ETrue;
+ }
+
+ }
+
+ PrepareLoadBlockL();
+ }
+
+
+
+void CJpeg::PrepareLoadBlockL()
+ {
+ if( iLoadBlockPrepared )
+ {
+ return;
+ }
+
+ // prepare rgb block bitmap
+ iBm.iSize = iData.iBlockSize;
+ iBm.iDrawRect = iBm.iSize;
+ iBlkPixels = iData.iBlockSize.iWidth * iData.iBlockSize.iHeight;
+ iBm.iData = NULL;
+ iBm.iType = E16MColor;
+
+
+ // prepare yuv buffers
+ iC[ 0 ] = new( ELeave )TUint8[ 64 * iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor ];
+ iC[ 1 ] = new( ELeave )TUint8[ 64 * iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor ];
+ iC[ 2 ] = new( ELeave )TUint8[ 64 * iComponent[ 2 ].iXFactor * iComponent[ 2 ].iYFactor ];
+
+ // prepare yuv->rgb scale
+ TInt bw = iBm.iSize.iWidth;
+ TInt bh = iBm.iSize.iHeight;
+ iYxa = 256 * ( 8 * iComponent[ 0 ].iXFactor ) / bw;
+ iYya = 256 * ( 8 * iComponent[ 0 ].iYFactor ) / bh;
+ iUxa = 256 * ( 8 * iComponent[ 1 ].iXFactor ) / bw;
+ iUya = 256 * ( 8 * iComponent[ 1 ].iYFactor ) / bh;
+ iVxa = 256 * ( 8 * iComponent[ 2 ].iXFactor ) / bw;
+ iVya = 256 * ( 8 * iComponent[ 2 ].iYFactor ) / bh;
+
+ //
+ // Select YUV -> RGB function
+ //
+ iYuv2rgbFunc = Yuv2RgbFree; // default, handles all combinations
+
+ if( iComponent[ 0 ].iXFactor == 2 && iComponent[ 0 ].iYFactor == 1 &&
+ iComponent[ 1 ].iXFactor == 1 && iComponent[ 1 ].iYFactor == 1 &&
+ iComponent[ 2 ].iXFactor == 1 && iComponent[ 2 ].iYFactor == 1 )
+ {
+ iYuv2rgbFunc = Yuv2Rgb21_11_11;
+ }
+ else if( iComponent[ 0 ].iXFactor == 2 && iComponent[ 0 ].iYFactor == 2 &&
+ iComponent[ 1 ].iXFactor == 1 && iComponent[ 1 ].iYFactor == 1 &&
+ iComponent[ 2 ].iXFactor == 1 && iComponent[ 2 ].iYFactor == 1 )
+ {
+ iYuv2rgbFunc = Yuv2Rgb22_11_11;
+ }
+
+ iLoadBlockPrepared = true;
+ }
+
+
+
+void CJpeg::ScanRandomL()
+ {
+ if( iRandomScanned )
+ {
+ return;
+ }
+ //
+ // Set file read position
+ //
+ iBufPos = iImageDataStart;
+ iBufBits = 0;
+ iBuf = 0;
+
+ //
+ // Reserve memory for random access tables
+ //
+ TInt numBlocks = iData.iSizeInBlocks.iWidth * iData.iSizeInBlocks.iHeight;
+ iBlock = new( ELeave )TJpegBlock[ numBlocks ];
+
+
+ TInt bw = iData.iSizeInBlocks.iWidth;
+ TInt bh = iData.iSizeInBlocks.iHeight;
+
+ TInt bx;
+ TInt by;
+
+ TInt c1 = 0;
+ TInt c2 = 0;
+ TInt c3 = 0;
+
+ //TInt blockNum = 0;
+
+ for( by=0; by<bh; by++ )
+ {
+ ////RDebug::Print( _L("Jpeg scan %d/%d"), by+1,bh );
+
+ for( bx=0; bx<bw; bx++ )
+ {
+
+ if( iRst )
+ {
+ iRst = false;
+ iBuf = 0;
+ iBufBits = 0;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ }
+
+ // store information for every block
+ TJpegBlock& block = iBlock[ iNumBlocks++ ];
+
+ block.iY = c1;
+ block.iU = c2;
+ block.iV = c3;
+ block.iOffset = iBufPos;
+ block.iBuf = iBuf;
+ block.iBufBits = iBufBits;
+
+ //iBlock.Append( block );
+
+ TInt i;
+
+ // go fast trough all huffman data
+ iCurrentHuffman = 0;
+ iCurrentQt = iQt[ 0 ];
+
+ // Y-component
+ TInt n = iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor;
+ iDct[ 0 ] = c1;
+ for( i=0; i<n; i++ )
+ {
+ DecodeBlock();
+ }
+ c1 = iDct[ 0 ];
+
+ iCurrentHuffman = 1;
+ iCurrentQt = iQt[ 1 ];
+
+ // U-component
+ n = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
+ iDct[ 0 ] = c2;
+ for( i=0; i<n; i++ )
+ {
+ DecodeBlock();
+ }
+ c2 = iDct[ 0 ];
+
+ // V-component
+ n = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
+ iDct[ 0 ] = c3;
+ for( i=0; i<n; i++ )
+ {
+ DecodeBlock();
+ }
+ c3 = iDct[ 0 ];
+
+ }
+ }
+
+ iRandomScanned = true;
+
+ }
+
+
+
+TBitmapHandle CJpeg::LoadBlockL( const TPoint& aBlock )
+ {
+ TBitmapHandle bm = iBm;
+ bm.iData = new( ELeave )TUint32[ iBlkPixels ];
+ CleanupStack::PushL(bm.iData);
+ TUint32* rgb = (TUint32*) bm.iData;
+
+ TInt blkNum = aBlock.iX + aBlock.iY * iData.iSizeInBlocks.iWidth;
+
+ if( aBlock.iX < 0 || aBlock.iX >= iData.iSizeInBlocks.iWidth )
+ {
+ blkNum = -1;
+ }
+ //if( blkNum < 0 || blkNum >= iBlock.Count() )
+ if( blkNum < 0 || blkNum >= iNumBlocks )
+ {
+ Mem::FillZ( bm.iData, iBlkPixels * sizeof( TUint32 ) );
+ return bm;
+ }
+
+ TJpegBlock& blk = iBlock[ blkNum ];
+
+ iBuf = blk.iBuf;
+ iBufBits = blk.iBufBits;
+ iBufPos = blk.iOffset;
+
+ //
+ // Decode block
+ //
+
+ TInt c1 = blk.iY;
+ TInt c2 = blk.iU;
+ TInt c3 = blk.iV;
+
+
+ ///////////
+ TInt x;
+ TInt y;
+ TInt xx;
+ TInt yy;
+ TInt w;
+ TInt* p;
+
+ // Y-component
+ iCurrentHuffman = 0;
+ iCurrentQt = iQt[ 0 ];
+ xx = iComponent[ 0 ].iXFactor;
+ yy = iComponent[ 0 ].iYFactor;
+ w = xx * 8;
+ p = iBlk;
+ iDct[ 0 ] = c1;
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ DecodeBlock2();
+ TUint8* tp = iC[ 0 ] + x*8 + y * 8 * w;
+ p = iBlk;
+
+ for( TInt ty=0; ty<8; ty++ )
+ {
+ for( TInt tx=0; tx<8; tx++ )
+ {
+ tp[ tx + ty * w ] = *p++;
+ }
+ }
+ }
+ }
+
+
+ // U-component
+ iCurrentHuffman = 1;
+ iCurrentQt = iQt[ 1 ];
+ xx = iComponent[ 1 ].iXFactor;
+ yy = iComponent[ 1 ].iYFactor;
+ w = xx * 8;
+ p = iBlk;
+ iDct[ 0 ] = c2;
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ DecodeBlock2();
+ TUint8* tp = iC[ 1 ] + x*8 + y * 8 * w;
+ p = iBlk;
+
+ for( TInt ty=0; ty<8; ty++ )
+ {
+ for( TInt tx=0; tx<8; tx++ )
+ {
+ tp[ tx + ty * w ] = *p++;
+ }
+ }
+ }
+ }
+
+ // V-component
+ iCurrentHuffman = 1;
+ iCurrentQt = iQt[ 1 ];
+ xx = iComponent[ 2 ].iXFactor;
+ yy = iComponent[ 2 ].iYFactor;
+ w = xx * 8;
+ iDct[ 0 ] = c3;
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ DecodeBlock2();
+ TUint8* tp = iC[ 2 ] + x*8 + y * 8 * w;
+
+ p = iBlk;
+ for( TInt ty=0; ty<8; ty++ )
+ {
+ for( TInt tx=0; tx<8; tx++ )
+ {
+ tp[ tx + ty * w ] = *p++;
+ }
+ }
+ }
+ }
+ ///////////
+
+ //
+ // Scaled blit YUV->RGB
+ //
+
+ TInt bw = bm.iSize.iWidth;
+ TInt bh = bm.iSize.iHeight;
+
+
+ TInt y1y = 0;
+ TInt y1u = 0;
+ TInt y1v = 0;
+
+ TInt yw = iComponent[ 0 ].iXFactor * 8;
+ TInt uw = iComponent[ 1 ].iXFactor * 8;
+ TInt vw = iComponent[ 2 ].iXFactor * 8;
+
+ TUint32* prgb = rgb;
+ for( y=0; y<bh; y++ )
+ {
+ TInt txy = 0;
+ TInt txu = 0;
+ TInt txv = 0;
+ TUint8* ccy = iC[ 0 ] + ( y1y/256 ) * yw;
+ TUint8* ccu = iC[ 1 ] + ( y1u/256 ) * uw;
+ TUint8* ccv = iC[ 2 ] + ( y1v/256 ) * vw;
+
+ for( x=0; x<bw; x++ )
+ {
+
+ TInt cy = ccy[ txy / 256 ];
+ TInt cu = ccu[ txu / 256 ] - 128;
+ TInt cv = ccv[ txv / 256 ] - 128;
+
+ txy += iYxa;
+ txu += iUxa;
+ txv += iVxa;
+
+ TInt cr = cy + ( 91881 * cv ) / 65536;
+ TInt cg = cy - ( 22554 * cu + 46802 * cv ) / 65536;
+ TInt cb = cy + ( 116130 * cu ) / 65536;
+
+ if( cr < 0 ) cr = 0;
+ if( cg < 0 ) cg = 0;
+ if( cb < 0 ) cb = 0;
+ if( cr > 255 ) cr = 255;
+ if( cg > 255 ) cg = 255;
+ if( cb > 255 ) cb = 255;
+
+ //rgb[ x + y * bw ] = cr * 65536 + cg * 256 + cb;
+ *prgb++ = cr * 65536 + cg * 256 + cb;
+ }
+ y1y += iYya;
+ y1u += iUya;
+ y1v += iVya;
+ }
+
+ CleanupStack::Pop();
+ return bm;
+ }
+
+
+
+
+void CJpeg::DecodeBlock()
+ {
+ // //RDebug::Print( _L("DecodeBlock()") );
+ //
+ // Dummy version of block decode
+ // only traverses through huffman data
+ // and collects DC-values
+ //
+ THuffman* h = iHuffman[ iCurrentHuffman ];
+
+ TInt k;
+ for( k=0; k<64; k++ )
+ {
+ TInt v = Buf16();
+ TInt index = h->iSearch[ v ];
+ TInt symbol = h->iSymbol[ index ];
+ BufFwd( h->iLength[ index ] );
+
+ TInt nullCount = 0;
+ if( k>0 )
+ {
+ nullCount = symbol >> 4;
+ symbol &= 15;
+ }
+
+ v = BufBits( symbol );
+ if( v < ( 1 << ( symbol-1 ) ) )
+ {
+ v += 1 - ( 1 << symbol );
+ }
+
+ if( k )
+ {
+ if( nullCount==0 && v==0 )
+ {
+ k = 64;
+ break;
+ }
+ else if( nullCount==15 && v==0 )
+ {
+ k += 15;
+ }
+ else
+ {
+ k += nullCount;
+ }
+ }
+ else
+ {
+ iDct[ 0 ] += v * iCurrentQt[ 0 ];
+ h = iHuffman[ iCurrentHuffman+2 ];
+ }
+ }
+ }
+
+
+
+void CJpeg::DecodeBlock2()
+ {
+ //
+ // Real block decoder
+ // fills iDct table and calls Idct() function
+ //
+ THuffman* h = iHuffman[ iCurrentHuffman ];
+
+ TInt k;
+
+ for( k=1; k<64; k++ )
+ {
+ iDct[ k ] = 0;
+ }
+
+ for( k=0; k<64; k++ )
+ {
+ TInt v = Buf16();
+ TInt index = h->iSearch[ v ];
+ TInt symbol = h->iSymbol[ index ];
+ BufFwd( h->iLength[ index ] );
+
+ TInt nullCount = 0;
+ if( k>0 )
+ {
+ nullCount = symbol >> 4;
+ symbol &= 15;
+ }
+
+ v = BufBits( symbol );
+
+ if( v < ( 1 << ( symbol-1 ) ) )
+ {
+ v += 1 - ( 1 << symbol );
+ }
+
+ if( k )
+ {
+ if( nullCount==0 && v==0 )
+ {
+ k = 64;
+ break;
+ }
+ else if( nullCount==15 && v==0 )
+ {
+ k += 15;
+ }
+ else
+ {
+ k += nullCount;
+ iDct[ KZigZag[ k ] ] = v * iCurrentQt[ k ];
+ }
+ }
+ else
+ {
+ iDct[ 0 ] += v * iCurrentQt[ 0 ];
+ h = iHuffman[ iCurrentHuffman+2 ];
+ }
+
+ }
+ Idct();
+ }
+
+
+
+void CJpeg::DecodeBlock3()
+ {
+ //
+ // Real block decoder
+ // fills iDct table and calls Idct() function
+ //
+ THuffman* h = iHuffman[ iCurrentHuffman ];
+
+ TInt k;
+
+ for( k=1; k<64; k++ )
+ {
+ iDct[ k ] = 0;
+ }
+
+ for( k=0; k<64; k++ )
+ {
+ TInt v = Buf16();
+ TInt index = h->iSearch[ v ];
+ TInt symbol = h->iSymbol[ index ];
+ BufFwd( h->iLength[ index ] );
+
+ TInt nullCount = 0;
+ if( k>0 )
+ {
+ nullCount = symbol >> 4;
+ symbol &= 15;
+ }
+
+ v = BufBits( symbol );
+
+ if( v < ( 1 << ( symbol-1 ) ) )
+ {
+ v += 1 - ( 1 << symbol );
+ }
+
+ if( k )
+ {
+ if( nullCount==0 && v==0 )
+ {
+ k = 64;
+ break;
+ }
+ else if( nullCount==15 && v==0 )
+ {
+ k += 15;
+ }
+ else
+ {
+ k += nullCount;
+ iDct[ KZigZag[ k ] ] = v * iCurrentQt[ k ];
+ }
+ }
+ else
+ {
+ iDct[ 0 ] += v * iCurrentQt[ 0 ];
+ h = iHuffman[ iCurrentHuffman+2 ];
+ }
+
+ }
+ }
+
+
+
+
+void CJpeg::Idct()
+ {
+ TInt even[ 4 ];
+ TInt odd[ 4 ];
+ TInt res[ 64 ];
+
+ TInt* p = iDct;
+
+ for( TInt x=0; x<8; x++ )
+ {
+ TInt x0 = *p++;
+ TInt x1 = *p++;
+ TInt x2 = *p++;
+ TInt x3 = *p++;
+ TInt x4 = *p++;
+ TInt x5 = *p++;
+ TInt x6 = *p++;
+ TInt x7 = *p++;
+
+ TInt tx0 = x0;
+ x0 = (x0 + x4) * 181;
+ x4 = (tx0 - x4) * 181;
+
+ TInt tx2 = x2;
+ TInt tx6 = x6;
+ x2 = tx2 * 236 + tx6 * 98;
+ x6 = tx2 * 98 - tx6 * 236;
+
+ even[0] = x0 + x2;
+ even[1] = x4 + x6;
+ even[2] = x4 - x6;
+ even[3] = x0 - x2;
+
+ odd[0] = x1 * 251 + x5 * 142 + x3 * 212 + x7 * 49;
+ odd[1] = x1 * 213 - x5 * 251 - x3 * 50 - x7 * 142;
+ odd[2] = x1 * 142 + x5 * 50 - x3 * 251 + x7 * 213;
+ odd[3] = x1 * 50 + x5 * 213 - x3 * 142 - x7 * 251;
+
+ res[x + 0] = even[0] + odd[0];
+ res[x + 8] = even[1] + odd[1];
+ res[x + 16] = even[2] + odd[2];
+ res[x + 24] = even[3] + odd[3];
+ res[x + 32] = even[3] - odd[3];
+ res[x + 40] = even[2] - odd[2];
+ res[x + 48] = even[1] - odd[1];
+ res[x + 56] = even[0] - odd[0];
+ }
+
+ p = res;
+ TInt* tp = iBlk;
+
+ for( TInt y=0; y<8; y++ )
+ {
+ TInt x0 = *p++;
+ TInt x1 = *p++;
+ TInt x2 = *p++;
+ TInt x3 = *p++;
+ TInt x4 = *p++;
+ TInt x5 = *p++;
+ TInt x6 = *p++;
+ TInt x7 = *p++;
+
+ TInt tx0 = x0;
+ x0 = (x0 + x4) * 181;
+ x4 = (tx0 - x4) * 181;
+
+ TInt tx2 = x2;
+ TInt tx6 = x6;
+ x2 = tx2 * 236 + tx6 * 98;
+ x6 = tx2 * 98 - tx6 * 236;
+
+ even[0] = x0 + x2;
+ even[1] = x4 + x6;
+ even[2] = x4 - x6;
+ even[3] = x0 - x2;
+
+ odd[0] = x1 * 251 + x5 * 142 + x3 * 212 + x7 * 49;
+ odd[1] = x1 * 213 - x5 * 251 - x3 * 50 - x7 * 142;
+ odd[2] = x1 * 142 + x5 * 50 - x3 * 251 + x7 * 213;
+ odd[3] = x1 * 50 + x5 * 213 - x3 * 142 - x7 * 251;
+
+ *tp++ = (even[0] + odd[0]) / 262144 + 128;
+ *tp++ = (even[1] + odd[1]) / 262144 + 128;
+ *tp++ = (even[2] + odd[2]) / 262144 + 128;
+ *tp++ = (even[3] + odd[3]) / 262144 + 128;
+ *tp++ = (even[3] - odd[3]) / 262144 + 128;
+ *tp++ = (even[2] - odd[2]) / 262144 + 128;
+ *tp++ = (even[1] - odd[1]) / 262144 + 128;
+ *tp++ = (even[0] - odd[0]) / 262144 + 128;
+ }
+
+ //
+ // Clamp
+ //
+ tp = iBlk;
+ TInt* tpe = tp + 64;
+ while( tp < tpe )
+ {
+ if( *tp < 0 ) *tp = 0;
+ if( *tp > 255 ) *tp = 255;
+ tp++;
+ }
+ }
+
+
+
+void CJpeg::IdctHalf()
+ {
+ TInt even[ 4 ];
+ TInt odd[ 4 ];
+ TInt res[ 64 ];
+
+ TInt* p = iDct;
+
+ for( TInt x=0; x<4; x++ )
+ {
+ TInt x0 = *p++;
+ TInt x1 = *p++;
+ TInt x2 = *p++;
+ TInt x3 = *p++;
+ p += 4;
+
+ x0 = x0 * 181;
+
+ TInt x6 = x2 * 98;
+ x2 = x2 * 236;
+
+ even[0] = x0 + x2;
+ even[1] = x0 + x6;
+ even[2] = x0 - x6;
+ even[3] = x0 - x2;
+
+ odd[0] = x1 * 251 + x3 * 212;
+ odd[1] = x1 * 213 - x3 * 50;
+ odd[2] = x1 * 142 - x3 * 251;
+ odd[3] = x1 * 50 - x3 * 142;
+
+ res[x + 0] = even[0] + odd[0];
+ res[x + 4] = even[2] + odd[2];
+ res[x + 8] = even[3] - odd[3];
+ res[x + 12] = even[1] - odd[1];
+ }
+
+ p = res;
+ TInt* tp = iBlk;
+
+ for( TInt y=0; y<4; y++ )
+ {
+ TInt x0 = *p++;
+ TInt x1 = *p++;
+ TInt x2 = *p++;
+ TInt x3 = *p++;
+
+ x0 = x0 * 181;
+
+ TInt x6 = x2 * 98;
+ x2 = x2 * 236;
+
+ even[0] = x0 + x2;
+ even[1] = x0 + x6;
+ even[2] = x0 - x6;
+ even[3] = x0 - x2;
+
+ odd[0] = x1 * 251 + x3 * 212;
+ odd[1] = x1 * 213 - x3 * 50;
+ odd[2] = x1 * 142 - x3 * 251;
+ odd[3] = x1 * 50 - x3 * 142;
+
+ *tp++ = (even[0] + odd[0]) / 262144 + 128;
+ *tp++ = (even[2] + odd[2]) / 262144 + 128;
+ *tp++ = (even[3] - odd[3]) / 262144 + 128;
+ *tp++ = (even[1] - odd[1]) / 262144 + 128;
+ }
+
+ //
+ // Clamp
+ //
+ tp = iBlk;
+ TInt* tpe = tp + 16;
+ while( tp < tpe )
+ {
+ if( *tp < 0 ) *tp = 0;
+ if( *tp > 255 ) *tp = 255;
+ tp++;
+ }
+ }
+
+
+
+
+const TJpegData& CJpeg::Info()
+ {
+ return iData;
+ }
+
+
+TPtrC8 CJpeg::ExifData()
+ {
+ return TPtrC8( iExifData, iExifDataLength );
+ }
+
+
+
+void CJpeg::CreateHuffmanL( THuffman* aHuffman, const TUint8* aBits, const TUint8* aVal )
+ {
+ //
+ // default huffman lookup table generator
+ //
+
+ TInt huffSize[ 16 ];
+ TInt numSymbols = 0;
+ TInt i;
+
+ for( i=0; i<16; i++ )
+ {
+ TInt size = aBits[ i+1 ];
+ huffSize[ i ] = size;
+ numSymbols += size;
+ }
+
+ for( i=0; i<numSymbols; i++ )
+ {
+ aHuffman->iSymbol[ i ] = aVal[ i ];
+ }
+
+ TInt l;
+ TInt p = 0;
+ for( l=0; l<16; l++ )
+ {
+ for( i=0; i<huffSize[ l ]; i++ )
+ {
+ aHuffman->iLength[ p++ ] = l+1;
+ }
+ }
+
+ TInt code = 0;
+ aHuffman->iLength[ p ] = 0;
+ TInt si = aHuffman->iLength[ 0 ];
+ TInt lastP = p;
+
+ TInt hc[ 256 ];
+ p = 0;
+
+ while( aHuffman->iLength[ p ] )
+ {
+ while( aHuffman->iLength[ p ] == si )
+ {
+ hc[ p++ ] = code++;
+ }
+ code *= 2;
+ si++;
+ }
+
+ l = 65536;
+ for( i=lastP-1; i>=0; i-- )
+ {
+ TInt t = 16 - aHuffman->iLength[ i ];
+ TInt k = hc[ i ] * ( 1 << t );
+ TInt j;
+ for( j=k; j<l; j++ )
+ {
+ aHuffman->iSearch[ j ] = i;
+ }
+ l = k;
+ }
+
+ }
+
+
+
+void CJpeg::CreateDefaultHuffmanL()
+ {
+ //
+ // Creates default huffman tables
+ // needed if jpeg file doesn't have huffman tables
+ // for example motion jpeg file doesn't have.
+ //
+ THuffman* huff = new( ELeave )THuffman;
+ CleanupStack::PushL( huff );
+ CreateHuffmanL( huff, bits_dc_luminance, val_dc_luminance );
+ iHuffman[ 0 ] = huff;
+ CleanupStack::Pop( huff );
+
+ huff = new( ELeave )THuffman;
+ CleanupStack::PushL( huff );
+ CreateHuffmanL( huff, bits_dc_chrominance, val_dc_chrominance );
+ iHuffman[ 1 ] = huff;
+ CleanupStack::Pop( huff );
+
+ huff = new( ELeave )THuffman;
+ CleanupStack::PushL( huff );
+ CreateHuffmanL( huff, bits_ac_luminance, val_ac_luminance );
+ iHuffman[ 2 ] = huff;
+ CleanupStack::Pop( huff );
+
+ huff = new( ELeave )THuffman;
+ CleanupStack::PushL( huff );
+ CreateHuffmanL( huff, bits_ac_chrominance, val_ac_chrominance );
+ iHuffman[ 3 ] = huff;
+ CleanupStack::Pop( huff );
+ }
+
+
+
+void CJpeg::DecRgb1_1L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
+ {
+ PrepareLoadBlockL();
+
+ //
+ // Set file read position
+ //
+ iBufPos = iImageDataStart;
+ iBufBits = 0;
+ iBuf = 0;
+
+ TInt c[ 3 ];
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+
+ TInt w = aBitmap.iSize.iWidth;
+ TUint32* rgb = (TUint32*)aBitmap.iData;
+
+ //
+ // Store data for yuv->rgb conversion
+ //
+ iYuvConv.iBlkSize = iData.iBlockSize;
+ iYuvConv.iRgbWidth = w;
+ iYuvConv.iBlkPixels = 8;
+
+ TInt blw = aBlockRect.Size().iWidth;
+ TInt blh = aBlockRect.Size().iHeight;
+
+ for( TInt by=0; by<blh; by++ )
+ {
+
+ if( iRandomScanned )
+ {
+ TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
+ TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
+ TJpegBlock& blk = iBlock[ blkNum ];
+
+ iBuf = blk.iBuf;
+ iBufBits = blk.iBufBits;
+ iBufPos = blk.iOffset;
+ c[ 0 ] = blk.iY;
+ c[ 1 ] = blk.iU;
+ c[ 2 ] = blk.iV;
+ iRst = false;
+ }
+
+ //TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
+
+ for( TInt bx=0; bx<blw; bx++ )
+ {
+ iYuvConv.iRgb = rgb + bx * iData.iBlockSize.iWidth;
+ iYuvConv.iRgb += by * iData.iBlockSize.iHeight * w;
+
+ if( iRst )
+ {
+ iRst = false;
+ iBuf = 0;
+ iBufBits = 0;
+
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+ }
+ //blockNum++;
+
+
+ TInt xx;
+ TInt yy;
+ TInt* p;
+
+ for( TInt i=0; i<iNumComponents; i++ )
+ {
+ iCurrentQt = iQt[ KQuantIndex[ i ] ];
+ xx = iComponent[ i ].iXFactor;
+ yy = iComponent[ i ].iYFactor;
+ TInt dw = xx * 8;
+ p = iBlk;
+ iDct[ 0 ] = c[ i ];
+
+ for( TInt y=0; y<yy; y++ )
+ {
+ for( TInt x=0; x<xx; x++ )
+ {
+ iCurrentHuffman = KHuffIndex[ i ];
+ DecodeBlock3();
+ Idct();
+ TUint8* tp = iC[ i ] + x*8 + y*8 * dw;
+ p = iBlk;
+
+ for( TInt ty=0; ty<8; ty++ )
+ {
+ for( TInt tx=0; tx<8; tx++ )
+ {
+ tp[ tx + ty * dw ] = *p++;
+ }
+ }
+ }
+ }
+ c[ i ] = iDct[ 0 ];
+ }
+
+ //
+ // Scaled blit YUV->RGB
+ //
+ if( iRgbConv )
+ {
+ iYuv2rgbFunc( this );
+ }
+
+ }
+ }
+ }
+
+
+
+
+void CJpeg::DecRgb1_2L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
+ {
+ PrepareLoadBlockL();
+
+ //
+ // Set file read position
+ //
+ iBufPos = iImageDataStart;
+ iBufBits = 0;
+ iBuf = 0;
+
+ TInt c[ 3 ];
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+
+ TInt w = aBitmap.iSize.iWidth;
+ TUint32* rgb = (TUint32*)aBitmap.iData;
+
+ TInt bw = iData.iBlockSize.iWidth / 2;
+ TInt bh = iData.iBlockSize.iHeight / 2;
+ //
+ // Store data for yuv->rgb conversion
+ //
+ iYuvConv.iBlkSize = TSize( bw, bh );
+ iYuvConv.iRgbWidth = w;
+ iYuvConv.iBlkPixels = 4;
+
+ TInt blw = aBlockRect.Size().iWidth;
+ TInt blh = aBlockRect.Size().iHeight;
+
+ for( TInt by=0; by<blh; by++ )
+ {
+
+ if( iRandomScanned )
+ {
+ TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
+ TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
+ TJpegBlock& blk = iBlock[ blkNum ];
+
+ iBuf = blk.iBuf;
+ iBufBits = blk.iBufBits;
+ iBufPos = blk.iOffset;
+ c[ 0 ] = blk.iY;
+ c[ 1 ] = blk.iU;
+ c[ 2 ] = blk.iV;
+ iRst = false;
+ }
+
+ //TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
+
+ for( TInt bx=0; bx<blw; bx++ )
+ {
+ iYuvConv.iRgb = rgb + bx * bw;
+ iYuvConv.iRgb += by * bh * w;
+
+ if( iRst )
+ {
+ iRst = false;
+ iBuf = 0;
+ iBufBits = 0;
+
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+ }
+ //blockNum++;
+
+
+
+ ///////////
+ TInt x;
+ TInt y;
+ TInt xx;
+ TInt yy;
+ TInt* p;
+
+ for( TInt i=0; i<iNumComponents; i++ )
+ {
+ iCurrentQt = iQt[ KQuantIndex[ i ] ];
+ xx = iComponent[ i ].iXFactor;
+ yy = iComponent[ i ].iYFactor;
+ TInt dw = xx * 4;
+ p = iBlk;
+ iDct[ 0 ] = c[ i ];
+
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ iCurrentHuffman = KHuffIndex[ i ];
+ DecodeBlock3();
+ TUint8* tp = iC[ i ] + x*4 + y*4 * dw;
+
+ //
+ // 4x4 Idct
+ //
+ IdctHalf();
+
+ for( TInt ty=0; ty<4; ty++ )
+ {
+ for( TInt tx=0; tx<4; tx++ )
+ {
+ tp[ tx + ty * dw ] = p[ tx + ty*4 ];
+ }
+ }
+ }
+ }
+
+
+ c[ i ] = iDct[ 0 ];
+ }
+
+ //
+ // Scaled blit YUV->RGB
+ //
+ if( iRgbConv )
+ {
+ iYuv2rgbFunc( this );
+ }
+
+
+ }
+ }
+ }
+
+
+
+void CJpeg::DecRgb1_4L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
+ {
+ PrepareLoadBlockL();
+
+ //
+ // Set file read position
+ //
+ iBufPos = iImageDataStart;
+ iBufBits = 0;
+ iBuf = 0;
+
+ TInt c[ 3 ];
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+
+ TInt w = aBitmap.iSize.iWidth;
+ TUint32* rgb = (TUint32*)aBitmap.iData;
+
+ TInt bw = iData.iBlockSize.iWidth / 4;
+ TInt bh = iData.iBlockSize.iHeight / 4;
+ //
+ // Store data for yuv->rgb conversion
+ //
+ iYuvConv.iBlkSize = TSize( bw, bh );
+ iYuvConv.iRgbWidth = w;
+ iYuvConv.iBlkPixels = 2;
+
+ TInt blw = aBlockRect.Size().iWidth;
+ TInt blh = aBlockRect.Size().iHeight;
+
+ for( TInt by=0; by<blh; by++ )
+ {
+
+ if( iRandomScanned )
+ {
+ TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
+ TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
+ TJpegBlock& blk = iBlock[ blkNum ];
+
+ iBuf = blk.iBuf;
+ iBufBits = blk.iBufBits;
+ iBufPos = blk.iOffset;
+ c[ 0 ] = blk.iY;
+ c[ 1 ] = blk.iU;
+ c[ 2 ] = blk.iV;
+ iRst = false;
+ }
+
+ //TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
+
+ for( TInt bx=0; bx<blw; bx++ )
+ {
+ iYuvConv.iRgb = rgb + bx * bw;
+ iYuvConv.iRgb += by * bh * w;
+
+ if( iRst )
+ {
+ iRst = false;
+ iBuf = 0;
+ iBufBits = 0;
+
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+ }
+ //blockNum++;
+
+
+ TInt x;
+ TInt y;
+ TInt xx;
+ TInt yy;
+
+ for( TInt i=0; i<iNumComponents; i++ )
+ {
+ iCurrentQt = iQt[ KQuantIndex[ i ] ];
+ xx = iComponent[ i ].iXFactor;
+ yy = iComponent[ i ].iYFactor;
+ TInt dw = xx * 2;
+ iDct[ 0 ] = c[ i ];
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ iCurrentHuffman = KHuffIndex[ i ];
+ DecodeBlock3();
+ TUint8* tp = iC[ i ] + x*2 + y*2 * dw;
+
+ //
+ // 2x2 Idct
+ //
+ TInt v0 = 181*iDct[1];
+ TInt v1 = 32761 * iDct[ 0 ];
+ TInt v2 = 45431 * iDct[ 8 ];
+ TInt v3 = -9050 * iDct[ 8 ];
+ TInt v4 = v0 + 251*iDct[9];
+ TInt v5 = v0 - 50*iDct[9];
+
+ TInt v = (v1 + v2 + 251*v4 ) / 262144 + 128;
+ if( v<0 ) v=0; if( v>255 ) v=255; tp[ 0 ] = v;
+
+ v = (v1 + v2 - 50*v4 ) / 262144 + 128;
+ if( v<0 ) v=0; if( v>255 ) v=255; tp[ dw ] = v;
+
+ v = (v1 + v3 + 251*v5 ) / 262144 + 128;
+ if( v<0 ) v=0; if( v>255 ) v=255; tp[ 1 ] = v;
+
+ v = (v1 + v3 - 50*v5 ) / 262144 + 128;
+ if( v<0 ) v=0; if( v>255 ) v=255; tp[ dw+1 ] = v;
+ }
+ }
+ c[ i ] = iDct[ 0 ];
+ }
+
+
+ //
+ // Scaled blit YUV->RGB
+ //
+ if( iRgbConv )
+ {
+ iYuv2rgbFunc( this );
+ }
+
+
+ }
+ }
+ }
+
+
+
+void CJpeg::DecRgb1_8L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
+ {
+ PrepareLoadBlockL();
+
+ //
+ // Set file read position
+ //
+ iBufPos = iImageDataStart;
+ iBufBits = 0;
+ iBuf = 0;
+
+ TInt c[ 3 ];
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+
+ TInt w = aBitmap.iSize.iWidth;
+ TUint32* rgb = (TUint32*)aBitmap.iData;
+
+ TInt bw = iData.iBlockSize.iWidth / 8;
+ TInt bh = iData.iBlockSize.iHeight / 8;
+
+ //
+ // Store data for yuv->rgb conversion
+ //
+ iYuvConv.iBlkSize = TSize( bw, bh );
+ iYuvConv.iRgbWidth = w;
+ iYuvConv.iBlkPixels = 1;
+
+ TInt blw = aBlockRect.Size().iWidth;
+ TInt blh = aBlockRect.Size().iHeight;
+
+ for( TInt by=0; by<blh; by++ )
+ {
+
+ if( iRandomScanned )
+ {
+ TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
+ TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
+ TJpegBlock& blk = iBlock[ blkNum ];
+
+ iBuf = blk.iBuf;
+ iBufBits = blk.iBufBits;
+ iBufPos = blk.iOffset;
+ c[ 0 ] = blk.iY;
+ c[ 1 ] = blk.iU;
+ c[ 2 ] = blk.iV;
+ iRst = false;
+ }
+
+ //TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
+
+ for( TInt bx=0; bx<blw; bx++ )
+ {
+ iYuvConv.iRgb = rgb + bx * bw;
+ iYuvConv.iRgb += by * bh * w;
+
+ if( iRst )
+ {
+ iRst = false;
+ iBuf = 0;
+ iBufBits = 0;
+
+ c[ 0 ] = 0;
+ c[ 1 ] = 0;
+ c[ 2 ] = 0;
+ }
+ //blockNum++;
+
+
+ TInt x;
+ TInt y;
+ TInt xx;
+ TInt yy;
+
+ for( TInt i=0; i<iNumComponents; i++ )
+ {
+ iCurrentQt = iQt[ KQuantIndex[ i ] ];
+ xx = iComponent[ i ].iXFactor;
+ yy = iComponent[ i ].iYFactor;
+ TInt dw = xx * 1;
+ iDct[ 0 ] = c[ i ];
+
+ for( y=0; y<yy; y++ )
+ {
+ for( x=0; x<xx; x++ )
+ {
+ iCurrentHuffman = KHuffIndex[ i ];
+ DecodeBlock3();
+ TUint8* tp = iC[ i ] + x*1 + y*1 * dw;
+
+ *tp = iDct[ 0 ] / 8 + 128;
+ }
+ }
+ c[ i ] = iDct[ 0 ];
+ }
+
+ //
+ // Scaled blit YUV->RGB
+ //
+ if( iRgbConv )
+ {
+ iYuv2rgbFunc( this );
+ }
+
+ }
+ }
+ }
+
+
+
+void CJpeg::SetScale( TJpegScale aScale )
+ {
+ iScale = aScale;
+ }
+
+
+
+void CJpeg::Yuv2Rgb22_11_11( TAny* aPtr )
+ {
+ CJpeg& p = *(CJpeg*)aPtr;
+
+ //
+ // YUV420
+ //
+ // YY
+ // YY U V
+ //
+
+ TUint8* cY = p.iC[ 0 ];
+ TUint8* cU = p.iC[ 1 ];
+ TUint8* cV = p.iC[ 2 ];
+ TUint32* rgb = p.iYuvConv.iRgb;
+ TInt modulo = p.iYuvConv.iRgbWidth - p.iYuvConv.iBlkSize.iWidth;
+
+ TInt w = p.iYuvConv.iBlkSize.iWidth;
+ TInt h = p.iYuvConv.iBlkSize.iHeight;
+
+
+ for( TInt y=0; y<h; y++ )
+ {
+ TInt x = 0;
+ TInt cu = 0;
+ TInt cv = 0;
+ for( x=0; x<w; x++ )
+ {
+ TInt cy = *cY++;
+ if( ( x & 1 ) == 0 )
+ {
+ // when X even, fetch new color components
+ cu = *cU++ - 128;
+ cv = *cV++ - 128;
+ }
+
+
+ // urgb color
+ TUint32 c;
+
+ // rgb color component
+ TInt cc;
+
+ // add red
+ cc = cy + ( 359 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c = cc << 16;
+
+ // add green
+ cc = cy - ( 88 * cu + 183 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c |= cc << 8;
+
+ // add blue
+ cc = cy + ( 454 * cu ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+
+ // write to bitmap
+ *rgb++ = c + cc;
+
+ }
+ rgb += modulo;
+ if( ( y & 1 ) == 0 )
+ {
+ // only advance color components on odd Y
+ // so on even, do rewind
+ cU -= x/2;
+ cV -= x/2;
+ }
+ }
+ }
+
+
+
+void CJpeg::Yuv2Rgb21_11_11( TAny* aPtr )
+ {
+ CJpeg& p = *(CJpeg*)aPtr;
+ //
+ // YUV422
+ //
+ // YY U V
+ //
+
+ TUint8* cY = p.iC[ 0 ];
+ TUint8* cU = p.iC[ 1 ];
+ TUint8* cV = p.iC[ 2 ];
+ TUint32* rgb = p.iYuvConv.iRgb;
+ TInt modulo = p.iYuvConv.iRgbWidth - p.iYuvConv.iBlkSize.iWidth;
+
+ TInt w = p.iYuvConv.iBlkSize.iWidth;
+ TInt h = p.iYuvConv.iBlkSize.iHeight;
+
+ for( TInt y=0; y<h; y++ )
+ {
+ TInt cu = 0;
+ TInt cv = 0;
+ for( TInt x=0; x<w; x++ )
+ {
+ TInt cy = *cY++;
+ if( ( x & 1 ) == 0 )
+ {
+ // for every even X, fetch new color components
+ cu = *cU++ - 128;
+ cv = *cV++ - 128;
+ }
+
+ // urgb color
+ TUint32 c;
+
+ // rgb color component
+ TInt cc;
+
+ // add red
+ cc = cy + ( 359 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c = cc << 16;
+
+ // add green
+ cc = cy - ( 88 * cu + 183 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c |= cc << 8;
+
+ // add blue
+ cc = cy + ( 454 * cu ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+
+ // write to bitmap
+ *rgb++ = c + cc;
+ }
+ rgb += modulo;
+ }
+ }
+
+
+
+void CJpeg::Yuv2RgbFree( TAny* aPtr )
+ {
+ CJpeg& p = *(CJpeg*)aPtr;
+
+ TInt bw = p.iYuvConv.iBlkSize.iWidth;
+ TInt bh = p.iYuvConv.iBlkSize.iHeight;
+
+ TInt y1y = 0;
+ TInt y1u = 0;
+ TInt y1v = 0;
+
+ TInt yw = p.iComponent[ 0 ].iXFactor * p.iYuvConv.iBlkPixels;
+ TInt uw = p.iComponent[ 1 ].iXFactor * p.iYuvConv.iBlkPixels;
+ TInt vw = p.iComponent[ 2 ].iXFactor * p.iYuvConv.iBlkPixels;
+
+ TUint32* rgb = p.iYuvConv.iRgb;
+ TInt modulo = p.iYuvConv.iRgbWidth - bw;
+
+ for( TInt y=0; y<bh; y++ )
+ {
+ TInt txy = 0;
+ TInt txu = 0;
+ TInt txv = 0;
+ TUint8* ccy = p.iC[ 0 ] + ( y1y/256 ) * yw;
+ TUint8* ccu = p.iC[ 1 ] + ( y1u/256 ) * uw;
+ TUint8* ccv = p.iC[ 2 ] + ( y1v/256 ) * vw;
+
+ for( TInt x=0; x<bw; x++ )
+ {
+
+ TInt cy = ccy[ txy / 256 ];
+ TInt cu = ccu[ txu / 256 ] - 128;
+ TInt cv = ccv[ txv / 256 ] - 128;
+
+ txy += p.iYxa;
+ txu += p.iUxa;
+ txv += p.iVxa;
+
+ // urgb color
+ TUint32 c;
+
+ // rgb color component
+ TInt cc;
+
+ // add red
+ cc = cy + ( 359 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c = cc << 16;
+
+ // add green
+ cc = cy - ( 88 * cu + 183 * cv ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+ c |= cc << 8;
+
+ // add blue
+ cc = cy + ( 454 * cu ) / 256;
+ if( cc < 0 ) cc = 0;
+ if( cc > 255 ) cc = 255;
+
+ // write to bitmap
+ *rgb++ = c + cc;
+ }
+ y1y += p.iYya;
+ y1u += p.iUya;
+ y1v += p.iVya;
+ rgb += modulo;
+ }
+ }
+
+
+
+
+void CJpeg::EnableRgvConv()
+ {
+ iRgbConv = true;
+ }
+
+
+
+void CJpeg::DisableRgbConv()
+ {
+ iRgbConv = false;
+ }
+
+
+
+TBitmapHandle CJpeg::LoadImageL( TRect& aRect )
+ {
+ //
+ // Crop possible illegal rect
+ //
+ //aRect.BoundingRect( TRect( iData.iSize ) );
+
+ if( aRect.iTl.iX < 0 ) aRect.iTl.iX = 0;
+ if( aRect.iTl.iY < 0 ) aRect.iTl.iY = 0;
+ if( aRect.iBr.iX < 0 ) aRect.iBr.iX = 0;
+ if( aRect.iBr.iY < 0 ) aRect.iBr.iY = 0;
+ if( aRect.iTl.iX > iData.iSize.iWidth ) aRect.iTl.iX = iData.iSize.iWidth;
+ if( aRect.iTl.iY > iData.iSize.iHeight ) aRect.iTl.iY = iData.iSize.iHeight;
+ if( aRect.iBr.iX > iData.iSize.iWidth ) aRect.iBr.iX = iData.iSize.iWidth;
+ if( aRect.iBr.iY > iData.iSize.iHeight ) aRect.iBr.iY = iData.iSize.iHeight;
+
+ //
+ // Create rectangle of blocks that has all the pixels of aRect
+ //
+ TRect blockRect = aRect;
+ blockRect.iTl.iX /= iData.iBlockSize.iWidth;
+ blockRect.iBr.iX /= iData.iBlockSize.iWidth;
+ blockRect.iTl.iY /= iData.iBlockSize.iHeight;
+ blockRect.iBr.iY /= iData.iBlockSize.iHeight;
+
+ if( aRect.iBr.iX & ( iData.iBlockSize.iWidth - 1 ) )
+ {
+ blockRect.iBr.iX++;
+ }
+
+ if( aRect.iBr.iY & ( iData.iBlockSize.iHeight - 1 ) )
+ {
+ blockRect.iBr.iY++;
+ }
+
+ //
+ // Return the real 1:1 scale pixel rectangle back in aRect
+ //
+ aRect.iTl.iX = blockRect.iTl.iX * iData.iBlockSize.iWidth;
+ aRect.iTl.iY = blockRect.iTl.iY * iData.iBlockSize.iHeight;
+ aRect.iBr.iX = blockRect.iBr.iX * iData.iBlockSize.iWidth;
+ aRect.iBr.iY = blockRect.iBr.iY * iData.iBlockSize.iHeight;
+
+
+ // decode area size in blocks
+ TSize blockSize = blockRect.Size();
+
+ // create bitmap
+ TBitmapHandle bm;
+ bm.iSize.iWidth = iData.iBlockSize.iWidth * blockSize.iWidth;
+ bm.iSize.iHeight = iData.iBlockSize.iHeight * blockSize.iHeight;
+
+ //
+ // If not whole image decode, random access must be initialized
+ //
+ if( iData.iSizeInBlocks != blockSize )
+ {
+ ScanRandomL();
+ }
+
+ //
+ // ...and decode
+ //
+ switch( iScale )
+ {
+ case EScale1:
+ {
+ bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
+ CleanupStack::PushL( bm.iData );
+ DecRgb1_1L( bm, blockRect );
+ CleanupStack::Pop( bm.iData );
+ break;
+ }
+ case EScale2:
+ {
+ bm.iSize.iWidth /= 2;
+ bm.iSize.iHeight /= 2;
+ bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
+ CleanupStack::PushL( bm.iData );
+ DecRgb1_2L( bm, blockRect );
+ CleanupStack::Pop( bm.iData );
+ break;
+ }
+ case EScale4:
+ {
+ bm.iSize.iWidth /= 4;
+ bm.iSize.iHeight /= 4;
+ bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
+ CleanupStack::PushL( bm.iData );
+ DecRgb1_4L( bm, blockRect );
+ CleanupStack::Pop( bm.iData );
+ break;
+ }
+ case EScale8:
+ {
+ bm.iSize.iWidth /= 8;
+ bm.iSize.iHeight /= 8;
+ bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
+ CleanupStack::PushL( bm.iData );
+ DecRgb1_8L( bm, blockRect );
+ CleanupStack::Pop( bm.iData );
+ break;
+ }
+ }
+
+ return bm;
+ }