imageeditorengine/src/CJpeg.cpp
changeset 1 edfc90759b9f
equal deleted inserted replaced
0:57d4cdd99204 1:edfc90759b9f
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "CJpeg.h"
       
    22 #include <e32svr.h>
       
    23 
       
    24 
       
    25 const TUint8 KQuantIndex[ 3 ] = { 0,1,1 };
       
    26 const TUint8 KHuffIndex[ 3 ] = { 0,1,1 };
       
    27 
       
    28 
       
    29 
       
    30 
       
    31 const TUint8 KZigZag[] = {
       
    32 						 0, 8,   1,  2,  9, 16, 24, 17,
       
    33 						10, 3,   4, 11, 18, 25, 32, 40,
       
    34 						33, 26, 19, 12,  5,  6, 13, 20,
       
    35 						27, 34, 41, 48, 56, 49, 42, 35,
       
    36 						28, 21, 14,  7, 15, 22, 29, 36,
       
    37 						43, 50, 57, 58, 51, 44, 37, 30,
       
    38 						23, 31, 38, 45, 52, 59, 60, 53,
       
    39 						46, 39, 47, 54, 61, 62, 55, 63
       
    40 						};
       
    41 
       
    42 
       
    43 
       
    44 
       
    45 
       
    46 
       
    47 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
       
    48 /* IMPORTANT: these are only valid for 8-bit data precision! */
       
    49 
       
    50 const TUint8 bits_dc_luminance[17] =
       
    51 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
       
    52 const TUint8 val_dc_luminance[] =
       
    53 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    54 
       
    55 const TUint8 bits_dc_chrominance[17] =
       
    56 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
       
    57 const TUint8 val_dc_chrominance[] =
       
    58 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    59 
       
    60 const TUint8 bits_ac_luminance[17] =
       
    61 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
       
    62 const TUint8 val_ac_luminance[] =
       
    63 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
       
    64   0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
       
    65   0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
       
    66   0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
       
    67   0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
       
    68   0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
       
    69   0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
       
    70   0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
       
    71   0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
       
    72   0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
       
    73   0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
       
    74   0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
       
    75   0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
       
    76   0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
       
    77   0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
       
    78   0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
       
    79   0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
       
    80   0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
       
    81   0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
       
    82   0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
    83   0xf9, 0xfa 
       
    84 };
       
    85 
       
    86 const TUint8 bits_ac_chrominance[17] =
       
    87 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
       
    88 
       
    89 const TUint8 val_ac_chrominance[] =
       
    90 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
       
    91   0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
       
    92   0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
       
    93   0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
       
    94   0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
       
    95   0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
       
    96   0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
       
    97   0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
       
    98   0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
       
    99   0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
       
   100   0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
       
   101   0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
       
   102   0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
       
   103   0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
       
   104   0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
       
   105   0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
       
   106   0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
       
   107   0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
       
   108   0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
       
   109   0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
   110   0xf9, 0xfa 
       
   111 };
       
   112 
       
   113 const TUint8 KExifHeader[] = "Exif";
       
   114 
       
   115 class THuffman
       
   116 	{
       
   117 	public:
       
   118 		TInt8 iLength[ 256 ];
       
   119 		TUint8 iSymbol[ 256 ];
       
   120 		TUint8 iSearch[ 65536 ];
       
   121 	};
       
   122 
       
   123 
       
   124 CJpeg* CJpeg::NewL()
       
   125 	{
       
   126 	CJpeg* self = NewLC();
       
   127 	CleanupStack::Pop( self );
       
   128 	return self;
       
   129 	}
       
   130 
       
   131 
       
   132 CJpeg* CJpeg::NewLC()
       
   133 	{
       
   134 	CJpeg* self = new( ELeave )CJpeg();
       
   135 	CleanupStack::PushL( self );
       
   136 	self->ConstructL();
       
   137 	return self;
       
   138 	}
       
   139 
       
   140 
       
   141 CJpeg::~CJpeg()
       
   142 	{
       
   143 	delete iHuffman[ 0 ];
       
   144 	delete iHuffman[ 1 ];
       
   145 	delete iHuffman[ 2 ];
       
   146 	delete iHuffman[ 3 ];
       
   147 
       
   148 	delete iQt[ 0 ];
       
   149 	delete iQt[ 1 ];
       
   150 	delete iQt[ 2 ];
       
   151 	delete iQt[ 3 ];
       
   152 
       
   153 	iCurrentQt = NULL;
       
   154 	iExifData = NULL;
       
   155 
       
   156 	//iBlock.Reset();
       
   157 	delete iBlock;
       
   158 
       
   159 	delete iBuffer;
       
   160 	delete iC[ 0 ];
       
   161 	delete iC[ 1 ];
       
   162 	delete iC[ 2 ];
       
   163 
       
   164 	//iDebug.Close();
       
   165 	//iFs.Close();
       
   166 	}
       
   167 
       
   168 CJpeg::CJpeg()
       
   169 	{
       
   170 
       
   171 	}
       
   172 
       
   173 void CJpeg::ConstructL()
       
   174 	{
       
   175 	}
       
   176 
       
   177 
       
   178 
       
   179 
       
   180 void CJpeg::OpenL( const TFileName& aFile )
       
   181 	{
       
   182 	if (iBuffer)
       
   183 		{
       
   184 		delete iBuffer;
       
   185 		iBuffer = NULL;
       
   186 		}
       
   187 	
       
   188 	RFs fs;
       
   189 	User::LeaveIfError( fs.Connect() );
       
   190 	CleanupClosePushL( fs );
       
   191 	
       
   192 	RFile file;
       
   193 	TInt err = file.Open( fs, aFile, EFileRead | EFileShareReadersOnly );
       
   194 	if (KErrNone != err)
       
   195 		{
       
   196 		User::LeaveIfError( file.Open( fs, aFile, EFileRead | EFileShareAny ) );
       
   197 		}
       
   198 	CleanupClosePushL( file );
       
   199 	
       
   200 	TInt size;
       
   201 	file.Size( size );
       
   202 	iBuffer = new( ELeave )TUint8[ size + 2 ];
       
   203 	TPtr8 ptr( iBuffer, size );
       
   204 	file.Read( ptr );
       
   205 	
       
   206 	CleanupStack::PopAndDestroy( 2 ); // file, fs
       
   207 	OpenL( ptr );
       
   208 	}
       
   209 
       
   210 
       
   211 
       
   212 void CJpeg::OpenL( const TPtr8& aData )
       
   213 	{
       
   214 	//iFs.Connect();
       
   215 	//iDebug.Replace( iFs, _L("e:\\TestData\\jpdeb.txt"), EFileWrite );
       
   216 
       
   217 	EnableRgvConv();
       
   218 
       
   219 	iBuffer = (TUint8*)aData.Ptr();
       
   220 	
       
   221 	// if used again, all variables should be cleared
       
   222 	iBuf = 0;
       
   223 	iBufBits = 0;
       
   224 	
       
   225 	delete iHuffman[ 0 ];
       
   226 	delete iHuffman[ 1 ];
       
   227 	delete iHuffman[ 2 ];
       
   228 	delete iHuffman[ 3 ];
       
   229 	iHuffman[ 0 ] = 0;
       
   230 	iHuffman[ 1 ] = 0;
       
   231 	iHuffman[ 2 ] = 0;
       
   232 	iHuffman[ 3 ] = 0;
       
   233 
       
   234 	//iDebug.Write( _L8("d1\n") );
       
   235 
       
   236 	//
       
   237 	// This is only needed if no huffman tables found
       
   238 	//
       
   239 	//CreateDefaultHuffmanL();
       
   240 
       
   241 
       
   242 	iQt[ 0 ] = 0;
       
   243 	iQt[ 1 ] = 0;
       
   244 	iQt[ 2 ] = 0;
       
   245 	iQt[ 3 ] = 0;
       
   246 
       
   247 	//
       
   248 
       
   249 	//TBitmapHandle bm;
       
   250 	//bm.iData = 0;
       
   251 
       
   252 	TBool moreChunks = ETrue;
       
   253 	TBool possibleChunk = EFalse;
       
   254 
       
   255 //	TInt pos;
       
   256 
       
   257 	while( moreChunks )
       
   258 		{
       
   259 		TUint8 b = iBuffer[ iBufPos++ ];
       
   260 		if( possibleChunk )
       
   261 			{
       
   262 			possibleChunk = EFalse;
       
   263 			switch( b )
       
   264 				{
       
   265 				case 0xd8: // start of image
       
   266 					{
       
   267 				    //RDebug::Print( _L("--Jpeg start of image") );
       
   268 					//iDebug.Write( _L8("d2\n") );
       
   269 					break;
       
   270 					}
       
   271 				case 0xe0: // JFIF application segment
       
   272 					{
       
   273 					//RDebug::Print( _L("--Jpeg application segment") );
       
   274 					//iDebug.Write( _L8("d3\n") );
       
   275 					break;
       
   276 					}
       
   277 				case 0xe1: // APP1 segment, possible EXIF
       
   278 					{
       
   279 					//iDebug.Write( _L8("d4\n") );
       
   280 					//RDebug::Print( _L("--Jpeg app1 segment") );
       
   281 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   282 					l -= 2;
       
   283 
       
   284 					// this could be used to read exif data:
       
   285 					//TPtrC8 exifData( iBuffer + iBufPos, l );
       
   286 
       
   287 					// Check that there is "Exif" header in the data
       
   288 					const TUint8* pos = &iBuffer[ iBufPos ];
       
   289 					if (Mem::Compare(pos, 2, &KExifHeader[0], 2 ))
       
   290 					{
       
   291 						iBufPos += l;
       
   292 						break;
       
   293 					}
       
   294 
       
   295 					// suppose there is exif here
       
   296 					// exif header is 6 bytes ( 45 78 69 66 00 00 "Exif.." )
       
   297 					iBufPos += 6;
       
   298 					l -= 6;
       
   299 
       
   300 					iExifData = iBuffer + iBufPos;
       
   301 					iExifDataLength = l;
       
   302 
       
   303 					iBufPos += l;
       
   304 					break;
       
   305 					}
       
   306 				case 0xe2:
       
   307 				case 0xe3:
       
   308 				case 0xe4:
       
   309 				case 0xe5:
       
   310 				case 0xe6:
       
   311 				case 0xe7:
       
   312 				case 0xe8:
       
   313 				case 0xe9:
       
   314 				case 0xea:
       
   315 				case 0xeb:
       
   316 				case 0xec:
       
   317 				case 0xed:
       
   318 				case 0xee:
       
   319 				case 0xef:
       
   320 					{
       
   321 					//iDebug.Write( _L8("d5\n") );
       
   322 					//
       
   323 					// Unused segment, skip
       
   324 					// 
       
   325 					//RDebug::Print( _L("--Jpeg unused tag %x"), b );
       
   326 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   327 
       
   328 					iBufPos += l-2;
       
   329 					break;
       
   330 					}
       
   331 				case 0xdb: // Quantization table
       
   332 					{
       
   333 					//iDebug.Write( _L8("d6\n") );
       
   334 					
       
   335 					//RDebug::Print( _L("--Jpeg quant table") );
       
   336 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   337 					////RDebug::Print( _L("Start:%x length:%d"), iBufPos-2, l );
       
   338 					TInt nqt = l / 65;
       
   339 					TInt i;
       
   340 
       
   341 					// one or more quantization table
       
   342 					for( i=0; i<nqt; i++ )
       
   343 						{
       
   344 						TUint8 t = iBuffer[ iBufPos++ ];
       
   345 						TInt n = t & 15;
       
   346 
       
   347 						// not used:
       
   348 						// TInt precision = n >> 4; 
       
   349 
       
   350 						if (iQt[ n ])
       
   351 						{
       
   352 							delete iQt[ n ];
       
   353 							iQt[ n ] = NULL;							
       
   354 						}
       
   355 						
       
   356 						iQt[ n ] = new( ELeave )TUint8[ 64 ];
       
   357 						TInt j;
       
   358 						for( j=0; j<64; j++ )
       
   359 							{
       
   360 							iQt[ n ][ j ] = iBuffer[ iBufPos++ ];
       
   361 							//RDebug::Print( _L("Quant %d:first=%d"), j, iQt[ n ][ j ] );
       
   362 							}
       
   363 						}
       
   364 
       
   365 					break;
       
   366 					}
       
   367 				case 0xc0: // start of frame ( SOF )
       
   368 					{
       
   369 					//iDebug.Write( _L8("d7\n") );
       
   370 
       
   371 					//RDebug::Print( _L("--Jpeg start of frame") );
       
   372 
       
   373 					//TInt length = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; 
       
   374 					iBufPos += 2;
       
   375 
       
   376 					////RDebug::Print( _L("Start:%x length:%d"), iBufPos-2, length );
       
   377 
       
   378 					// not used:
       
   379 					// TInt precision = iBuffer[ iBufPos ];
       
   380 					iBufPos++; 
       
   381 					
       
   382 					// height
       
   383 					TInt t = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   384 					iData.iSize.iHeight = t;
       
   385 					
       
   386 					// width
       
   387 					t = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   388 					iData.iSize.iWidth = t;
       
   389 					
       
   390 					// component data
       
   391 					iNumComponents = iBuffer[ iBufPos++ ];
       
   392 					
       
   393 					TInt i;
       
   394 					for( i=0; i<iNumComponents; i++ )
       
   395 						{
       
   396 						TInt compID = iBuffer[ iBufPos++ ];
       
   397 						
       
   398 						TInt samplingFactor = iBuffer[ iBufPos++ ];
       
   399 						TInt quantizationTable = iBuffer[ iBufPos++ ];
       
   400 						iComponent[ i ].iXFactor = samplingFactor >> 4;
       
   401 						iComponent[ i ].iYFactor = samplingFactor & 15;
       
   402 						iComponent[ i ].iQuantTable = quantizationTable;
       
   403 						iComponent[ i ].iID = compID;
       
   404 						//RDebug::Print( _L("component %d = %d"), i, compID );
       
   405 						//RDebug::Print( _L("component %d quanttable=%d"), i, quantizationTable );
       
   406 						//RDebug::Print( _L("component %d factor = %d,%d"), iComponent[ i ].iXFactor, iComponent[ i ].iYFactor );
       
   407 						}
       
   408 					
       
   409 					TInt xBlocks = 0;
       
   410 					TInt yBlocks = 0;
       
   411 
       
   412 					for( i=0; i<iNumComponents; i++ )
       
   413 						{
       
   414 						TInt x = iComponent[ i ].iXFactor;
       
   415 						TInt y = iComponent[ i ].iYFactor;
       
   416 						if( x > xBlocks )
       
   417 							{
       
   418 							xBlocks = x;
       
   419 							}
       
   420 						if( y > yBlocks )
       
   421 							{
       
   422 							yBlocks = y;
       
   423 							}
       
   424 						}
       
   425 					
       
   426 					iData.iBlockSize.iWidth = xBlocks * 8;
       
   427 					iData.iBlockSize.iHeight = yBlocks * 8;
       
   428 
       
   429 					TSize size = iData.iSize;
       
   430 					size.iWidth /= iData.iBlockSize.iWidth;
       
   431 					size.iHeight /= iData.iBlockSize.iHeight;
       
   432 
       
   433 					if( iData.iSize.iWidth & ( iData.iBlockSize.iWidth - 1 ) )
       
   434 						{
       
   435 						size.iWidth++;
       
   436 						}
       
   437 
       
   438 					if( iData.iSize.iHeight & ( iData.iBlockSize.iHeight - 1 ) )
       
   439 						{
       
   440 						size.iHeight++;
       
   441 						}
       
   442 					
       
   443 					iData.iSizeInBlocks = size;
       
   444 
       
   445 
       
   446 					break;
       
   447 					}
       
   448 				case 0xc1:
       
   449 					{
       
   450 					//iDebug.Write( _L8("d8\n") );
       
   451 					//RDebug::Print( _L("--Jpeg tag 0xc1, extended sequential, unsupported") );
       
   452 
       
   453 					// Extended sequential Jpeg, not supported
       
   454 					User::Leave( KErrNotSupported );
       
   455 					break;
       
   456 					};
       
   457 				case 0xc2:
       
   458 					{
       
   459 					//iDebug.Write( _L8("d9\n") );
       
   460 					//RDebug::Print( _L("--Jpeg tag 0xc2, Progressive DCT, unsupported") );
       
   461 
       
   462 					// Progressive DCT jpeg, not supported
       
   463 					User::Leave( KErrNotSupported );
       
   464 					break;
       
   465 					};
       
   466 				case 0xc3:
       
   467 					{
       
   468 					//iDebug.Write( _L8("d10\n") );
       
   469 					
       
   470 					//RDebug::Print( _L("--Jpeg tag 0xc1, Lossless, unsupported") );
       
   471 					// Lossless ( sequential ) Jpeg, not supported
       
   472 					User::Leave( KErrNotSupported );
       
   473 					break;
       
   474 					};
       
   475 	
       
   476 				case 0xc5:
       
   477 				case 0xc6:
       
   478 				case 0xc7:
       
   479 				case 0xc8:
       
   480 				case 0xc9:
       
   481 				case 0xca:
       
   482 				case 0xcb:
       
   483 				case 0xcc:
       
   484 				case 0xcd:
       
   485 				case 0xce:
       
   486 				case 0xcf:
       
   487 					{
       
   488 					//iDebug.Write( _L8("d11\n") );
       
   489 					
       
   490 					//RDebug::Print( _L("--Jpeg tag %x, unknown"), b );
       
   491 					User::Leave( KErrNotSupported );
       
   492 					break;
       
   493 					};
       
   494 				case 0xc4: // huffman table
       
   495 					{
       
   496 					//iDebug.Write( _L8("d12\n") );
       
   497 
       
   498 					//RDebug::Print( _L("--Jpeg huffman table") );
       
   499 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   500 					
       
   501 					TInt table = 0;
       
   502 
       
   503 					TInt n = 0;
       
   504 
       
   505 					// one or more huffman tables
       
   506 					while( n<l-2 )
       
   507 						{
       
   508 						THuffman* huff = new( ELeave )THuffman;
       
   509 					
       
   510 						table = iBuffer[ iBufPos++ ];
       
   511 						n++;
       
   512 						TInt huffSize[ 16 ];
       
   513 						TInt numSymbols = 0;
       
   514 						TInt i;
       
   515 
       
   516 						for( i=0; i<16; i++ )
       
   517 							{
       
   518 							TInt size = iBuffer[ iBufPos++ ];
       
   519 							huffSize[ i ] = size;
       
   520 							numSymbols += size;
       
   521 							n++;
       
   522 							}
       
   523 
       
   524 						////RDebug::Print( _L("       # of symbols %d"), numSymbols );
       
   525 						
       
   526 						for( i=0; i<numSymbols; i++ )
       
   527 							{
       
   528 							TUint8 v = iBuffer[ iBufPos++ ];
       
   529 							huff->iSymbol[ i ] = v;
       
   530 							n++;
       
   531 							}
       
   532 						
       
   533 
       
   534 						// Generate huffman lookup tables ( huffSize, table )
       
   535 
       
   536 
       
   537 						TInt ll;
       
   538 						TInt p = 0;
       
   539 						for( ll=0; ll<16; ll++ )
       
   540 							{
       
   541 							for( i=0; i<huffSize[ ll ]; i++ )
       
   542 								{
       
   543 								huff->iLength[ p++ ] = ll+1;
       
   544 								}
       
   545 							}
       
   546 
       
   547 						TInt code = 0;
       
   548 						huff->iLength[ p ] = 0;
       
   549 						TInt si = huff->iLength[ 0 ];
       
   550 						TInt lastP = p;						
       
   551 						
       
   552 						TInt hc[ 256 ];
       
   553 						p = 0;
       
   554 
       
   555 						while( huff->iLength[ p ] )
       
   556 							{
       
   557 							while( huff->iLength[ p ] == si )
       
   558 								{
       
   559 								hc[ p++ ] = code++;
       
   560 								}
       
   561 							code *= 2;
       
   562 							si++;
       
   563 							}
       
   564 
       
   565 						ll = 65536;
       
   566 						for( i=lastP-1; i>=0; i-- )
       
   567 							{
       
   568 							TInt t = 16 - huff->iLength[ i ];
       
   569 							TInt k = hc[ i ] * ( 1 << t );
       
   570 							TInt j;
       
   571 							for( j=k; j<ll; j++ )
       
   572 								{
       
   573 								huff->iSearch[ j ] = i;
       
   574 								}
       
   575 							ll = k;
       
   576 							}
       
   577 
       
   578 						i = ( table & 16 ) / 8 + ( table & 15 );
       
   579 						delete iHuffman[ i ];						
       
   580 						iHuffman[ i ] = huff;
       
   581 						}
       
   582 					
       
   583 					break;
       
   584 					}
       
   585 //
       
   586 				case 0xda: // start of scan ( SOS )
       
   587 					{
       
   588 					//iDebug.Write( _L8("d13\n") );
       
   589 
       
   590 					//RDebug::Print( _L("--Jpeg start of scan") );
       
   591 					//TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   592 					iBufPos += 2;
       
   593 					
       
   594 					TInt numComponents = iBuffer[ iBufPos++ ];
       
   595 					//RDebug::Print( _L("JPEG: number of components=%d"), numComponents );
       
   596 					if( numComponents != iNumComponents )
       
   597 						{
       
   598 						// non-interleaved( planar ) not supported
       
   599 						User::Leave( KErrNotSupported );
       
   600 						}
       
   601 					//RDebug::Print( _L("Number of components=%d"), numComponents );
       
   602 					
       
   603 					TInt componentHt[ 3 ];
       
   604 					
       
   605 					TInt i;
       
   606 					for( i=0; i<numComponents; i++ )
       
   607 						{
       
   608 						TInt componentId = iBuffer[ iBufPos++ ];
       
   609 						// find index by ID
       
   610 						TInt index = -1;
       
   611 						for( TInt j=0; j<iNumComponents; j++ )
       
   612 							{
       
   613 							if( iComponent[ j ].iID == componentId )
       
   614 								{
       
   615 								index = j;
       
   616 								}
       
   617 							}
       
   618 						if( index == -1 )
       
   619 							{
       
   620 							// ID not found
       
   621 							User::Leave( KErrNotSupported );
       
   622 							}
       
   623 						componentHt[ index ] = iBuffer[ iBufPos++ ];
       
   624 						//RDebug::Print( _L("id=%d, ht=%d"), componentId, componentHt[ i ] );
       
   625 						}
       
   626 						
       
   627 					if( componentHt[ 1 ] == 0 || componentHt[ 2 ] == 0 )
       
   628 						{
       
   629 						// images with same huffman for all components
       
   630 						// not yet supported
       
   631 						//RDebug::Print( _L("jpeg not supported") );
       
   632 						User::Leave( KErrNotSupported );
       
   633 						}						
       
   634 					
       
   635 
       
   636 					if( iHuffman[ 0 ] == NULL )
       
   637 						{
       
   638 						// no huffman tables found, create default tables
       
   639 						CreateDefaultHuffmanL();
       
   640 						}
       
   641 					
       
   642 
       
   643 					iBufPos += 3;
       
   644 
       
   645 					iImageDataStart = iBufPos;
       
   646 					iRandomScanned = false;
       
   647 					
       
   648 					moreChunks = EFalse;
       
   649 
       
   650 					break;
       
   651 					}
       
   652 				case 0xd9: // end of image ( EOI )
       
   653 					{
       
   654 					//RDebug::Print( _L("--Jpeg end of image") );
       
   655 					// not really used for anything
       
   656 					// will exit if picture data is read.
       
   657 					break;
       
   658 					}				
       
   659 				case 0xdd: // define restart interval
       
   660 					{
       
   661 					//RDebug::Print( _L("--Jpeg define restart interval") );
       
   662 					
       
   663 					//TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   664 					iBufPos += 2;
       
   665 					
       
   666 					TInt interval = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   667 					//iBufPos += 2;
       
   668 					//RDebug::Print( _L("       interval = %d"), interval );
       
   669 					iResetInterval = interval;
       
   670 					
       
   671 					// not really used for anything
       
   672 					// restart markers are just handled when they come
       
   673 					break;
       
   674 					}
       
   675 				case 0x00: // escaped 0xff
       
   676 					{
       
   677 					// only comes if file is broken somehow
       
   678 					break;
       
   679 					}
       
   680 				default:
       
   681 					{
       
   682 					// unknown jpeg tag
       
   683 					//RDebug::Print( _L("unknown jpeg tag %x"), b );
       
   684 					break;
       
   685 					}
       
   686 				}
       
   687 			}
       
   688 		else if( b == 255 )
       
   689 			{
       
   690 			possibleChunk = ETrue;
       
   691 			}
       
   692 			
       
   693 		}
       
   694 
       
   695 	PrepareLoadBlockL();
       
   696 	}
       
   697 
       
   698 
       
   699 
       
   700 void CJpeg::PrepareLoadBlockL()
       
   701 	{
       
   702 	if( iLoadBlockPrepared )
       
   703 		{
       
   704 		return;
       
   705 		}
       
   706 
       
   707 	// prepare rgb block bitmap
       
   708 	iBm.iSize = iData.iBlockSize;
       
   709 	iBm.iDrawRect = iBm.iSize;
       
   710 	iBlkPixels = iData.iBlockSize.iWidth * iData.iBlockSize.iHeight;
       
   711 	iBm.iData = NULL;
       
   712 	iBm.iType = E16MColor;
       
   713 	
       
   714 
       
   715 	// prepare yuv buffers
       
   716 	iC[ 0 ] = new( ELeave )TUint8[ 64 * iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor ];
       
   717 	iC[ 1 ] = new( ELeave )TUint8[ 64 * iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor ];
       
   718 	iC[ 2 ] = new( ELeave )TUint8[ 64 * iComponent[ 2 ].iXFactor * iComponent[ 2 ].iYFactor ];
       
   719 
       
   720 	// prepare yuv->rgb scale
       
   721 	TInt bw = iBm.iSize.iWidth;
       
   722 	TInt bh = iBm.iSize.iHeight;
       
   723 	iYxa = 256 * ( 8 * iComponent[ 0 ].iXFactor ) / bw;
       
   724 	iYya = 256 * ( 8 * iComponent[ 0 ].iYFactor ) / bh;
       
   725 	iUxa = 256 * ( 8 * iComponent[ 1 ].iXFactor ) / bw;
       
   726 	iUya = 256 * ( 8 * iComponent[ 1 ].iYFactor ) / bh;
       
   727 	iVxa = 256 * ( 8 * iComponent[ 2 ].iXFactor ) / bw;
       
   728 	iVya = 256 * ( 8 * iComponent[ 2 ].iYFactor ) / bh;
       
   729 
       
   730 	//
       
   731 	// Select YUV -> RGB function
       
   732 	//
       
   733 	iYuv2rgbFunc = Yuv2RgbFree;	// default, handles all combinations
       
   734 	
       
   735 	if( iComponent[ 0 ].iXFactor == 2 && iComponent[ 0 ].iYFactor == 1 &&
       
   736 		iComponent[ 1 ].iXFactor == 1 && iComponent[ 1 ].iYFactor == 1 &&
       
   737 		iComponent[ 2 ].iXFactor == 1 && iComponent[ 2 ].iYFactor == 1 )
       
   738 		{
       
   739 		iYuv2rgbFunc = Yuv2Rgb21_11_11;
       
   740 		}
       
   741 	else if( iComponent[ 0 ].iXFactor == 2 && iComponent[ 0 ].iYFactor == 2 &&
       
   742 			 iComponent[ 1 ].iXFactor == 1 && iComponent[ 1 ].iYFactor == 1 &&
       
   743 			 iComponent[ 2 ].iXFactor == 1 && iComponent[ 2 ].iYFactor == 1 )
       
   744 		{
       
   745 		iYuv2rgbFunc = Yuv2Rgb22_11_11;
       
   746 		}
       
   747 
       
   748 	iLoadBlockPrepared = true;
       
   749 	}
       
   750 
       
   751 
       
   752 
       
   753 void CJpeg::ScanRandomL()
       
   754 	{
       
   755 	if( iRandomScanned )
       
   756 		{
       
   757 		return;
       
   758 		}
       
   759 	//
       
   760 	// Set file read position
       
   761 	//
       
   762 	iBufPos = iImageDataStart;
       
   763 	iBufBits = 0;
       
   764 	iBuf = 0;
       
   765 
       
   766 	//
       
   767 	// Reserve memory for random access tables
       
   768 	//
       
   769 	TInt numBlocks = iData.iSizeInBlocks.iWidth * iData.iSizeInBlocks.iHeight;
       
   770 	iBlock = new( ELeave )TJpegBlock[ numBlocks ];
       
   771 						
       
   772 	
       
   773 	TInt bw = iData.iSizeInBlocks.iWidth;
       
   774 	TInt bh = iData.iSizeInBlocks.iHeight;
       
   775 
       
   776 	TInt bx;
       
   777 	TInt by;
       
   778 
       
   779 	TInt c1 = 0;
       
   780 	TInt c2 = 0;
       
   781 	TInt c3 = 0;
       
   782 
       
   783 	//TInt blockNum = 0;
       
   784 
       
   785 	for( by=0; by<bh; by++ )
       
   786 		{
       
   787 		////RDebug::Print( _L("Jpeg scan %d/%d"), by+1,bh );
       
   788 		
       
   789 		for( bx=0; bx<bw; bx++ )
       
   790 			{
       
   791 
       
   792 			if( iRst )
       
   793 				{
       
   794 				iRst = false;
       
   795 				iBuf = 0;
       
   796 				iBufBits = 0;
       
   797 				
       
   798 				c1 = 0;
       
   799 				c2 = 0;
       
   800 				c3 = 0;
       
   801 				}
       
   802 			
       
   803 			// store information for every block 
       
   804 			TJpegBlock& block = iBlock[ iNumBlocks++ ];
       
   805 			
       
   806 			block.iY = c1;
       
   807 			block.iU = c2;
       
   808 			block.iV = c3;
       
   809 			block.iOffset = iBufPos;
       
   810 			block.iBuf = iBuf;
       
   811 			block.iBufBits = iBufBits;
       
   812 			
       
   813 			//iBlock.Append( block );
       
   814 			
       
   815 			TInt i;
       
   816 			
       
   817 			// go fast trough all huffman data
       
   818 			iCurrentHuffman = 0;
       
   819 			iCurrentQt = iQt[ 0 ];
       
   820 			
       
   821 			// Y-component
       
   822 			TInt n = iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor;
       
   823 			iDct[ 0 ] = c1;
       
   824 			for( i=0; i<n; i++ )
       
   825 				{
       
   826 				DecodeBlock();
       
   827 				}
       
   828 			c1 = iDct[ 0 ];
       
   829 			
       
   830 			iCurrentHuffman = 1;
       
   831 			iCurrentQt = iQt[ 1 ];
       
   832 			
       
   833 			// U-component
       
   834 			n = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
       
   835 			iDct[ 0 ] = c2;
       
   836 			for( i=0; i<n; i++ )
       
   837 				{
       
   838 				DecodeBlock();
       
   839 				}
       
   840 			c2 = iDct[ 0 ];
       
   841 
       
   842 			// V-component
       
   843 			n = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
       
   844 			iDct[ 0 ] = c3;
       
   845 			for( i=0; i<n; i++ )
       
   846 				{
       
   847 				DecodeBlock();
       
   848 				}
       
   849 			c3 = iDct[ 0 ];
       
   850 
       
   851 			}
       
   852 		}
       
   853 
       
   854 	iRandomScanned = true;
       
   855 	
       
   856 	}
       
   857 
       
   858 
       
   859 
       
   860 TBitmapHandle CJpeg::LoadBlockL( const TPoint& aBlock )
       
   861 	{
       
   862 	TBitmapHandle bm = iBm;
       
   863 	bm.iData = new( ELeave )TUint32[ iBlkPixels ];
       
   864 	CleanupStack::PushL(bm.iData);
       
   865 	TUint32* rgb = (TUint32*) bm.iData;
       
   866 	
       
   867 	TInt blkNum = aBlock.iX + aBlock.iY * iData.iSizeInBlocks.iWidth;
       
   868 
       
   869 	if( aBlock.iX < 0 || aBlock.iX >= iData.iSizeInBlocks.iWidth )
       
   870 		{
       
   871 		blkNum = -1;
       
   872 		}
       
   873 	//if( blkNum < 0 || blkNum >= iBlock.Count() )
       
   874 	if( blkNum < 0 || blkNum >= iNumBlocks )
       
   875 		{
       
   876 		Mem::FillZ( bm.iData, iBlkPixels * sizeof( TUint32 ) );
       
   877 		return bm;
       
   878 		}
       
   879 
       
   880 	TJpegBlock& blk = iBlock[ blkNum ];
       
   881 
       
   882 	iBuf = blk.iBuf;
       
   883 	iBufBits = blk.iBufBits;
       
   884 	iBufPos = blk.iOffset;
       
   885 	
       
   886 	//
       
   887 	// Decode block
       
   888 	//
       
   889 
       
   890 	TInt c1 = blk.iY;
       
   891 	TInt c2 = blk.iU;
       
   892 	TInt c3 = blk.iV;
       
   893 	
       
   894 	
       
   895 	///////////
       
   896 	TInt x;
       
   897 	TInt y;
       
   898 	TInt xx;
       
   899 	TInt yy;
       
   900 	TInt w;
       
   901 	TInt* p;
       
   902 
       
   903 	// Y-component
       
   904 	iCurrentHuffman = 0;
       
   905 	iCurrentQt = iQt[ 0 ];	
       
   906 	xx = iComponent[ 0 ].iXFactor;
       
   907 	yy = iComponent[ 0 ].iYFactor;
       
   908 	w = xx * 8;
       
   909 	p = iBlk;
       
   910 	iDct[ 0 ] = c1;
       
   911 
       
   912 	for( y=0; y<yy; y++ )
       
   913 		{
       
   914 		for( x=0; x<xx; x++ )
       
   915 			{
       
   916 			DecodeBlock2();
       
   917 			TUint8* tp = iC[ 0 ] + x*8 + y * 8 * w;
       
   918 			p = iBlk;
       
   919 
       
   920 			for( TInt ty=0; ty<8; ty++ )
       
   921 				{
       
   922 				for( TInt tx=0; tx<8; tx++ )
       
   923 					{
       
   924 					tp[ tx + ty * w ] = *p++;
       
   925 					}
       
   926 				}
       
   927 			}
       
   928 		}
       
   929 	
       
   930 
       
   931 	// U-component
       
   932 	iCurrentHuffman = 1;
       
   933 	iCurrentQt = iQt[ 1 ];	
       
   934 	xx = iComponent[ 1 ].iXFactor;
       
   935 	yy = iComponent[ 1 ].iYFactor;
       
   936 	w = xx * 8;
       
   937 	p = iBlk;
       
   938 	iDct[ 0 ] = c2;
       
   939 
       
   940 	for( y=0; y<yy; y++ )
       
   941 		{
       
   942 		for( x=0; x<xx; x++ )
       
   943 			{
       
   944 			DecodeBlock2();
       
   945 			TUint8* tp = iC[ 1 ] + x*8 + y * 8 * w;
       
   946 			p = iBlk;
       
   947 
       
   948 			for( TInt ty=0; ty<8; ty++ )
       
   949 				{
       
   950 				for( TInt tx=0; tx<8; tx++ )
       
   951 					{
       
   952 					tp[ tx + ty * w ] = *p++;
       
   953 					}
       
   954 				}
       
   955 			}
       
   956 		}
       
   957 
       
   958 	// V-component
       
   959 	iCurrentHuffman = 1;
       
   960 	iCurrentQt = iQt[ 1 ];	
       
   961 	xx = iComponent[ 2 ].iXFactor;
       
   962 	yy = iComponent[ 2 ].iYFactor;
       
   963 	w = xx * 8;
       
   964 	iDct[ 0 ] = c3;
       
   965 	
       
   966 	for( y=0; y<yy; y++ )
       
   967 		{
       
   968 		for( x=0; x<xx; x++ )
       
   969 			{
       
   970 			DecodeBlock2();
       
   971 			TUint8* tp = iC[ 2 ] + x*8 + y * 8 * w;
       
   972 			
       
   973 			p = iBlk;
       
   974 			for( TInt ty=0; ty<8; ty++ )
       
   975 				{
       
   976 				for( TInt tx=0; tx<8; tx++ )
       
   977 					{
       
   978 					tp[ tx + ty * w ] = *p++;
       
   979 					}
       
   980 				}
       
   981 			}
       
   982 		}
       
   983 	///////////
       
   984 
       
   985 	//
       
   986 	// Scaled blit YUV->RGB
       
   987 	//
       
   988 
       
   989 	TInt bw = bm.iSize.iWidth;
       
   990 	TInt bh = bm.iSize.iHeight;
       
   991 
       
   992 	
       
   993 	TInt y1y = 0;
       
   994 	TInt y1u = 0;
       
   995 	TInt y1v = 0;
       
   996 
       
   997 	TInt yw = iComponent[ 0 ].iXFactor * 8;
       
   998 	TInt uw = iComponent[ 1 ].iXFactor * 8;
       
   999 	TInt vw = iComponent[ 2 ].iXFactor * 8;
       
  1000 	
       
  1001 	TUint32* prgb = rgb;
       
  1002 	for( y=0; y<bh; y++ )
       
  1003 		{
       
  1004 		TInt txy = 0;
       
  1005 		TInt txu = 0;
       
  1006 		TInt txv = 0;
       
  1007 		TUint8* ccy = iC[ 0 ] + ( y1y/256 ) * yw;
       
  1008 		TUint8* ccu = iC[ 1 ] + ( y1u/256 ) * uw;
       
  1009 		TUint8* ccv = iC[ 2 ] + ( y1v/256 ) * vw;
       
  1010 
       
  1011 		for( x=0; x<bw; x++ )
       
  1012 			{
       
  1013 
       
  1014 			TInt cy = ccy[ txy / 256 ];
       
  1015 			TInt cu = ccu[ txu / 256 ] - 128;
       
  1016 			TInt cv = ccv[ txv / 256 ] - 128;
       
  1017 			
       
  1018 			txy += iYxa;
       
  1019 			txu += iUxa;
       
  1020 			txv += iVxa;
       
  1021 
       
  1022 			TInt cr = cy + ( 91881 * cv ) / 65536;
       
  1023 			TInt cg = cy - ( 22554 * cu  +  46802 * cv ) / 65536;
       
  1024 			TInt cb = cy + ( 116130 * cu ) / 65536;
       
  1025 			
       
  1026 			if( cr < 0 ) cr = 0;
       
  1027 			if( cg < 0 ) cg = 0;
       
  1028 			if( cb < 0 ) cb = 0;
       
  1029 			if( cr > 255 ) cr = 255;
       
  1030 			if( cg > 255 ) cg = 255;
       
  1031 			if( cb > 255 ) cb = 255;
       
  1032 
       
  1033 			//rgb[ x + y * bw ] = cr * 65536 + cg * 256 + cb;
       
  1034 			*prgb++ = cr * 65536 + cg * 256 + cb;
       
  1035 			}
       
  1036 		y1y += iYya;
       
  1037 		y1u += iUya;
       
  1038 		y1v += iVya;
       
  1039 		}
       
  1040 
       
  1041 	CleanupStack::Pop();
       
  1042 	return bm;
       
  1043 	}
       
  1044 
       
  1045 
       
  1046 
       
  1047 
       
  1048 void CJpeg::DecodeBlock()
       
  1049 	{
       
  1050 	// //RDebug::Print( _L("DecodeBlock()") );
       
  1051 	//
       
  1052 	// Dummy version of block decode
       
  1053 	// only traverses through huffman data
       
  1054 	// and collects DC-values
       
  1055 	//
       
  1056 	THuffman* h = iHuffman[ iCurrentHuffman ];
       
  1057 	
       
  1058 	TInt k;
       
  1059 	for( k=0; k<64; k++ )
       
  1060 		{
       
  1061 		TInt v = Buf16();
       
  1062 		TInt index = h->iSearch[ v ];
       
  1063 		TInt symbol = h->iSymbol[ index ];
       
  1064 		BufFwd( h->iLength[ index ] );
       
  1065 		
       
  1066 		TInt nullCount = 0;
       
  1067 		if( k>0 )
       
  1068 			{
       
  1069 			nullCount = symbol >> 4;
       
  1070 			symbol &= 15;
       
  1071 			}
       
  1072 	
       
  1073 		v = BufBits( symbol );
       
  1074 		if( v < ( 1 << ( symbol-1 ) ) )
       
  1075 			{
       
  1076 			v += 1 - ( 1 << symbol );
       
  1077 			}
       
  1078 		
       
  1079 		if( k )
       
  1080 			{
       
  1081 			if( nullCount==0 && v==0 )
       
  1082 				{
       
  1083 				k = 64;
       
  1084 				break;
       
  1085 				}
       
  1086 			else if( nullCount==15 && v==0 )
       
  1087 				{
       
  1088 				k += 15;
       
  1089 				}
       
  1090 			else
       
  1091 				{
       
  1092 				k += nullCount;
       
  1093 				}
       
  1094 			}
       
  1095 		else
       
  1096 			{
       
  1097 			iDct[ 0 ] += v * iCurrentQt[ 0 ];
       
  1098 			h = iHuffman[ iCurrentHuffman+2 ];
       
  1099 			}
       
  1100 		}
       
  1101 	}
       
  1102 
       
  1103 
       
  1104 
       
  1105 void CJpeg::DecodeBlock2()
       
  1106 	{
       
  1107 	//
       
  1108 	// Real block decoder
       
  1109 	// fills iDct table and calls Idct() function
       
  1110 	//
       
  1111 	THuffman* h = iHuffman[ iCurrentHuffman ];
       
  1112 
       
  1113 	TInt k;
       
  1114 	
       
  1115 	for( k=1; k<64; k++ )
       
  1116 		{
       
  1117 		iDct[ k ] = 0;
       
  1118 		}
       
  1119 
       
  1120 	for( k=0; k<64; k++ )
       
  1121 		{
       
  1122 		TInt v = Buf16();
       
  1123 		TInt index = h->iSearch[ v ];
       
  1124 		TInt symbol = h->iSymbol[ index ];
       
  1125 		BufFwd( h->iLength[ index ] );
       
  1126 		
       
  1127 		TInt nullCount = 0;
       
  1128 		if( k>0 )
       
  1129 			{
       
  1130 			nullCount = symbol >> 4;
       
  1131 			symbol &= 15;
       
  1132 			}
       
  1133 		
       
  1134 		v = BufBits( symbol );
       
  1135 					
       
  1136 		if( v < ( 1 << ( symbol-1 ) ) )
       
  1137 			{
       
  1138 			v += 1 - ( 1 << symbol );
       
  1139 			}
       
  1140 		
       
  1141 		if( k )
       
  1142 			{
       
  1143 			if( nullCount==0 && v==0 )
       
  1144 				{
       
  1145 				k = 64;
       
  1146 				break;
       
  1147 				}
       
  1148 			else if( nullCount==15 && v==0 )
       
  1149 				{
       
  1150 				k += 15;
       
  1151 				}
       
  1152 			else
       
  1153 				{
       
  1154 				k += nullCount;
       
  1155 				iDct[ KZigZag[ k ] ] = v * iCurrentQt[ k ];
       
  1156 				}
       
  1157 			}
       
  1158 		else
       
  1159 			{
       
  1160 			iDct[ 0 ] += v * iCurrentQt[ 0 ];
       
  1161 			h = iHuffman[ iCurrentHuffman+2 ];
       
  1162 			}
       
  1163 
       
  1164 		}
       
  1165 	Idct();
       
  1166 	}
       
  1167 
       
  1168 
       
  1169 
       
  1170 void CJpeg::DecodeBlock3()
       
  1171 	{
       
  1172 	//
       
  1173 	// Real block decoder
       
  1174 	// fills iDct table and calls Idct() function
       
  1175 	//
       
  1176 	THuffman* h = iHuffman[ iCurrentHuffman ];
       
  1177 
       
  1178 	TInt k;
       
  1179 	
       
  1180 	for( k=1; k<64; k++ )
       
  1181 		{
       
  1182 		iDct[ k ] = 0;
       
  1183 		}
       
  1184 
       
  1185 	for( k=0; k<64; k++ )
       
  1186 		{
       
  1187 		TInt v = Buf16();
       
  1188 		TInt index = h->iSearch[ v ];
       
  1189 		TInt symbol = h->iSymbol[ index ];
       
  1190 		BufFwd( h->iLength[ index ] );
       
  1191 		
       
  1192 		TInt nullCount = 0;
       
  1193 		if( k>0 )
       
  1194 			{
       
  1195 			nullCount = symbol >> 4;
       
  1196 			symbol &= 15;
       
  1197 			}
       
  1198 		
       
  1199 		v = BufBits( symbol );
       
  1200 					
       
  1201 		if( v < ( 1 << ( symbol-1 ) ) )
       
  1202 			{
       
  1203 			v += 1 - ( 1 << symbol );
       
  1204 			}
       
  1205 		
       
  1206 		if( k )
       
  1207 			{
       
  1208 			if( nullCount==0 && v==0 )
       
  1209 				{
       
  1210 				k = 64;
       
  1211 				break;
       
  1212 				}
       
  1213 			else if( nullCount==15 && v==0 )
       
  1214 				{
       
  1215 				k += 15;
       
  1216 				}
       
  1217 			else
       
  1218 				{
       
  1219 				k += nullCount;
       
  1220 				iDct[ KZigZag[ k ] ] = v * iCurrentQt[ k ];
       
  1221 				}
       
  1222 			}
       
  1223 		else
       
  1224 			{
       
  1225 			iDct[ 0 ] += v * iCurrentQt[ 0 ];
       
  1226 			h = iHuffman[ iCurrentHuffman+2 ];
       
  1227 			}
       
  1228 
       
  1229 		}
       
  1230 	}
       
  1231 
       
  1232 
       
  1233 
       
  1234 
       
  1235 void CJpeg::Idct()
       
  1236 	{
       
  1237 	TInt even[ 4 ];
       
  1238 	TInt odd[ 4 ];
       
  1239 	TInt res[ 64 ];
       
  1240 
       
  1241 	TInt* p = iDct;
       
  1242     
       
  1243     for( TInt x=0; x<8; x++ )
       
  1244 		{
       
  1245 		TInt x0 = *p++;
       
  1246 		TInt x1 = *p++;
       
  1247 		TInt x2 = *p++;
       
  1248 		TInt x3 = *p++;
       
  1249 		TInt x4 = *p++;
       
  1250 		TInt x5 = *p++;
       
  1251 		TInt x6 = *p++;
       
  1252 		TInt x7 = *p++;
       
  1253         
       
  1254         TInt tx0 = x0;
       
  1255         x0 = (x0 + x4) * 181;
       
  1256         x4 = (tx0 - x4) * 181;
       
  1257         
       
  1258         TInt tx2 = x2;
       
  1259         TInt tx6 = x6;
       
  1260         x2 = tx2 * 236 + tx6 * 98;
       
  1261         x6 = tx2 * 98 - tx6 * 236;
       
  1262         
       
  1263         even[0] = x0 + x2;
       
  1264         even[1] = x4 + x6;
       
  1265         even[2] = x4 - x6;
       
  1266         even[3] = x0 - x2;
       
  1267         
       
  1268         odd[0] = x1 * 251 + x5 * 142 + x3 * 212 + x7 * 49;
       
  1269         odd[1] = x1 * 213 - x5 * 251 - x3 * 50 - x7 * 142;
       
  1270         odd[2] = x1 * 142 + x5 * 50 - x3 * 251 + x7 * 213;
       
  1271         odd[3] = x1 * 50 + x5 * 213 - x3 * 142 - x7 * 251;
       
  1272                 
       
  1273         res[x + 0] = even[0] + odd[0];
       
  1274         res[x + 8] = even[1] + odd[1];
       
  1275         res[x + 16] = even[2] + odd[2];
       
  1276         res[x + 24] = even[3] + odd[3];
       
  1277         res[x + 32] = even[3] - odd[3];
       
  1278         res[x + 40] = even[2] - odd[2];
       
  1279         res[x + 48] = even[1] - odd[1];
       
  1280         res[x + 56] = even[0] - odd[0];
       
  1281 		}
       
  1282     
       
  1283     p = res;
       
  1284 	TInt* tp = iBlk;
       
  1285 
       
  1286     for( TInt y=0; y<8; y++ )
       
  1287 		{
       
  1288         TInt x0 = *p++;
       
  1289         TInt x1 = *p++;
       
  1290         TInt x2 = *p++;
       
  1291         TInt x3 = *p++;
       
  1292         TInt x4 = *p++;
       
  1293         TInt x5 = *p++;
       
  1294         TInt x6 = *p++;
       
  1295         TInt x7 = *p++;
       
  1296         
       
  1297         TInt tx0 = x0;
       
  1298         x0 = (x0 + x4) * 181;
       
  1299         x4 = (tx0 - x4) * 181;
       
  1300         
       
  1301         TInt tx2 = x2;
       
  1302         TInt tx6 = x6;
       
  1303         x2 = tx2 * 236 + tx6 * 98;
       
  1304         x6 = tx2 * 98 - tx6 * 236;
       
  1305         
       
  1306         even[0] = x0 + x2;
       
  1307         even[1] = x4 + x6;
       
  1308         even[2] = x4 - x6;
       
  1309         even[3] = x0 - x2;
       
  1310         
       
  1311         odd[0] = x1 * 251 + x5 * 142 + x3 * 212 + x7 * 49;
       
  1312         odd[1] = x1 * 213 - x5 * 251 - x3 * 50 - x7 * 142;
       
  1313         odd[2] = x1 * 142 + x5 * 50 - x3 * 251 + x7 * 213;
       
  1314         odd[3] = x1 * 50 + x5 * 213 - x3 * 142 - x7 * 251;
       
  1315                 
       
  1316         *tp++ = (even[0] + odd[0]) / 262144 + 128;
       
  1317         *tp++ = (even[1] + odd[1]) / 262144 + 128;
       
  1318         *tp++ = (even[2] + odd[2]) / 262144 + 128;
       
  1319         *tp++ = (even[3] + odd[3]) / 262144 + 128;
       
  1320         *tp++ = (even[3] - odd[3]) / 262144 + 128;
       
  1321         *tp++ = (even[2] - odd[2]) / 262144 + 128;
       
  1322         *tp++ = (even[1] - odd[1]) / 262144 + 128;
       
  1323         *tp++ = (even[0] - odd[0]) / 262144 + 128;
       
  1324 		}
       
  1325 
       
  1326 	//
       
  1327 	// Clamp
       
  1328 	//
       
  1329 	tp = iBlk;
       
  1330 	TInt* tpe = tp + 64;
       
  1331 	while( tp < tpe )
       
  1332 		{
       
  1333 		if( *tp < 0 ) *tp = 0;
       
  1334 		if( *tp > 255 ) *tp = 255;
       
  1335 		tp++;
       
  1336 		}
       
  1337 	}
       
  1338 
       
  1339 
       
  1340 
       
  1341 void CJpeg::IdctHalf()
       
  1342 	{
       
  1343 	TInt even[ 4 ];
       
  1344 	TInt odd[ 4 ];
       
  1345 	TInt res[ 64 ];
       
  1346 
       
  1347 	TInt* p = iDct;
       
  1348     
       
  1349     for( TInt x=0; x<4; x++ )
       
  1350 		{
       
  1351 		TInt x0 = *p++;
       
  1352 		TInt x1 = *p++;
       
  1353 		TInt x2 = *p++;
       
  1354 		TInt x3 = *p++;
       
  1355 		p += 4;
       
  1356 
       
  1357         x0 = x0 * 181;
       
  1358         
       
  1359 		TInt x6 = x2 * 98;
       
  1360         x2 = x2 * 236;
       
  1361         
       
  1362         even[0] = x0 + x2;
       
  1363         even[1] = x0 + x6;
       
  1364         even[2] = x0 - x6;
       
  1365         even[3] = x0 - x2;
       
  1366         
       
  1367         odd[0] = x1 * 251 + x3 * 212;
       
  1368         odd[1] = x1 * 213 - x3 * 50;
       
  1369         odd[2] = x1 * 142 - x3 * 251;
       
  1370         odd[3] = x1 * 50  - x3 * 142;
       
  1371                 
       
  1372         res[x + 0] = even[0] + odd[0];
       
  1373         res[x + 4] = even[2] + odd[2];
       
  1374         res[x + 8] = even[3] - odd[3];
       
  1375         res[x + 12] = even[1] - odd[1];
       
  1376 		}
       
  1377     
       
  1378 	p = res;
       
  1379 	TInt* tp = iBlk;
       
  1380 
       
  1381     for( TInt y=0; y<4; y++ )
       
  1382 		{
       
  1383         TInt x0 = *p++;
       
  1384         TInt x1 = *p++;
       
  1385         TInt x2 = *p++;
       
  1386         TInt x3 = *p++;
       
  1387         
       
  1388         x0 = x0 * 181;
       
  1389         
       
  1390         TInt x6 = x2 * 98;
       
  1391         x2 = x2 * 236;
       
  1392         
       
  1393         even[0] = x0 + x2;
       
  1394         even[1] = x0 + x6;
       
  1395         even[2] = x0 - x6;
       
  1396         even[3] = x0 - x2;
       
  1397         
       
  1398         odd[0] = x1 * 251  + x3 * 212;
       
  1399         odd[1] = x1 * 213  - x3 * 50;
       
  1400         odd[2] = x1 * 142  - x3 * 251;
       
  1401         odd[3] = x1 * 50   - x3 * 142;
       
  1402                 
       
  1403         *tp++ = (even[0] + odd[0]) / 262144 + 128;
       
  1404         *tp++ = (even[2] + odd[2]) / 262144 + 128;
       
  1405         *tp++ = (even[3] - odd[3]) / 262144 + 128;
       
  1406         *tp++ = (even[1] - odd[1]) / 262144 + 128;
       
  1407 		}
       
  1408 
       
  1409 	//
       
  1410 	// Clamp
       
  1411 	//
       
  1412 	tp = iBlk;
       
  1413 	TInt* tpe = tp + 16;
       
  1414 	while( tp < tpe )
       
  1415 		{
       
  1416 		if( *tp < 0 ) *tp = 0;
       
  1417 		if( *tp > 255 ) *tp = 255;
       
  1418 		tp++;
       
  1419 		}
       
  1420 	}
       
  1421 
       
  1422 
       
  1423 
       
  1424 
       
  1425 const TJpegData& CJpeg::Info()
       
  1426 	{
       
  1427 	return iData;
       
  1428 	}
       
  1429 
       
  1430 
       
  1431 TPtrC8 CJpeg::ExifData()
       
  1432 	{
       
  1433 	return TPtrC8( iExifData, iExifDataLength );
       
  1434 	}
       
  1435 
       
  1436 
       
  1437 
       
  1438 void CJpeg::CreateHuffmanL( THuffman* aHuffman, const TUint8* aBits, const TUint8* aVal )
       
  1439 	{
       
  1440 	//
       
  1441 	// default huffman lookup table generator
       
  1442 	//
       
  1443 
       
  1444 	TInt huffSize[ 16 ];
       
  1445 	TInt numSymbols = 0;
       
  1446 	TInt i;
       
  1447 
       
  1448 	for( i=0; i<16; i++ )
       
  1449 		{
       
  1450 		TInt size = aBits[ i+1 ];
       
  1451 		huffSize[ i ] = size;
       
  1452 		numSymbols += size;
       
  1453 		}
       
  1454 
       
  1455 	for( i=0; i<numSymbols; i++ )
       
  1456 		{
       
  1457 		aHuffman->iSymbol[ i ] = aVal[ i ];
       
  1458 		}
       
  1459 	
       
  1460 	TInt l;
       
  1461 	TInt p = 0;
       
  1462 	for( l=0; l<16; l++ )
       
  1463 		{
       
  1464 		for( i=0; i<huffSize[ l ]; i++ )
       
  1465 			{
       
  1466 			aHuffman->iLength[ p++ ] = l+1;
       
  1467 			}
       
  1468 		}
       
  1469 
       
  1470 	TInt code = 0;
       
  1471 	aHuffman->iLength[ p ] = 0;
       
  1472 	TInt si = aHuffman->iLength[ 0 ];
       
  1473 	TInt lastP = p;
       
  1474 	
       
  1475 	TInt hc[ 256 ];
       
  1476 	p = 0;
       
  1477 
       
  1478 	while( aHuffman->iLength[ p ] )
       
  1479 		{
       
  1480 		while( aHuffman->iLength[ p ] == si )
       
  1481 			{
       
  1482 			hc[ p++ ] = code++;
       
  1483 			}
       
  1484 		code *= 2;
       
  1485 		si++;
       
  1486 		}
       
  1487 	
       
  1488 	l = 65536;
       
  1489 	for( i=lastP-1; i>=0; i-- )
       
  1490 		{
       
  1491 		TInt t = 16 - aHuffman->iLength[ i ];
       
  1492 		TInt k = hc[ i ] * ( 1 << t );
       
  1493 		TInt j;
       
  1494 		for( j=k; j<l; j++ )
       
  1495 			{
       
  1496 			aHuffman->iSearch[ j ] = i;
       
  1497 			}
       
  1498 		l = k;
       
  1499 		}
       
  1500 	
       
  1501 	}
       
  1502 
       
  1503 
       
  1504 
       
  1505 void CJpeg::CreateDefaultHuffmanL()
       
  1506 	{
       
  1507 	//
       
  1508 	// Creates default huffman tables
       
  1509 	// needed if jpeg file doesn't have huffman tables
       
  1510 	// for example motion jpeg file doesn't have.
       
  1511 	//
       
  1512 	THuffman* huff = new( ELeave )THuffman;
       
  1513 	CleanupStack::PushL( huff );
       
  1514 	CreateHuffmanL( huff, bits_dc_luminance, val_dc_luminance );
       
  1515 	iHuffman[ 0 ] = huff;
       
  1516 	CleanupStack::Pop( huff );
       
  1517 
       
  1518 	huff = new( ELeave )THuffman;
       
  1519 	CleanupStack::PushL( huff );
       
  1520 	CreateHuffmanL( huff, bits_dc_chrominance, val_dc_chrominance );
       
  1521 	iHuffman[ 1 ] = huff;
       
  1522 	CleanupStack::Pop( huff );
       
  1523 
       
  1524 	huff = new( ELeave )THuffman;
       
  1525 	CleanupStack::PushL( huff );
       
  1526 	CreateHuffmanL( huff, bits_ac_luminance, val_ac_luminance );
       
  1527 	iHuffman[ 2 ] = huff;
       
  1528 	CleanupStack::Pop( huff );
       
  1529 
       
  1530 	huff = new( ELeave )THuffman;
       
  1531 	CleanupStack::PushL( huff );
       
  1532 	CreateHuffmanL( huff, bits_ac_chrominance, val_ac_chrominance );
       
  1533 	iHuffman[ 3 ] = huff;
       
  1534 	CleanupStack::Pop( huff );
       
  1535 	}
       
  1536 
       
  1537 
       
  1538 
       
  1539 void CJpeg::DecRgb1_1L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
       
  1540 	{
       
  1541 	PrepareLoadBlockL();
       
  1542 
       
  1543 	//
       
  1544 	// Set file read position
       
  1545 	//
       
  1546 	iBufPos = iImageDataStart;
       
  1547 	iBufBits = 0;
       
  1548 	iBuf = 0;
       
  1549 
       
  1550 	TInt c[ 3 ];
       
  1551 	c[ 0 ] = 0;
       
  1552 	c[ 1 ] = 0;
       
  1553 	c[ 2 ] = 0;
       
  1554 
       
  1555 	TInt w = aBitmap.iSize.iWidth;
       
  1556 	TUint32* rgb = (TUint32*)aBitmap.iData;
       
  1557 
       
  1558 	//
       
  1559 	// Store data for yuv->rgb conversion
       
  1560 	//
       
  1561 	iYuvConv.iBlkSize = iData.iBlockSize;
       
  1562 	iYuvConv.iRgbWidth = w;
       
  1563 	iYuvConv.iBlkPixels = 8;
       
  1564 
       
  1565 	TInt blw = aBlockRect.Size().iWidth;
       
  1566 	TInt blh = aBlockRect.Size().iHeight;
       
  1567 
       
  1568 	for( TInt by=0; by<blh; by++ )
       
  1569 		{
       
  1570 
       
  1571 		if( iRandomScanned )
       
  1572 			{
       
  1573 			TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
       
  1574 			TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
       
  1575 			TJpegBlock& blk = iBlock[ blkNum ];
       
  1576 
       
  1577 			iBuf = blk.iBuf;
       
  1578 			iBufBits = blk.iBufBits;
       
  1579 			iBufPos = blk.iOffset;
       
  1580 			c[ 0 ] = blk.iY;
       
  1581 			c[ 1 ] = blk.iU;
       
  1582 			c[ 2 ] = blk.iV;
       
  1583 			iRst = false;
       
  1584 			}
       
  1585 
       
  1586 		//TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
       
  1587 
       
  1588 		for( TInt bx=0; bx<blw; bx++ )
       
  1589 			{
       
  1590 			iYuvConv.iRgb = rgb + bx * iData.iBlockSize.iWidth;
       
  1591 			iYuvConv.iRgb += by * iData.iBlockSize.iHeight * w;
       
  1592 		
       
  1593 			if( iRst )
       
  1594 				{
       
  1595 				iRst = false;
       
  1596 				iBuf = 0;
       
  1597 				iBufBits = 0;
       
  1598 				
       
  1599 				c[ 0 ] = 0;
       
  1600 				c[ 1 ] = 0;
       
  1601 				c[ 2 ] = 0;
       
  1602 				}
       
  1603 			//blockNum++;
       
  1604 
       
  1605 			
       
  1606 			TInt xx;
       
  1607 			TInt yy;
       
  1608 			TInt* p;
       
  1609 
       
  1610 			for( TInt i=0; i<iNumComponents; i++ )
       
  1611 				{
       
  1612 				iCurrentQt = iQt[ KQuantIndex[ i ] ];	
       
  1613 				xx = iComponent[ i ].iXFactor;
       
  1614 				yy = iComponent[ i ].iYFactor;
       
  1615 				TInt dw = xx * 8;
       
  1616 				p = iBlk;
       
  1617 				iDct[ 0 ] = c[ i ];
       
  1618 
       
  1619 				for( TInt y=0; y<yy; y++ )
       
  1620 					{
       
  1621 					for( TInt x=0; x<xx; x++ )
       
  1622 						{
       
  1623 						iCurrentHuffman = KHuffIndex[ i ];
       
  1624 						DecodeBlock3();
       
  1625 						Idct();
       
  1626 						TUint8* tp = iC[ i ] + x*8 + y*8 * dw;
       
  1627 						p = iBlk;
       
  1628 
       
  1629 						for( TInt ty=0; ty<8; ty++ )
       
  1630 							{
       
  1631 							for( TInt tx=0; tx<8; tx++ )
       
  1632 								{
       
  1633 								tp[ tx + ty * dw ] = *p++;
       
  1634 								}
       
  1635 							}
       
  1636 						}
       
  1637 					}
       
  1638 				c[ i ] = iDct[ 0 ];
       
  1639 				}
       
  1640 
       
  1641 			//
       
  1642 			// Scaled blit YUV->RGB
       
  1643 			//
       
  1644 			if( iRgbConv )
       
  1645 				{
       
  1646 				iYuv2rgbFunc( this );
       
  1647 				}
       
  1648 
       
  1649 			}
       
  1650 		}		
       
  1651 	}
       
  1652 
       
  1653 
       
  1654 
       
  1655 
       
  1656 void CJpeg::DecRgb1_2L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
       
  1657 	{
       
  1658 	PrepareLoadBlockL();
       
  1659 
       
  1660 	//
       
  1661 	// Set file read position
       
  1662 	//
       
  1663 	iBufPos = iImageDataStart;
       
  1664 	iBufBits = 0;
       
  1665 	iBuf = 0;
       
  1666 
       
  1667 	TInt c[ 3 ];
       
  1668 	c[ 0 ] = 0;
       
  1669 	c[ 1 ] = 0;
       
  1670 	c[ 2 ] = 0;
       
  1671 
       
  1672 	TInt w = aBitmap.iSize.iWidth;
       
  1673 	TUint32* rgb = (TUint32*)aBitmap.iData;
       
  1674 
       
  1675 	TInt bw = iData.iBlockSize.iWidth / 2;
       
  1676 	TInt bh = iData.iBlockSize.iHeight / 2;
       
  1677 	//
       
  1678 	// Store data for yuv->rgb conversion
       
  1679 	//
       
  1680 	iYuvConv.iBlkSize = TSize( bw, bh );
       
  1681 	iYuvConv.iRgbWidth = w;
       
  1682 	iYuvConv.iBlkPixels = 4;
       
  1683 
       
  1684 	TInt blw = aBlockRect.Size().iWidth;
       
  1685 	TInt blh = aBlockRect.Size().iHeight;
       
  1686 
       
  1687 	for( TInt by=0; by<blh; by++ )
       
  1688 		{
       
  1689 
       
  1690 		if( iRandomScanned )
       
  1691 			{
       
  1692 			TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
       
  1693 			TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
       
  1694 			TJpegBlock& blk = iBlock[ blkNum ];
       
  1695 
       
  1696 			iBuf = blk.iBuf;
       
  1697 			iBufBits = blk.iBufBits;
       
  1698 			iBufPos = blk.iOffset;
       
  1699 			c[ 0 ] = blk.iY;
       
  1700 			c[ 1 ] = blk.iU;
       
  1701 			c[ 2 ] = blk.iV;
       
  1702 			iRst = false;
       
  1703 			}
       
  1704 
       
  1705 		//TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
       
  1706 
       
  1707 		for( TInt bx=0; bx<blw; bx++ )
       
  1708 			{
       
  1709 			iYuvConv.iRgb = rgb + bx * bw;
       
  1710 			iYuvConv.iRgb += by * bh * w;
       
  1711 
       
  1712 			if( iRst )
       
  1713 				{
       
  1714 				iRst = false;
       
  1715 				iBuf = 0;
       
  1716 				iBufBits = 0;
       
  1717 				
       
  1718 				c[ 0 ] = 0;
       
  1719 				c[ 1 ] = 0;
       
  1720 				c[ 2 ] = 0;
       
  1721 				}
       
  1722 			//blockNum++;
       
  1723 
       
  1724 
       
  1725 			
       
  1726 			///////////
       
  1727 			TInt x;
       
  1728 			TInt y;
       
  1729 			TInt xx;
       
  1730 			TInt yy;
       
  1731 			TInt* p;
       
  1732 
       
  1733 			for( TInt i=0; i<iNumComponents; i++ )
       
  1734 				{
       
  1735 				iCurrentQt = iQt[ KQuantIndex[ i ] ];	
       
  1736 				xx = iComponent[ i ].iXFactor;
       
  1737 				yy = iComponent[ i ].iYFactor;
       
  1738 				TInt dw = xx * 4;
       
  1739 				p = iBlk;
       
  1740 				iDct[ 0 ] = c[ i ];
       
  1741 
       
  1742 				
       
  1743 				for( y=0; y<yy; y++ )
       
  1744 					{
       
  1745 					for( x=0; x<xx; x++ )
       
  1746 						{
       
  1747 						iCurrentHuffman = KHuffIndex[ i ];
       
  1748 						DecodeBlock3();
       
  1749 						TUint8* tp = iC[ i ] + x*4 + y*4 * dw;
       
  1750 						
       
  1751 						//
       
  1752 						// 4x4 Idct
       
  1753 						//
       
  1754 						IdctHalf();
       
  1755 
       
  1756 						for( TInt ty=0; ty<4; ty++ )
       
  1757 							{
       
  1758 							for( TInt tx=0; tx<4; tx++ )
       
  1759 								{
       
  1760 								tp[ tx + ty * dw ] = p[ tx + ty*4 ];
       
  1761 								}
       
  1762 							}
       
  1763 						}
       
  1764 					}
       
  1765 				
       
  1766 
       
  1767 				c[ i ] = iDct[ 0 ];
       
  1768 				}
       
  1769 
       
  1770 			//
       
  1771 			// Scaled blit YUV->RGB
       
  1772 			//
       
  1773 			if( iRgbConv )
       
  1774 				{
       
  1775 				iYuv2rgbFunc( this );
       
  1776 				}
       
  1777 
       
  1778 
       
  1779 			}
       
  1780 		}
       
  1781 	}
       
  1782 
       
  1783 
       
  1784 
       
  1785 void CJpeg::DecRgb1_4L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
       
  1786 	{
       
  1787 	PrepareLoadBlockL();
       
  1788 
       
  1789 	//
       
  1790 	// Set file read position
       
  1791 	//
       
  1792 	iBufPos = iImageDataStart;
       
  1793 	iBufBits = 0;
       
  1794 	iBuf = 0;
       
  1795 
       
  1796 	TInt c[ 3 ];
       
  1797 	c[ 0 ] = 0;
       
  1798 	c[ 1 ] = 0;
       
  1799 	c[ 2 ] = 0;
       
  1800 
       
  1801 	TInt w = aBitmap.iSize.iWidth;
       
  1802 	TUint32* rgb = (TUint32*)aBitmap.iData;
       
  1803 
       
  1804 	TInt bw = iData.iBlockSize.iWidth / 4;
       
  1805 	TInt bh = iData.iBlockSize.iHeight / 4;
       
  1806 	//
       
  1807 	// Store data for yuv->rgb conversion
       
  1808 	//
       
  1809 	iYuvConv.iBlkSize = TSize( bw, bh );
       
  1810 	iYuvConv.iRgbWidth = w;
       
  1811 	iYuvConv.iBlkPixels = 2;
       
  1812 
       
  1813 	TInt blw = aBlockRect.Size().iWidth;
       
  1814 	TInt blh = aBlockRect.Size().iHeight;
       
  1815 
       
  1816 	for( TInt by=0; by<blh; by++ )
       
  1817 		{
       
  1818 
       
  1819 		if( iRandomScanned )
       
  1820 			{
       
  1821 			TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
       
  1822 			TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
       
  1823 			TJpegBlock& blk = iBlock[ blkNum ];
       
  1824 
       
  1825 			iBuf = blk.iBuf;
       
  1826 			iBufBits = blk.iBufBits;
       
  1827 			iBufPos = blk.iOffset;
       
  1828 			c[ 0 ] = blk.iY;
       
  1829 			c[ 1 ] = blk.iU;
       
  1830 			c[ 2 ] = blk.iV;
       
  1831 			iRst = false;
       
  1832 			}
       
  1833 
       
  1834 		//TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
       
  1835 		
       
  1836 		for( TInt bx=0; bx<blw; bx++ )
       
  1837 			{
       
  1838 			iYuvConv.iRgb = rgb + bx * bw;
       
  1839 			iYuvConv.iRgb += by * bh * w;
       
  1840 
       
  1841 			if( iRst )
       
  1842 				{
       
  1843 				iRst = false;
       
  1844 				iBuf = 0;
       
  1845 				iBufBits = 0;
       
  1846 				
       
  1847 				c[ 0 ] = 0;
       
  1848 				c[ 1 ] = 0;
       
  1849 				c[ 2 ] = 0;
       
  1850 				}
       
  1851 			//blockNum++;
       
  1852 
       
  1853 			
       
  1854 			TInt x;
       
  1855 			TInt y;
       
  1856 			TInt xx;
       
  1857 			TInt yy;
       
  1858 
       
  1859 			for( TInt i=0; i<iNumComponents; i++ )
       
  1860 				{
       
  1861 				iCurrentQt = iQt[ KQuantIndex[ i ] ];	
       
  1862 				xx = iComponent[ i ].iXFactor;
       
  1863 				yy = iComponent[ i ].iYFactor;
       
  1864 				TInt dw = xx * 2;
       
  1865 				iDct[ 0 ] = c[ i ];
       
  1866 
       
  1867 				for( y=0; y<yy; y++ )
       
  1868 					{
       
  1869 					for( x=0; x<xx; x++ )
       
  1870 						{
       
  1871 						iCurrentHuffman = KHuffIndex[ i ];
       
  1872 						DecodeBlock3();
       
  1873 						TUint8* tp = iC[ i ] + x*2 + y*2 * dw;
       
  1874 						
       
  1875 						//
       
  1876 						// 2x2 Idct
       
  1877 						//
       
  1878 						TInt v0 = 181*iDct[1];
       
  1879 						TInt v1 = 32761 * iDct[ 0 ];
       
  1880 						TInt v2 = 45431 * iDct[ 8 ];
       
  1881 						TInt v3 = -9050 * iDct[ 8 ];
       
  1882 						TInt v4 = v0 + 251*iDct[9];
       
  1883 						TInt v5 = v0 -  50*iDct[9];
       
  1884 										
       
  1885 						TInt v = (v1 + v2 + 251*v4 ) / 262144 + 128;
       
  1886 						if( v<0 ) v=0; if( v>255 ) v=255; tp[ 0 ] = v;
       
  1887 
       
  1888 						v = (v1 + v2 -  50*v4 ) / 262144 + 128;
       
  1889 						if( v<0 ) v=0; if( v>255 ) v=255; tp[ dw ] = v;
       
  1890 
       
  1891 						v = (v1 + v3 + 251*v5 ) / 262144 + 128;
       
  1892 						if( v<0 ) v=0; if( v>255 ) v=255; tp[ 1 ] = v;
       
  1893 
       
  1894 						v = (v1 + v3 -  50*v5 ) / 262144 + 128;
       
  1895 						if( v<0 ) v=0; if( v>255 ) v=255; tp[ dw+1 ] = v;
       
  1896 						}
       
  1897 					}
       
  1898 				c[ i ] = iDct[ 0 ];
       
  1899 				}
       
  1900 
       
  1901 
       
  1902 			//
       
  1903 			// Scaled blit YUV->RGB
       
  1904 			//
       
  1905 			if( iRgbConv )
       
  1906 				{
       
  1907 				iYuv2rgbFunc( this );
       
  1908 				}
       
  1909 
       
  1910 
       
  1911 			}
       
  1912 		}
       
  1913 	}
       
  1914 
       
  1915 
       
  1916 
       
  1917 void CJpeg::DecRgb1_8L( const TBitmapHandle& aBitmap, const TRect& aBlockRect )
       
  1918 	{
       
  1919 	PrepareLoadBlockL();
       
  1920 
       
  1921 	//
       
  1922 	// Set file read position
       
  1923 	//
       
  1924 	iBufPos = iImageDataStart;
       
  1925 	iBufBits = 0;
       
  1926 	iBuf = 0;
       
  1927 
       
  1928 	TInt c[ 3 ];
       
  1929 	c[ 0 ] = 0;
       
  1930 	c[ 1 ] = 0;
       
  1931 	c[ 2 ] = 0;
       
  1932 
       
  1933 	TInt w = aBitmap.iSize.iWidth;
       
  1934 	TUint32* rgb = (TUint32*)aBitmap.iData;
       
  1935 
       
  1936 	TInt bw = iData.iBlockSize.iWidth / 8;
       
  1937 	TInt bh = iData.iBlockSize.iHeight / 8;
       
  1938 	
       
  1939 	//
       
  1940 	// Store data for yuv->rgb conversion
       
  1941 	//
       
  1942 	iYuvConv.iBlkSize = TSize( bw, bh );
       
  1943 	iYuvConv.iRgbWidth = w;
       
  1944 	iYuvConv.iBlkPixels = 1;
       
  1945 
       
  1946 	TInt blw = aBlockRect.Size().iWidth;
       
  1947 	TInt blh = aBlockRect.Size().iHeight;
       
  1948 
       
  1949 	for( TInt by=0; by<blh; by++ )
       
  1950 		{
       
  1951 
       
  1952 		if( iRandomScanned )
       
  1953 			{
       
  1954 			TPoint pos( aBlockRect.iTl.iX, aBlockRect.iTl.iY + by );
       
  1955 			TInt blkNum = pos.iX + pos.iY * iData.iSizeInBlocks.iWidth;
       
  1956 			TJpegBlock& blk = iBlock[ blkNum ];
       
  1957 
       
  1958 			iBuf = blk.iBuf;
       
  1959 			iBufBits = blk.iBufBits;
       
  1960 			iBufPos = blk.iOffset;
       
  1961 			c[ 0 ] = blk.iY;
       
  1962 			c[ 1 ] = blk.iU;
       
  1963 			c[ 2 ] = blk.iV;
       
  1964 			iRst = false;
       
  1965 			}
       
  1966 
       
  1967 		//TInt blockNum = aBlockRect.iTl.iX + ( aBlockRect.iTl.iY + by ) * iData.iSizeInBlocks.iWidth;
       
  1968 
       
  1969 		for( TInt bx=0; bx<blw; bx++ )
       
  1970 			{
       
  1971 			iYuvConv.iRgb = rgb + bx * bw;
       
  1972 			iYuvConv.iRgb += by * bh * w;
       
  1973 
       
  1974 			if( iRst )
       
  1975 				{
       
  1976 				iRst = false;
       
  1977 				iBuf = 0;
       
  1978 				iBufBits = 0;
       
  1979 				
       
  1980 				c[ 0 ] = 0;
       
  1981 				c[ 1 ] = 0;
       
  1982 				c[ 2 ] = 0;
       
  1983 				}
       
  1984 			//blockNum++;
       
  1985 
       
  1986 			
       
  1987 			TInt x;
       
  1988 			TInt y;
       
  1989 			TInt xx;
       
  1990 			TInt yy;
       
  1991 
       
  1992 			for( TInt i=0; i<iNumComponents; i++ )
       
  1993 				{
       
  1994 				iCurrentQt = iQt[ KQuantIndex[ i ] ];	
       
  1995 				xx = iComponent[ i ].iXFactor;
       
  1996 				yy = iComponent[ i ].iYFactor;
       
  1997 				TInt dw = xx * 1;
       
  1998 				iDct[ 0 ] = c[ i ];
       
  1999 
       
  2000 				for( y=0; y<yy; y++ )
       
  2001 					{
       
  2002 					for( x=0; x<xx; x++ )
       
  2003 						{
       
  2004 						iCurrentHuffman = KHuffIndex[ i ];
       
  2005 						DecodeBlock3();
       
  2006 						TUint8* tp = iC[ i ] + x*1 + y*1 * dw;
       
  2007 
       
  2008 						*tp = iDct[ 0 ] / 8 + 128;
       
  2009 						}
       
  2010 					}
       
  2011 				c[ i ] = iDct[ 0 ];
       
  2012 				}
       
  2013 
       
  2014 			//
       
  2015 			// Scaled blit YUV->RGB
       
  2016 			//
       
  2017 			if( iRgbConv )
       
  2018 				{
       
  2019 				iYuv2rgbFunc( this );
       
  2020 				}
       
  2021 
       
  2022 			}
       
  2023 		}
       
  2024 	}
       
  2025 
       
  2026 
       
  2027 
       
  2028 void CJpeg::SetScale( TJpegScale aScale )
       
  2029 	{
       
  2030 	iScale = aScale;
       
  2031 	}
       
  2032 
       
  2033 
       
  2034 
       
  2035 void CJpeg::Yuv2Rgb22_11_11( TAny* aPtr )
       
  2036 	{
       
  2037 	CJpeg& p = *(CJpeg*)aPtr;
       
  2038 	
       
  2039 	//
       
  2040 	// YUV420
       
  2041 	//
       
  2042 	// YY
       
  2043 	// YY U V
       
  2044 	//
       
  2045 	
       
  2046 	TUint8* cY = p.iC[ 0 ];
       
  2047 	TUint8* cU = p.iC[ 1 ];
       
  2048 	TUint8* cV = p.iC[ 2 ];
       
  2049 	TUint32* rgb = p.iYuvConv.iRgb;
       
  2050 	TInt modulo = p.iYuvConv.iRgbWidth - p.iYuvConv.iBlkSize.iWidth;
       
  2051 
       
  2052 	TInt w = p.iYuvConv.iBlkSize.iWidth;
       
  2053 	TInt h = p.iYuvConv.iBlkSize.iHeight;
       
  2054 	
       
  2055 
       
  2056 	for( TInt y=0; y<h; y++ )
       
  2057 		{
       
  2058 		TInt x = 0;
       
  2059 		TInt cu = 0;
       
  2060 		TInt cv = 0;
       
  2061 		for( x=0; x<w; x++ )
       
  2062 			{
       
  2063 			TInt cy = *cY++;
       
  2064 			if( ( x & 1 ) == 0 )
       
  2065 				{
       
  2066 				// when X even, fetch new color components
       
  2067 				cu = *cU++ - 128;
       
  2068 				cv = *cV++ - 128;
       
  2069 				}
       
  2070 			
       
  2071 
       
  2072 			// urgb color
       
  2073 			TUint32 c;
       
  2074 
       
  2075 			// rgb color component
       
  2076 			TInt cc;
       
  2077 			
       
  2078 			// add red
       
  2079 			cc = cy + ( 359 * cv ) / 256;
       
  2080 			if( cc < 0 ) cc = 0;
       
  2081 			if( cc > 255 ) cc = 255;
       
  2082 			c = cc << 16;
       
  2083 
       
  2084 			// add green
       
  2085 			cc = cy - ( 88 * cu  +  183 * cv ) / 256;
       
  2086 			if( cc < 0 ) cc = 0;
       
  2087 			if( cc > 255 ) cc = 255;
       
  2088 			c |= cc << 8;
       
  2089 			
       
  2090 			// add blue
       
  2091 			cc = cy + ( 454 * cu ) / 256;
       
  2092 			if( cc < 0 ) cc = 0;
       
  2093 			if( cc > 255 ) cc = 255;
       
  2094 
       
  2095 			// write to bitmap
       
  2096 			*rgb++ = c + cc;
       
  2097 			
       
  2098 			}
       
  2099 		rgb += modulo;
       
  2100 		if( ( y & 1 ) == 0 )
       
  2101 			{
       
  2102 			// only advance color components on odd Y
       
  2103 			// so on even, do rewind
       
  2104 			cU -= x/2;
       
  2105 			cV -= x/2;
       
  2106 			}
       
  2107 		}	
       
  2108 	}
       
  2109 
       
  2110 
       
  2111 
       
  2112 void CJpeg::Yuv2Rgb21_11_11( TAny* aPtr )
       
  2113 	{
       
  2114 	CJpeg& p = *(CJpeg*)aPtr;
       
  2115 	//
       
  2116 	// YUV422
       
  2117 	//
       
  2118 	// YY U V
       
  2119 	//
       
  2120 
       
  2121 	TUint8* cY = p.iC[ 0 ];
       
  2122 	TUint8* cU = p.iC[ 1 ];
       
  2123 	TUint8* cV = p.iC[ 2 ];
       
  2124 	TUint32* rgb = p.iYuvConv.iRgb;
       
  2125 	TInt modulo = p.iYuvConv.iRgbWidth - p.iYuvConv.iBlkSize.iWidth;
       
  2126 
       
  2127 	TInt w = p.iYuvConv.iBlkSize.iWidth;
       
  2128 	TInt h = p.iYuvConv.iBlkSize.iHeight;
       
  2129 
       
  2130 	for( TInt y=0; y<h; y++ )
       
  2131 		{
       
  2132 		TInt cu = 0;
       
  2133 		TInt cv = 0;
       
  2134 		for( TInt x=0; x<w; x++ )
       
  2135 			{
       
  2136 			TInt cy = *cY++;
       
  2137 			if( ( x & 1 ) == 0 )
       
  2138 				{
       
  2139 				// for every even X, fetch new color components
       
  2140 				cu = *cU++ - 128;
       
  2141 				cv = *cV++ - 128;
       
  2142 				}
       
  2143 
       
  2144 			// urgb color
       
  2145 			TUint32 c;
       
  2146 			
       
  2147 			// rgb color component
       
  2148 			TInt cc;
       
  2149 			
       
  2150 			// add red
       
  2151 			cc = cy + ( 359 * cv ) / 256;
       
  2152 			if( cc < 0 ) cc = 0;
       
  2153 			if( cc > 255 ) cc = 255;
       
  2154 			c = cc << 16;
       
  2155 
       
  2156 			// add green
       
  2157 			cc = cy - ( 88 * cu  +  183 * cv ) / 256;
       
  2158 			if( cc < 0 ) cc = 0;
       
  2159 			if( cc > 255 ) cc = 255;
       
  2160 			c |= cc << 8;
       
  2161 			
       
  2162 			// add blue
       
  2163 			cc = cy + ( 454 * cu ) / 256;
       
  2164 			if( cc < 0 ) cc = 0;
       
  2165 			if( cc > 255 ) cc = 255;
       
  2166 
       
  2167 			// write to bitmap
       
  2168 			*rgb++ = c + cc;
       
  2169 			}
       
  2170 		rgb += modulo;
       
  2171 		}
       
  2172 	}
       
  2173 
       
  2174 
       
  2175 
       
  2176 void CJpeg::Yuv2RgbFree( TAny* aPtr )
       
  2177 	{
       
  2178 	CJpeg& p = *(CJpeg*)aPtr;
       
  2179 
       
  2180 	TInt bw = p.iYuvConv.iBlkSize.iWidth;
       
  2181 	TInt bh = p.iYuvConv.iBlkSize.iHeight;
       
  2182 	
       
  2183 	TInt y1y = 0;
       
  2184 	TInt y1u = 0;
       
  2185 	TInt y1v = 0;
       
  2186 
       
  2187 	TInt yw = p.iComponent[ 0 ].iXFactor * p.iYuvConv.iBlkPixels; 
       
  2188 	TInt uw = p.iComponent[ 1 ].iXFactor * p.iYuvConv.iBlkPixels;
       
  2189 	TInt vw = p.iComponent[ 2 ].iXFactor * p.iYuvConv.iBlkPixels;
       
  2190 	
       
  2191 	TUint32* rgb = p.iYuvConv.iRgb;
       
  2192 	TInt modulo = p.iYuvConv.iRgbWidth - bw;
       
  2193 	
       
  2194 	for( TInt y=0; y<bh; y++ )
       
  2195 		{
       
  2196 		TInt txy = 0;
       
  2197 		TInt txu = 0;
       
  2198 		TInt txv = 0;
       
  2199 		TUint8* ccy = p.iC[ 0 ] + ( y1y/256 ) * yw;
       
  2200 		TUint8* ccu = p.iC[ 1 ] + ( y1u/256 ) * uw;
       
  2201 		TUint8* ccv = p.iC[ 2 ] + ( y1v/256 ) * vw;
       
  2202 
       
  2203 		for( TInt x=0; x<bw; x++ )
       
  2204 			{
       
  2205 
       
  2206 			TInt cy = ccy[ txy / 256 ];
       
  2207 			TInt cu = ccu[ txu / 256 ] - 128;
       
  2208 			TInt cv = ccv[ txv / 256 ] - 128;
       
  2209 			
       
  2210 			txy += p.iYxa;
       
  2211 			txu += p.iUxa;
       
  2212 			txv += p.iVxa;
       
  2213 
       
  2214 			// urgb color
       
  2215 			TUint32 c;
       
  2216 			
       
  2217 			// rgb color component
       
  2218 			TInt cc;
       
  2219 			
       
  2220 			// add red
       
  2221 			cc = cy + ( 359 * cv ) / 256;
       
  2222 			if( cc < 0 ) cc = 0;
       
  2223 			if( cc > 255 ) cc = 255;
       
  2224 			c = cc << 16;
       
  2225 
       
  2226 			// add green
       
  2227 			cc = cy - ( 88 * cu  +  183 * cv ) / 256;
       
  2228 			if( cc < 0 ) cc = 0;
       
  2229 			if( cc > 255 ) cc = 255;
       
  2230 			c |= cc << 8;
       
  2231 			
       
  2232 			// add blue
       
  2233 			cc = cy + ( 454 * cu ) / 256;
       
  2234 			if( cc < 0 ) cc = 0;
       
  2235 			if( cc > 255 ) cc = 255;
       
  2236 
       
  2237 			// write to bitmap
       
  2238 			*rgb++ = c + cc;
       
  2239 			}
       
  2240 		y1y += p.iYya;
       
  2241 		y1u += p.iUya;
       
  2242 		y1v += p.iVya;
       
  2243 		rgb += modulo;
       
  2244 		}
       
  2245 	}
       
  2246 
       
  2247 
       
  2248 
       
  2249 
       
  2250 void CJpeg::EnableRgvConv()
       
  2251 	{
       
  2252 	iRgbConv = true;
       
  2253 	}
       
  2254 
       
  2255 
       
  2256 
       
  2257 void CJpeg::DisableRgbConv()
       
  2258 	{
       
  2259 	iRgbConv = false;
       
  2260 	}
       
  2261 
       
  2262 
       
  2263 
       
  2264 TBitmapHandle CJpeg::LoadImageL( TRect& aRect )
       
  2265 	{
       
  2266 	//
       
  2267 	// Crop possible illegal rect
       
  2268 	//
       
  2269 	//aRect.BoundingRect( TRect( iData.iSize ) );
       
  2270 	
       
  2271 	if( aRect.iTl.iX < 0 ) aRect.iTl.iX = 0;
       
  2272 	if( aRect.iTl.iY < 0 ) aRect.iTl.iY = 0;
       
  2273 	if( aRect.iBr.iX < 0 ) aRect.iBr.iX = 0;
       
  2274 	if( aRect.iBr.iY < 0 ) aRect.iBr.iY = 0;
       
  2275 	if( aRect.iTl.iX > iData.iSize.iWidth ) aRect.iTl.iX = iData.iSize.iWidth;
       
  2276 	if( aRect.iTl.iY > iData.iSize.iHeight ) aRect.iTl.iY = iData.iSize.iHeight;
       
  2277 	if( aRect.iBr.iX > iData.iSize.iWidth ) aRect.iBr.iX = iData.iSize.iWidth;
       
  2278 	if( aRect.iBr.iY > iData.iSize.iHeight ) aRect.iBr.iY = iData.iSize.iHeight;
       
  2279 	
       
  2280 	//
       
  2281 	// Create rectangle of blocks that has all the pixels of aRect
       
  2282 	//
       
  2283 	TRect blockRect = aRect;
       
  2284 	blockRect.iTl.iX /= iData.iBlockSize.iWidth;
       
  2285 	blockRect.iBr.iX /= iData.iBlockSize.iWidth;
       
  2286 	blockRect.iTl.iY /= iData.iBlockSize.iHeight;
       
  2287 	blockRect.iBr.iY /= iData.iBlockSize.iHeight;
       
  2288 	
       
  2289 	if( aRect.iBr.iX & ( iData.iBlockSize.iWidth - 1 ) )
       
  2290 		{
       
  2291 		blockRect.iBr.iX++;
       
  2292 		}
       
  2293 
       
  2294 	if( aRect.iBr.iY & ( iData.iBlockSize.iHeight - 1 ) )
       
  2295 		{
       
  2296 		blockRect.iBr.iY++;
       
  2297 		}
       
  2298 
       
  2299 	//
       
  2300 	// Return the real 1:1 scale pixel rectangle back in aRect
       
  2301 	//
       
  2302 	aRect.iTl.iX = blockRect.iTl.iX * iData.iBlockSize.iWidth;
       
  2303 	aRect.iTl.iY = blockRect.iTl.iY * iData.iBlockSize.iHeight;
       
  2304 	aRect.iBr.iX = blockRect.iBr.iX * iData.iBlockSize.iWidth;
       
  2305 	aRect.iBr.iY = blockRect.iBr.iY * iData.iBlockSize.iHeight;
       
  2306 
       
  2307 
       
  2308 	// decode area size in blocks
       
  2309 	TSize blockSize = blockRect.Size();
       
  2310 
       
  2311 	// create bitmap
       
  2312 	TBitmapHandle bm;
       
  2313 	bm.iSize.iWidth = iData.iBlockSize.iWidth * blockSize.iWidth;
       
  2314 	bm.iSize.iHeight = iData.iBlockSize.iHeight * blockSize.iHeight;
       
  2315 	
       
  2316 	//
       
  2317 	// If not whole image decode, random access must be initialized
       
  2318 	//
       
  2319 	if( iData.iSizeInBlocks != blockSize )
       
  2320 		{
       
  2321 		ScanRandomL();
       
  2322 		}
       
  2323 
       
  2324 	//
       
  2325 	// ...and decode
       
  2326 	//
       
  2327 	switch( iScale )
       
  2328 		{
       
  2329 		case EScale1:
       
  2330 			{
       
  2331 			bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
       
  2332 			CleanupStack::PushL( bm.iData );
       
  2333 			DecRgb1_1L( bm, blockRect );
       
  2334 			CleanupStack::Pop( bm.iData );
       
  2335 			break;
       
  2336 			}
       
  2337 		case EScale2:
       
  2338 			{
       
  2339 			bm.iSize.iWidth /= 2;
       
  2340 			bm.iSize.iHeight /= 2;
       
  2341 			bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
       
  2342 			CleanupStack::PushL( bm.iData );
       
  2343 			DecRgb1_2L( bm, blockRect );
       
  2344 			CleanupStack::Pop( bm.iData );
       
  2345 			break;
       
  2346 			}
       
  2347 		case EScale4:
       
  2348 			{
       
  2349 			bm.iSize.iWidth /= 4;
       
  2350 			bm.iSize.iHeight /= 4;
       
  2351 			bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
       
  2352 			CleanupStack::PushL( bm.iData );
       
  2353 			DecRgb1_4L( bm, blockRect );
       
  2354 			CleanupStack::Pop( bm.iData );
       
  2355 			break;
       
  2356 			}
       
  2357 		case EScale8:
       
  2358 			{
       
  2359 			bm.iSize.iWidth /= 8;
       
  2360 			bm.iSize.iHeight /= 8;
       
  2361 			bm.iData = new( ELeave )TUint32[ bm.iSize.iWidth * bm.iSize.iHeight ];
       
  2362 			CleanupStack::PushL( bm.iData );
       
  2363 			DecRgb1_8L( bm, blockRect );
       
  2364 			CleanupStack::Pop( bm.iData );
       
  2365 			break;
       
  2366 			}
       
  2367 		}
       
  2368 
       
  2369 	return bm;
       
  2370 	}