imageeditorengine/JpegRotator/src/CJpRotate.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 
       
    22 
       
    23 #include "CJpRotate.h"
       
    24 #include "MJpRotateCallBack.h"
       
    25 #include "CExifParser.h"
       
    26 
       
    27 const TUint8 KZigZag[] = {
       
    28 						0,8,1,2,9,16,24,17,
       
    29 						10,3,4,11,18,25,32,40,
       
    30 						33,26,19,12,5,6,13,20,
       
    31 						27,34,41,48,56,49,42,35,
       
    32 						28,21,14,7,15,22,29,36,
       
    33 						43,50,57,58,51,44,37,30,
       
    34 						23,31,38,45,52,59,60,53,
       
    35 						46,39,47,54,61,62,55,63
       
    36 						};
       
    37 
       
    38 const TUint8 KReZig[] = {
       
    39 						0,2,1,5,4,3,9,8,
       
    40 						7,6,14,13,12,11,10,20,
       
    41 						19,18,17,16,15,27,26,25,
       
    42 						24,23,22,21,35,34,33,32,
       
    43 						31,30,29,28,42,41,40,39,
       
    44 						38,37,36,48,47,46,45,44,
       
    45 						43,53,52,51,50,49,57,56,
       
    46 						55,54,60,59,58,62,61,63 
       
    47 						};
       
    48 
       
    49 
       
    50 
       
    51 
       
    52 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
       
    53 /* IMPORTANT: these are only valid for 8-bit data precision! */
       
    54 
       
    55 const TUint8 bits_dc_luminance[17] =
       
    56 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
       
    57 const TUint8 val_dc_luminance[] =
       
    58 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    59 
       
    60 const TUint8 bits_dc_chrominance[17] =
       
    61 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
       
    62 const TUint8 val_dc_chrominance[] =
       
    63 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    64 
       
    65 const TUint8 bits_ac_luminance[17] =
       
    66 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
       
    67 const TUint8 val_ac_luminance[] =
       
    68 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
       
    69   0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
       
    70   0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
       
    71   0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
       
    72   0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
       
    73   0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
       
    74   0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
       
    75   0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
       
    76   0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
       
    77   0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
       
    78   0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
       
    79   0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
       
    80   0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
       
    81   0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
       
    82   0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
       
    83   0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
       
    84   0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
       
    85   0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
       
    86   0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
       
    87   0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
    88   0xf9, 0xfa 
       
    89 };
       
    90 
       
    91 const TUint8 bits_ac_chrominance[17] =
       
    92 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
       
    93 
       
    94 const TUint8 val_ac_chrominance[] =
       
    95 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
       
    96   0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
       
    97   0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
       
    98   0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
       
    99   0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
       
   100   0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
       
   101   0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
       
   102   0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
       
   103   0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
       
   104   0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
       
   105   0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
       
   106   0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
       
   107   0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
       
   108   0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
       
   109   0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
       
   110   0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
       
   111   0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
       
   112   0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
       
   113   0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
       
   114   0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
   115   0xf9, 0xfa 
       
   116 };
       
   117 
       
   118 const TUint8 KExifHeader[] = "Exif";
       
   119 
       
   120 class THuffman
       
   121 	{
       
   122 	public:
       
   123 		TInt8 iLength[ 256 ];
       
   124 		TUint8 iSymbol[ 256 ];
       
   125 		TUint8 iSearch[ 65536 ];
       
   126 	};
       
   127 
       
   128 
       
   129 CJpRotate* CJpRotate::NewL( RFs& aFs, RFile* aSaveFile, TInt aSaveBufSize )
       
   130 	{
       
   131 	CJpRotate* self = NewLC( aFs, aSaveFile, aSaveBufSize );
       
   132 	CleanupStack::Pop( self );
       
   133 	return self;
       
   134 	}
       
   135 
       
   136 
       
   137 CJpRotate* CJpRotate::NewLC( RFs& aFs, RFile* aSaveFile, TInt aSaveBufSize )
       
   138 	{
       
   139 	CJpRotate* self = new( ELeave )CJpRotate( aFs, aSaveFile, aSaveBufSize );
       
   140 	CleanupStack::PushL( self );
       
   141 	self->ConstructL();
       
   142 	return self;
       
   143 	}
       
   144 
       
   145 
       
   146 CJpRotate::~CJpRotate()
       
   147 	{
       
   148 	delete iHuffman[ 0 ];
       
   149 	delete iHuffman[ 1 ];
       
   150 	delete iHuffman[ 2 ];
       
   151 	delete iHuffman[ 3 ];
       
   152 
       
   153 	delete iSaveHuffman[ 0 ];
       
   154 	delete iSaveHuffman[ 1 ];
       
   155 	delete iSaveHuffman[ 2 ];
       
   156 	delete iSaveHuffman[ 3 ];
       
   157 
       
   158 	delete iQt[ 0 ];
       
   159 	delete iQt[ 1 ];
       
   160 	delete iQt[ 2 ];
       
   161 	delete iQt[ 3 ];
       
   162 
       
   163 	if( iOwnBuffer )
       
   164 		{
       
   165 		delete iBuffer;
       
   166 		}
       
   167 	delete iSaveBuf;
       
   168 	iBasicBlock.Reset();
       
   169 
       
   170 	if( &iSaveFile != NULL )
       
   171 		{
       
   172 		iSaveFile.Flush();
       
   173 		iSaveFile.Close();
       
   174 		}
       
   175 	}
       
   176 
       
   177 CJpRotate::CJpRotate( RFs& aFs, RFile* aSaveFile, TInt aSaveBufSize )
       
   178 	: iCancelled(EFalse)
       
   179 	, iFs( aFs )
       
   180 	, iSaveFile( *aSaveFile )
       
   181 	, iSaveBufSize( aSaveBufSize )
       
   182 	{
       
   183 
       
   184 	}
       
   185 
       
   186 void CJpRotate::ConstructL()
       
   187 	{
       
   188 	}
       
   189 
       
   190 
       
   191 
       
   192 void CJpRotate::SetCallBack( MJpRotateCallBack* aCallBack )
       
   193 	{
       
   194 	iCallBack = aCallBack;
       
   195 	}
       
   196 		
       
   197 void CJpRotate::Cancel()
       
   198     {
       
   199     iCancelled = ETrue;
       
   200     }
       
   201 
       
   202 
       
   203 
       
   204 void CJpRotate::RotateL( const TFileName& aFile, TBool aRotate, TBool aFlip, TBool aMirror )
       
   205 	{
       
   206 	
       
   207 	iCancelled = EFalse;
       
   208 	
       
   209 	if (iBuffer)
       
   210 	{
       
   211 		delete iBuffer;
       
   212 		iBuffer = NULL;		
       
   213 	}
       
   214 	
       
   215 	RFile file;
       
   216 	TInt err = file.Open( iFs, aFile, EFileRead | EFileShareReadersOnly );
       
   217 	if (KErrNone != err)
       
   218 		{
       
   219 		User::LeaveIfError( file.Open( iFs, aFile, EFileRead | EFileShareAny ) );
       
   220 		}
       
   221 	CleanupClosePushL( file );
       
   222 	
       
   223 	TInt size;
       
   224 	file.Size( size );
       
   225 	iOwnBuffer = true;
       
   226 	iBuffer = new( ELeave )TUint8[ size + 2 ];
       
   227 	TPtr8 ptr( iBuffer, size );
       
   228 	file.Read( ptr );
       
   229 	
       
   230 	CleanupStack::PopAndDestroy( 1 ); // file
       
   231 	RotateL( ptr, aRotate, aFlip, aMirror );
       
   232 	}
       
   233 
       
   234 
       
   235 
       
   236 void CJpRotate::RotateL( const TPtrC8& aData, TPtrC8& aTarget, TBool aRotate, TBool aFlip, TBool aMirror )
       
   237 	{
       
   238 	iOwnBuffer = false;
       
   239 	RotateL( aData, aRotate, aFlip, aMirror );
       
   240 
       
   241 	aTarget.Set( iSaveBuf, iSaveBufPos );
       
   242 	}
       
   243 
       
   244 
       
   245 
       
   246 void CJpRotate::RotateL( const TPtrC8& aData, TBool aRotate, TBool aFlip, TBool aMirror )
       
   247 	{
       
   248 	
       
   249 	iFlip = aFlip;
       
   250 	iMirror = aMirror;
       
   251 	iRotate = aRotate;
       
   252 	if( iRotate )
       
   253 		{
       
   254 		if( iFlip )
       
   255 			{
       
   256 			iFlip = false;
       
   257 			}
       
   258 		else
       
   259 			{
       
   260 			iFlip = true;
       
   261 			}
       
   262 		}
       
   263 	
       
   264 	
       
   265 	iBuffer = (TUint8*)aData.Ptr();
       
   266 
       
   267 	iSaveBuf = new( ELeave )TUint8[ iSaveBufSize ];
       
   268 	//Mem::FillZ( iSaveBuf, iS );
       
   269 	iSaveByte = 0;
       
   270 	iSaveBufPos = 0;
       
   271 	iSaveBufBitPos = 0;
       
   272 	
       
   273 	// if used again, all variables should be cleared
       
   274 	iBuf = 0;
       
   275 	iBufBits = 0;
       
   276 	
       
   277 	delete iHuffman[ 0 ];
       
   278 	delete iHuffman[ 1 ];
       
   279 	delete iHuffman[ 2 ];
       
   280 	delete iHuffman[ 3 ];
       
   281 	iHuffman[ 0 ] = 0;
       
   282 	iHuffman[ 1 ] = 0;
       
   283 	iHuffman[ 2 ] = 0;
       
   284 	iHuffman[ 3 ] = 0;
       
   285 	//CreateDefaultHuffmanL();
       
   286 
       
   287 
       
   288 	iQt[ 0 ] = 0;
       
   289 	iQt[ 1 ] = 0;
       
   290 	iQt[ 2 ] = 0;
       
   291 	iQt[ 3 ] = 0;
       
   292 
       
   293 
       
   294 	TBool moreChunks = ETrue;
       
   295 	TBool possibleChunk = EFalse;
       
   296 
       
   297 	while( moreChunks )
       
   298 		{
       
   299 		if (iCancelled)
       
   300 		    {
       
   301 		    return;
       
   302 		    }
       
   303 		    
       
   304 		TUint8 b = iBuffer[ iBufPos++ ];
       
   305 		if( possibleChunk )
       
   306 			{
       
   307 			possibleChunk = EFalse;
       
   308 			switch( b )
       
   309 				{
       
   310 				case 0xd8: // start of image
       
   311 					{
       
   312 					WriteSaveBuffer( (TUint16)0xffd8 );
       
   313 					break;
       
   314 					}
       
   315 				case 0xe0: // JFIF application segment
       
   316 					{
       
   317 					WriteSaveBuffer( (TUint16)0xffe0 );
       
   318 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   319 					WriteSaveBuffer( (TUint16)l );
       
   320 					WriteSaveBuffer( iBuffer + iBufPos, l-2 );
       
   321 					iBufPos += l-2;
       
   322 					break;
       
   323 					}
       
   324 				case 0xe1: // APP1 segment, possible EXIF
       
   325 					{
       
   326 					
       
   327 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; 
       
   328 					iBufPos += 2;
       
   329 					l -= 2;
       
   330 					
       
   331 					// Check that there is "Exif" header in the data
       
   332 					const TUint8* pos = &iBuffer[ iBufPos ];
       
   333 					if (Mem::Compare(pos, 2, &KExifHeader[0], 2 ))
       
   334 					{
       
   335 						iBufPos += l;
       
   336 						break;
       
   337 					}
       
   338 					
       
   339 					iBufPos += 6;
       
   340 					l -= 6;
       
   341 
       
   342 					iExifData = iBuffer + iBufPos;
       
   343 					iExifDataLength = l;
       
   344 					
       
   345 					CExifParser* p = CExifParser::NewLC();
       
   346 					
       
   347 					TRAP_IGNORE(p->ParseL( TPtrC8( iExifData, iExifDataLength ) ););
       
   348 						
       
   349 					TPtrC8 thumb( p->ThumbData() );
       
   350 					TPtrC8 saveThumb( 0,0 );
       
   351 					TUint8* thumbPtr = 0;
       
   352 					
       
   353 						
       
   354 					if( iRotate )
       
   355 						{
       
   356 						//
       
   357 						// swap width and height ( if exists )
       
   358 						//
       
   359 						if( p->TagExist( CExifParser::ESubIfd, 0xa002 ) &&
       
   360 							p->TagExist( CExifParser::ESubIfd, 0xa003 ) )
       
   361 							{
       
   362 							TUint16 width = p->TagValue( CExifParser::ESubIfd, 0xa002 );
       
   363 							TUint16 height = p->TagValue( CExifParser::ESubIfd, 0xa003 );
       
   364 
       
   365 							p->DeleteTag( CExifParser::ESubIfd, 0xa002 );
       
   366 							p->DeleteTag( CExifParser::ESubIfd, 0xa003 );
       
   367 
       
   368 							p->AddTagL( CExifParser::ESubIfd, 0xa002, height );
       
   369 							p->AddTagL( CExifParser::ESubIfd, 0xa003, width );
       
   370 							}
       
   371 						}
       
   372 
       
   373 					//
       
   374 					// Rotate thumbnail ( if exists )
       
   375 					//
       
   376 					if( thumb.Ptr() )
       
   377 						{
       
   378 						CJpRotate* r = CJpRotate::NewLC( iFs, NULL, 0x10000 );
       
   379 
       
   380 						TPtrC8 target;
       
   381 						r->RotateL( thumb, target, aRotate, aFlip, aMirror );
       
   382 						
       
   383 						thumbPtr = new( ELeave )TUint8[ target.Length() ];
       
   384 						Mem::Copy( thumbPtr, target.Ptr(), target.Length() );
       
   385 						saveThumb.Set( thumbPtr, target.Length() );
       
   386 
       
   387 						CleanupStack::PopAndDestroy( r );
       
   388 						CleanupStack::PushL( thumbPtr );
       
   389 						}
       
   390 
       
   391 
       
   392 					TPtrC8 exif = p->SaveL( saveThumb );
       
   393 					
       
   394 					WriteSaveBuffer( (TUint16)0xffe1 );	// APP1 segment
       
   395 
       
   396 					TUint16 l2 = exif.Length() + 6 + 2; // +header+tagsize
       
   397 					WriteSaveBuffer( l2 );
       
   398 
       
   399 					// exif header is 6 bytes ( 45 78 69 66 00 00 "Exif.." )
       
   400 					WriteSaveBuffer( (TUint8)0x45 );
       
   401 					WriteSaveBuffer( (TUint8)0x78 );
       
   402 					WriteSaveBuffer( (TUint8)0x69 );
       
   403 					WriteSaveBuffer( (TUint8)0x66 );
       
   404 					WriteSaveBuffer( (TUint8)0x00 );
       
   405 					WriteSaveBuffer( (TUint8)0x00 );
       
   406 
       
   407 					WriteSaveBuffer( exif.Ptr(), exif.Length() );
       
   408 
       
   409 					if( thumbPtr )
       
   410 						{
       
   411 						CleanupStack::PopAndDestroy( thumbPtr );
       
   412 						}
       
   413 					CleanupStack::PopAndDestroy( p );
       
   414 
       
   415 
       
   416 					iBufPos += l;
       
   417 					break;
       
   418 					}
       
   419 				case 0xe2:
       
   420 				case 0xe3:
       
   421 				case 0xe4:
       
   422 				case 0xe5:
       
   423 				case 0xe6:
       
   424 				case 0xe7:
       
   425 				case 0xe8:
       
   426 				case 0xe9:
       
   427 				case 0xea:
       
   428 				case 0xeb:
       
   429 				case 0xec:
       
   430 				case 0xed:
       
   431 				case 0xee:
       
   432 				case 0xef:
       
   433 					{
       
   434 					WriteSaveBuffer( (TUint8)0xff );
       
   435 					WriteSaveBuffer( (TUint8)b );
       
   436 					
       
   437 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   438 					WriteSaveBuffer( (TUint16)l );
       
   439 					WriteSaveBuffer( iBuffer + iBufPos, l-2 );
       
   440 					
       
   441 					iBufPos += l-2;
       
   442 					break;
       
   443 					}
       
   444 				case 0xdb: // Quantization table
       
   445 					{
       
   446 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   447 					
       
   448 					WriteSaveBuffer( (TUint16)0xffdb );
       
   449 					WriteSaveBuffer( (TUint16)l );
       
   450 
       
   451 					TInt nqt = l / 65;
       
   452 					TInt i;
       
   453 
       
   454 					// one or more quantization table
       
   455 					for( i=0; i<nqt; i++ )
       
   456 						{
       
   457 						TUint8 t = iBuffer[ iBufPos++ ];
       
   458 						TInt n = t & 15;
       
   459 						WriteSaveBuffer( t );
       
   460 
       
   461 						// not used:
       
   462 						// TInt precision = n >> 4; 
       
   463 
       
   464 						if (iQt[n])
       
   465 						{
       
   466 							delete iQt[ n ];
       
   467 							iQt[ n ] = NULL;
       
   468 						}
       
   469 
       
   470 						iQt[ n ] = new( ELeave )TUint8[ 64 ];
       
   471 						TInt j;
       
   472 						for( j=0; j<64; j++ )
       
   473 							{
       
   474 							iQt[ n ][ j ] = iBuffer[ iBufPos++ ];
       
   475 							}
       
   476 
       
   477 
       
   478 						TUint8 qt[ 64 ];
       
   479 						ConvertQuants( iQt[ n ], qt );
       
   480 						WriteSaveBuffer( qt, 64 );
       
   481 						}
       
   482 
       
   483 
       
   484 					break;
       
   485 					}
       
   486 				case 0xc0: // start of frame ( SOF )
       
   487 					{
       
   488 					TInt length = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   489 					
       
   490 					WriteSaveBuffer( (TUint16)0xffc0 );
       
   491 					WriteSaveBuffer( (TUint16)length );
       
   492 
       
   493 					// not used:
       
   494 					TUint8 precision = iBuffer[ iBufPos ];
       
   495 					WriteSaveBuffer( precision );
       
   496 					iBufPos++; 
       
   497 					
       
   498 					// height
       
   499 					TUint16 h = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   500 					iData.iSize.iHeight = h;
       
   501 					
       
   502 					// width
       
   503 					TUint16 w = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   504 					iData.iSize.iWidth = w;
       
   505 
       
   506 					if( iRotate )
       
   507 						{
       
   508 						WriteSaveBuffer( w );
       
   509 						WriteSaveBuffer( h );
       
   510 						}
       
   511 					else
       
   512 						{
       
   513 						WriteSaveBuffer( h );
       
   514 						WriteSaveBuffer( w );
       
   515 						}
       
   516 					
       
   517 					// component data
       
   518 					iNumComponents = iBuffer[ iBufPos++ ];
       
   519 					WriteSaveBuffer( (TUint8)iNumComponents );
       
   520 					
       
   521 					TInt i;
       
   522 					for( i=0; i<iNumComponents; i++ )
       
   523 						{
       
   524 						TUint8 comp = iBuffer[ iBufPos++ ] - 1;
       
   525 						TUint8 samplingFactor = iBuffer[ iBufPos++ ];
       
   526 						TUint8 quantizationTable = iBuffer[ iBufPos++ ];
       
   527 						iComponent[ comp ].iXFactor = samplingFactor >> 4;
       
   528 						iComponent[ comp ].iYFactor = samplingFactor & 15;
       
   529 						iComponent[ comp ].iQuantTable = quantizationTable;
       
   530 						
       
   531 
       
   532 						comp++;
       
   533 
       
   534 
       
   535 						if( iRotate )
       
   536 							{
       
   537 							samplingFactor = samplingFactor/16 + ( samplingFactor & 15 )*16;
       
   538 							}
       
   539 
       
   540 						WriteSaveBuffer( comp );
       
   541 						WriteSaveBuffer( samplingFactor );
       
   542 						WriteSaveBuffer( quantizationTable );
       
   543 						}
       
   544 					
       
   545 					TInt xBlocks = 0;
       
   546 					TInt yBlocks = 0;
       
   547 
       
   548 					for( i=0; i<iNumComponents; i++ )
       
   549 						{
       
   550 						TInt x = iComponent[ i ].iXFactor;
       
   551 						TInt y = iComponent[ i ].iYFactor;
       
   552 						if( x > xBlocks )
       
   553 							{
       
   554 							xBlocks = x;
       
   555 							}
       
   556 						if( y > yBlocks )
       
   557 							{
       
   558 							yBlocks = y;
       
   559 							}
       
   560 						}
       
   561 					
       
   562 					iData.iBlockSize.iWidth = xBlocks * 8;
       
   563 					iData.iBlockSize.iHeight = yBlocks * 8;
       
   564 
       
   565 					TSize size = iData.iSize;
       
   566 					size.iWidth /= iData.iBlockSize.iWidth;
       
   567 					size.iHeight /= iData.iBlockSize.iHeight;
       
   568 
       
   569 					if( iData.iSize.iWidth & ( iData.iBlockSize.iWidth - 1 ) )
       
   570 						{
       
   571 						size.iWidth++;
       
   572 						}
       
   573 
       
   574 					if( iData.iSize.iHeight & ( iData.iBlockSize.iHeight - 1 ) )
       
   575 						{
       
   576 						size.iHeight++;
       
   577 						}
       
   578 					
       
   579 					iData.iSizeInBlocks = size;
       
   580 
       
   581 
       
   582 					break;
       
   583 					}
       
   584 				case 0xc1:
       
   585 					{
       
   586 					// Extended sequential Jpeg, not supported
       
   587 					User::Leave( KErrNotSupported );
       
   588 					break;
       
   589 					};
       
   590 				case 0xc2:
       
   591 					{
       
   592 					// Progressive DCT jpeg, not supported
       
   593 					User::Leave( KErrNotSupported );
       
   594 					break;
       
   595 					};
       
   596 				case 0xc3:
       
   597 					{
       
   598 					// Lossless ( sequential ) Jpeg, not supported
       
   599 					User::Leave( KErrNotSupported );
       
   600 					break;
       
   601 					};
       
   602 	
       
   603 				case 0xc5:
       
   604 				case 0xc6:
       
   605 				case 0xc7:
       
   606 				case 0xc8:
       
   607 				case 0xc9:
       
   608 				case 0xca:
       
   609 				case 0xcb:
       
   610 				case 0xcc:
       
   611 				case 0xcd:
       
   612 				case 0xce:
       
   613 				case 0xcf:
       
   614 					{
       
   615 					User::Leave( KErrNotSupported );
       
   616 					break;
       
   617 					};
       
   618 				case 0xc4: // huffman table
       
   619 					{
       
   620 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   621 					
       
   622 
       
   623 					//
       
   624 					// Write default huffman tables
       
   625 					//
       
   626 					WriteSaveBuffer( (TUint16)0xffc4 );
       
   627 					TUint16 saveLen = 2+1+16+12+1+16+12+1+16+162+1+16+162;
       
   628 					WriteSaveBuffer( saveLen );
       
   629 					
       
   630 					WriteSaveBuffer( (TUint8)0 );
       
   631 					WriteSaveBuffer( bits_dc_luminance+1, 16 );
       
   632 					WriteSaveBuffer( val_dc_luminance, 12 );
       
   633 					
       
   634 					WriteSaveBuffer( (TUint8)1 );
       
   635 					WriteSaveBuffer( bits_dc_chrominance+1, 16 );
       
   636 					WriteSaveBuffer( val_dc_chrominance, 12 );
       
   637 					
       
   638 					WriteSaveBuffer( (TUint8)16 );
       
   639 					WriteSaveBuffer( bits_ac_luminance+1, 16 );
       
   640 					WriteSaveBuffer( val_ac_luminance, 20*8+2 );
       
   641 					
       
   642 					WriteSaveBuffer( (TUint8)17 );
       
   643 					WriteSaveBuffer( bits_ac_chrominance+1, 16 );
       
   644 					WriteSaveBuffer( val_ac_chrominance, 20*8+2 );
       
   645 					
       
   646 					TInt table = 0;
       
   647 
       
   648 					TInt n = 0;
       
   649 
       
   650 					// one or more huffman tables
       
   651 					while( n<l-2 )
       
   652 						{
       
   653 						THuffman* huff = new( ELeave )THuffman;
       
   654 					
       
   655 						table = iBuffer[ iBufPos++ ];
       
   656 						n++;
       
   657 						TUint8 huffSize[ 16 ];
       
   658 						TInt numSymbols = 0;
       
   659 						TInt i;
       
   660 
       
   661 						for( i=0; i<16; i++ )
       
   662 							{
       
   663 							TInt size = iBuffer[ iBufPos++ ];
       
   664 							huffSize[ i ] = size;
       
   665 							numSymbols += size;
       
   666 							n++;
       
   667 							}
       
   668 						
       
   669 						for( i=0; i<numSymbols; i++ )
       
   670 							{
       
   671 							TUint8 v = iBuffer[ iBufPos++ ];
       
   672 							huff->iSymbol[ i ] = v;
       
   673 							n++;
       
   674 							}
       
   675 
       
   676 						i = ( table & 16 ) / 8 + ( table & 15 );
       
   677 												
       
   678 
       
   679 						// Generate huffman lookup tables ( huffSize, table )
       
   680 
       
   681 
       
   682 						TInt l;
       
   683 						TInt p = 0;
       
   684 						for( l=0; l<16; l++ )
       
   685 							{
       
   686 							for( i=0; i<huffSize[ l ]; i++ )
       
   687 								{
       
   688 								huff->iLength[ p++ ] = l+1;
       
   689 								}
       
   690 							}
       
   691 
       
   692 						TInt code = 0;
       
   693 						huff->iLength[ p ] = 0;
       
   694 						TInt si = huff->iLength[ 0 ];
       
   695 						TInt lastP = p;						
       
   696 						
       
   697 						TInt hc[ 256 ];
       
   698 						p = 0;
       
   699 
       
   700 						while( huff->iLength[ p ] )
       
   701 							{
       
   702 							while( huff->iLength[ p ] == si )
       
   703 								{
       
   704 								hc[ p++ ] = code++;
       
   705 								}
       
   706 							code *= 2;
       
   707 							si++;
       
   708 							}
       
   709 
       
   710 						l = 65536;
       
   711 						for( i=lastP-1; i>=0; i-- )
       
   712 							{
       
   713 							TInt t = 16 - huff->iLength[ i ];
       
   714 							TInt k = hc[ i ] * ( 1 << t );
       
   715 							TInt j;
       
   716 							for( j=k; j<l; j++ )
       
   717 								{
       
   718 								huff->iSearch[ j ] = i;
       
   719 								}
       
   720 							l = k;
       
   721 							}
       
   722 
       
   723 						i = ( table & 16 ) / 8 + ( table & 15 );
       
   724 						delete iHuffman[ i ];						
       
   725 						iHuffman[ i ] = huff;
       
   726 						}
       
   727 
       
   728 					break;
       
   729 					}
       
   730 //
       
   731 				case 0xda: // start of scan ( SOS )
       
   732 					{
       
   733 					// write restart interval before SOS
       
   734 					/*
       
   735 					WriteSaveBuffer( (TUint16)0xffdd );
       
   736 					WriteSaveBuffer( (TUint16)0x0004 );
       
   737 					WriteSaveBuffer( (TUint16)1 ); // reset every (1) macroblock
       
   738 					*/
       
   739 					// SOS now:
       
   740 					WriteSaveBuffer( (TUint16)0xffda );
       
   741 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   742 
       
   743 					WriteSaveBuffer( (TUint16)l );
       
   744 
       
   745 					TInt c1 = 0;
       
   746 					TInt c2 = 0;
       
   747 					TInt c3 = 0;
       
   748 					
       
   749 					TInt numComponents = iBuffer[ iBufPos++ ];
       
   750 					WriteSaveBuffer( (TUint8)3 );
       
   751 					TInt i;
       
   752 					for( i=0; i<numComponents; i++ )
       
   753 						{
       
   754 						TInt componentId = iBuffer[ iBufPos++ ];
       
   755 						TInt componentHt = iBuffer[ iBufPos++ ];
       
   756 						}
       
   757 					WriteSaveBuffer( (TUint8)1 );	// component 1
       
   758 					WriteSaveBuffer( (TUint8)0 );
       
   759 					
       
   760 					WriteSaveBuffer( (TUint8)2 );	// component 2
       
   761 					WriteSaveBuffer( (TUint8)17 );
       
   762 					
       
   763 					WriteSaveBuffer( (TUint8)3 );	// component 3
       
   764 					WriteSaveBuffer( (TUint8)17 );
       
   765 
       
   766 					WriteSaveBuffer( (TUint8)0 );
       
   767 					WriteSaveBuffer( (TUint8)63 );	// dctsize - 1
       
   768 					WriteSaveBuffer( (TUint8)0 );
       
   769 
       
   770 					iBufPos += 3;
       
   771 					
       
   772 					//
       
   773 					// Create default huffman tables for save
       
   774 					//
       
   775 					TSHuffman* huff = new( ELeave )TSHuffman;
       
   776 					CreateSaveHuffmanL( huff, bits_dc_luminance, val_dc_luminance );
       
   777 					iSaveHuffman[ 0 ] = huff;
       
   778 
       
   779 					huff = new( ELeave )TSHuffman;
       
   780 					CreateSaveHuffmanL( huff, bits_dc_chrominance, val_dc_chrominance );
       
   781 					iSaveHuffman[ 1 ] = huff;
       
   782 
       
   783 					huff = new( ELeave )TSHuffman;
       
   784 					CreateSaveHuffmanL( huff, bits_ac_luminance, val_ac_luminance );
       
   785 					iSaveHuffman[ 2 ] = huff;
       
   786 					
       
   787 					huff = new( ELeave )TSHuffman;
       
   788 					CreateSaveHuffmanL( huff, bits_ac_chrominance, val_ac_chrominance );
       
   789 					iSaveHuffman[ 3 ] = huff;
       
   790 
       
   791 					
       
   792 
       
   793 					// decode
       
   794 					
       
   795 					TInt bw = iData.iSizeInBlocks.iWidth;
       
   796 					TInt bh = iData.iSizeInBlocks.iHeight;
       
   797 
       
   798 					TInt bx;
       
   799 					TInt by;
       
   800 
       
   801 					for( by=0; by<bh; by++ )
       
   802 						{
       
   803 						for( bx=0; bx<bw; bx++ )
       
   804 							{
       
   805 							if( iRst )
       
   806 								{
       
   807 								// reset marker zeroes DC-values
       
   808 								c1 = 0;
       
   809 								c2 = 0;
       
   810 								c3 = 0;
       
   811 								iRst = EFalse;
       
   812 								}
       
   813 							
       
   814 							TInt i;
       
   815 							
       
   816 							// go fast trough all huffman data
       
   817 							iCurrentHuffman = 0;
       
   818 							iCurrentQt = iQt[ 0 ];
       
   819 							
       
   820 							// Y-component
       
   821 							TInt n = iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor;
       
   822 							iDct[ 0 ] = c1;
       
   823 							for( i=0; i<n; i++ )
       
   824 								{
       
   825 								DecodeBlock2L();
       
   826 								}
       
   827 							c1 = iDct[ 0 ];
       
   828 
       
   829 							iCurrentHuffman = 1;
       
   830 							
       
   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 								DecodeBlock2L();
       
   839 								}
       
   840 							c2 = iDct[ 0 ];
       
   841 
       
   842 							iCurrentSaveHuffman = iSaveHuffman[ 1 ];
       
   843 							// V-component
       
   844 							n = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
       
   845 							iDct[ 0 ] = c3;
       
   846 							for( i=0; i<n; i++ )
       
   847 								{
       
   848 								DecodeBlock2L();
       
   849 								}
       
   850 							c3 = iDct[ 0 ];
       
   851 
       
   852 							// take care of RST0's leftover bits:
       
   853 							if( iRst )
       
   854 								{
       
   855 								TInt goodBits = ( iBufBits >> 3 ) << 3;
       
   856 								TInt badBits = iBufBits - goodBits;
       
   857 								iBuf <<= badBits;
       
   858 								iBufBits = goodBits;
       
   859 								}
       
   860 							}
       
   861 						}
       
   862 					
       
   863 					moreChunks = EFalse;
       
   864 					
       
   865 					SaveBlocks();
       
   866 
       
   867 					// flush last bits to save buffer
       
   868 					if( iSaveBufBitPos )
       
   869 						{
       
   870 						WriteBits( 0, 8-iSaveBufBitPos );
       
   871 						}
       
   872 
       
   873 					// EOI
       
   874 					
       
   875 
       
   876 
       
   877 					//iSaveBuf[ iSaveBufPos++ ] = 0xff;
       
   878 					//iSaveBuf[ iSaveBufPos++ ] = 0xd9;
       
   879 					WriteSaveBuffer( (TUint16)0xffd9 );
       
   880 
       
   881 					FlushSaveBuf();
       
   882 					
       
   883 
       
   884 					
       
   885 					break;
       
   886 					}
       
   887 				case 0xd9: // end of image ( EOI )
       
   888 					{
       
   889 					// not really used for anything
       
   890 					// will exit if picture data is read.
       
   891 					break;
       
   892 					}				
       
   893 				case 0xdd: // define restart interval
       
   894 					{
       
   895 					//TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; 
       
   896 					iBufPos += 2;
       
   897 					//TInt interval = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; 
       
   898 					iBufPos += 2;
       
   899 					
       
   900 					break;
       
   901 					}
       
   902 				case 0x00: // escaped 0xff
       
   903 					{
       
   904 					// only comes if file is broken somehow
       
   905 					break;
       
   906 					}
       
   907 				case 0xfe: // jpeg comment
       
   908 					{
       
   909 					TInt l = 256 * iBuffer[ iBufPos ] + iBuffer[ iBufPos + 1 ]; iBufPos += 2;
       
   910 					WriteSaveBuffer( (TUint16)0xfffe );
       
   911 					WriteSaveBuffer( (TUint16)l );
       
   912 					WriteSaveBuffer( iBuffer + iBufPos, l-2 );
       
   913 					iBufPos += l-2;
       
   914 					break;
       
   915 					};
       
   916 				default:
       
   917 					{
       
   918 					// unknown block
       
   919 					break;
       
   920 					}
       
   921 				}
       
   922 			}
       
   923 		else if( b == 255 )
       
   924 			{
       
   925 			possibleChunk = ETrue;
       
   926 			}
       
   927 			
       
   928 		}
       
   929 	
       
   930 	}
       
   931 
       
   932 
       
   933 
       
   934 
       
   935 void CJpRotate::BufFwd( TInt aBits )
       
   936 	{
       
   937 	iBuf <<= aBits;
       
   938 	iBufBits -= aBits;
       
   939 	}
       
   940 
       
   941 
       
   942 
       
   943 TInt CJpRotate::BufBits( TInt aBits )
       
   944 	{
       
   945 	if( aBits == 0 ) return 0;
       
   946 	while( iBufBits < aBits )
       
   947 		{
       
   948 		BufLoad8();
       
   949 		}
       
   950 	TInt val = iBuf >> ( 32-aBits );
       
   951 	BufFwd( aBits );
       
   952 	return val;
       
   953 	}
       
   954 
       
   955 
       
   956 
       
   957 TInt CJpRotate::Buf16()
       
   958 	{
       
   959 	while( iBufBits < 16 )
       
   960 		{
       
   961 		BufLoad8();
       
   962 		}
       
   963 	TInt val = iBuf >> ( 32-16 );
       
   964 	return val;
       
   965 	}
       
   966 
       
   967 
       
   968 
       
   969 void CJpRotate::BufLoad8()
       
   970 	{
       
   971 	TInt v;
       
   972 	v = iBuffer[ iBufPos++ ];
       
   973 	if( v == 255 )
       
   974 		{
       
   975 		v = iBuffer[ iBufPos++ ]; // escaped 0xff ?
       
   976 		if( v == 0 )
       
   977 			{
       
   978 			v = 255;
       
   979 			}
       
   980 		else if( v == 0xd9 ) // EOI
       
   981 			{
       
   982 			iEOF = true;
       
   983 			v = 0;
       
   984 			}
       
   985 		else
       
   986 			{
       
   987 			// here we have probably discarded a RST0 or similar
       
   988 			v = iBuffer[ iBufPos++ ];
       
   989 			iRst = ETrue;
       
   990 			}
       
   991 		}
       
   992 
       
   993 	v <<= ( 24 - iBufBits );
       
   994 	iBuf |= v;
       
   995 	iBufBits += 8;
       
   996 	}
       
   997 
       
   998 
       
   999 
       
  1000 void CJpRotate::DecodeBlockL( TInt aDc )
       
  1001 	{
       
  1002 	
       
  1003 	//
       
  1004 	// Dummy version of block decode
       
  1005 	// only traverses through huffman data
       
  1006 	// and collects DC-values
       
  1007 	//
       
  1008 	TInt16 vals[ 64 ];
       
  1009 	TUint16 bits[ 64 ];
       
  1010 	TUint8 lens[ 64 ];
       
  1011 
       
  1012 	Mem::FillZ( vals, 64*2 );
       
  1013 	Mem::FillZ( bits, 64*2 );
       
  1014 	Mem::FillZ( lens, 64 );
       
  1015 
       
  1016 	//for( TInt i=0; i<64; i++ ) lens[ i ] = 255;
       
  1017 
       
  1018 
       
  1019 	THuffman* h = iHuffman[ iCurrentHuffman ];
       
  1020 
       
  1021 	
       
  1022 	TInt k;
       
  1023 	for( k=0; k<64; k++ )
       
  1024 		{
       
  1025 		
       
  1026 		TInt v = Buf16();
       
  1027 		TInt index = h->iSearch[ v ];
       
  1028 		TInt symbol = h->iSymbol[ index ];
       
  1029 		BufFwd( h->iLength[ index ] );
       
  1030 		
       
  1031 		TInt nullCount = 0;
       
  1032 
       
  1033 		if( k>0 )
       
  1034 			{
       
  1035 			nullCount = symbol >> 4;
       
  1036 			symbol &= 15;
       
  1037 			}
       
  1038 	
       
  1039 
       
  1040 		v = BufBits( symbol );
       
  1041 		
       
  1042 		TUint16 currentBits = v;
       
  1043 		
       
  1044 		if( v < ( 1 << ( symbol-1 ) ) )
       
  1045 			{
       
  1046 			v += 1 - ( 1 << symbol );
       
  1047 			}
       
  1048 
       
  1049 
       
  1050 		if( k )
       
  1051 			{
       
  1052 			if( nullCount==0 && v==0 )
       
  1053 				{
       
  1054 				k = 64;
       
  1055 				break;
       
  1056 				}
       
  1057 			else if( nullCount==15 && v==0 )
       
  1058 				{
       
  1059 				k += 15;
       
  1060 				}
       
  1061 			else
       
  1062 				{
       
  1063 				k += nullCount;
       
  1064 				if( k > 63 ) break;
       
  1065 				TInt pos = k;
       
  1066 				if( iRotate ) pos = KReZig[ pos ];
       
  1067 				lens[ pos ] = symbol;
       
  1068 				vals[ pos ] = v;
       
  1069 				bits[ pos ] = currentBits;
       
  1070 				}
       
  1071 			}
       
  1072 		else
       
  1073 			{
       
  1074 			h = iHuffman[ iCurrentHuffman+2 ]; // DC -> AC huffman
       
  1075 
       
  1076 			lens[ 0 ] = symbol;
       
  1077 			vals[ 0 ] = aDc / iCurrentQt[ 0 ];
       
  1078 			//vals[ 0 ] = aDc;
       
  1079 			bits[ 0 ] = currentBits;
       
  1080 			}
       
  1081 		}
       
  1082 	
       
  1083 	
       
  1084 	
       
  1085 	TInt count;
       
  1086 	for( count=63; count>=0; count-- )
       
  1087 		{
       
  1088 		if( lens[ count ] != 0 ) break;
       
  1089 		}
       
  1090 	if( count < 0 ) count = 0;
       
  1091 
       
  1092 	TInt nullCount = 0;
       
  1093 
       
  1094 	//
       
  1095 	// Write DC
       
  1096 	//
       
  1097 		
       
  1098 	TInt value = vals[ 0 ];
       
  1099 	bool minus = false;
       
  1100 	if( value < 0 )
       
  1101 		{
       
  1102 		minus = true;
       
  1103 		value = -value;
       
  1104 		}
       
  1105 	TInt v = value;
       
  1106 	TInt vl = 0;
       
  1107 	
       
  1108 	while( v )
       
  1109 		{
       
  1110 		v >>= 1;
       
  1111 		vl++;
       
  1112 		}
       
  1113 
       
  1114 	if( minus ) 
       
  1115 		{
       
  1116 		TInt a = ( 1 << vl ) - 1;
       
  1117 		value ^= a;
       
  1118 		}
       
  1119 			
       
  1120 	WriteHuffmanL( vl );
       
  1121 	WriteBits( value, vl );
       
  1122 		
       
  1123 	// DC -> AC huffman
       
  1124 	if( iCurrentSaveHuffman == iSaveHuffman[ 0 ] )
       
  1125 		{
       
  1126 		iCurrentSaveHuffman = iSaveHuffman[ 2 ];
       
  1127 		}
       
  1128 	else if( iCurrentSaveHuffman == iSaveHuffman[ 1 ] )
       
  1129 		{
       
  1130 		iCurrentSaveHuffman = iSaveHuffman[ 3 ];
       
  1131 		}
       
  1132 	//
       
  1133 	// Write AC
       
  1134 	//
       
  1135 	for( k=1; k<=count; k++ )
       
  1136 		{
       
  1137 
       
  1138 		if( vals[ k ] == 0 )
       
  1139 			{
       
  1140 			nullCount++;
       
  1141 			if( nullCount == 16 )
       
  1142 				{
       
  1143 				// write nullCount 15 with value 0
       
  1144 				WriteHuffmanL( 15 * 16 );
       
  1145 				nullCount = 0;
       
  1146 				}
       
  1147 			}
       
  1148 		else
       
  1149 			{
       
  1150 			// write bits & nullCount huffman coded
       
  1151 			
       
  1152 			TUint8 neg = 0;
       
  1153 			TInt p = KZigZag[ k ];
       
  1154 			if( p & 8 && iMirror ) neg = 1;
       
  1155 			if( p & 1 && iFlip ) neg ^= 1;
       
  1156 			
       
  1157 			TUint16 b = bits[ k ];
       
  1158 			TInt l = lens[ k ];
       
  1159 			TInt v = vals[ k ];
       
  1160 			if( neg )
       
  1161 				{
       
  1162 				if( v>0 )
       
  1163 					{
       
  1164 					b = v ^ ( ( 1 << l ) - 1 );	
       
  1165 					}
       
  1166 				else
       
  1167 					{
       
  1168 					b = -v;
       
  1169 					}
       
  1170 							
       
  1171 				}
       
  1172 
       
  1173 			WriteHuffmanL( l + nullCount * 16 );
       
  1174 			WriteBits( b,l );
       
  1175 			
       
  1176 			nullCount = 0;
       
  1177 			}
       
  1178 		}
       
  1179 	if( count != 63 )
       
  1180 		{
       
  1181 		WriteHuffmanL( 0 );
       
  1182 		}
       
  1183 
       
  1184 	}
       
  1185 
       
  1186 
       
  1187 
       
  1188 void CJpRotate::DecodeBlock2L()
       
  1189 	{
       
  1190 
       
  1191 	THuffman* h = iHuffman[ iCurrentHuffman ];
       
  1192 
       
  1193 	TInt k;
       
  1194 	
       
  1195 	TJpegBasicBlock bl;
       
  1196 	bl.iOffset = iBufPos;
       
  1197 	bl.iBuf = iBuf;
       
  1198 	bl.iBufBits = iBufBits;
       
  1199 
       
  1200 
       
  1201 	for( k=0; k<64; k++ )
       
  1202 		{
       
  1203 
       
  1204 		TInt v = Buf16();
       
  1205 		TInt index = h->iSearch[ v ];
       
  1206 		TInt symbol = h->iSymbol[ index ];
       
  1207 		BufFwd( h->iLength[ index ] );
       
  1208 		
       
  1209 		TInt nullCount = 0;
       
  1210 		if( k>0 )
       
  1211 			{
       
  1212 			nullCount = symbol >> 4;
       
  1213 			symbol &= 15;
       
  1214 			}
       
  1215 		
       
  1216 		v = BufBits( symbol );
       
  1217 					
       
  1218 		if( v < ( 1 << ( symbol-1 ) ) )
       
  1219 			{
       
  1220 			v += 1 - ( 1 << symbol );
       
  1221 			}
       
  1222 		
       
  1223 		if( k )
       
  1224 			{
       
  1225 			if( nullCount==0 && v==0 )
       
  1226 				{
       
  1227 				k = 64;
       
  1228 				break;
       
  1229 				}
       
  1230 			else if( nullCount==15 && v==0 )
       
  1231 				{
       
  1232 				k += 15;
       
  1233 				}
       
  1234 			else
       
  1235 				{
       
  1236 				k += nullCount;
       
  1237 				}
       
  1238 			}
       
  1239 		else
       
  1240 			{
       
  1241 			iDct[ 0 ] += v * iCurrentQt[ 0 ];
       
  1242 			h = iHuffman[ iCurrentHuffman+2 ];
       
  1243 			}
       
  1244 
       
  1245 		}
       
  1246 
       
  1247 	bl.iDc = iDct[ 0 ];
       
  1248 	
       
  1249 	User::LeaveIfError(iBasicBlock.Append( bl ));
       
  1250 
       
  1251 	//Idct();
       
  1252 	}
       
  1253 
       
  1254 
       
  1255 
       
  1256 
       
  1257 const TJpegData& CJpRotate::Info()
       
  1258 	{
       
  1259 	return iData;
       
  1260 	}
       
  1261 
       
  1262 
       
  1263 TPtrC8 CJpRotate::ExifData()
       
  1264 	{
       
  1265 	return TPtrC8( iExifData, iExifDataLength );
       
  1266 	}
       
  1267 
       
  1268 
       
  1269 
       
  1270 
       
  1271 void CJpRotate::WriteHuffmanL( TInt aValue )
       
  1272 	{
       
  1273 	TInt code = iCurrentSaveHuffman->iCode[ aValue ];
       
  1274 	TInt len = iCurrentSaveHuffman->iLength[ aValue ];
       
  1275 	if( aValue != 0 && len == 0 )
       
  1276 		{
       
  1277 		//
       
  1278 		// The value which we tried to write doesn't exist in
       
  1279 		// the huffman table. Therefore the output would be
       
  1280 		// corrupted. Thus the leave.
       
  1281 		// actually this should not happen ever.
       
  1282 		//
       
  1283 		User::Leave( KErrCorrupt );
       
  1284 		}
       
  1285 	WriteBits( code, len );
       
  1286 	}
       
  1287 
       
  1288 
       
  1289 
       
  1290 void CJpRotate::WriteBits( TUint32 aValue, TInt aNumBits )
       
  1291 	{
       
  1292 
       
  1293 	aValue &= ( ( 1 << aNumBits ) - 1 );
       
  1294 	while( aNumBits > 0 )
       
  1295 		{
       
  1296 		TInt bitroom = 8 - iSaveBufBitPos;
       
  1297 		//iSaveBuf[ iSaveBufPos ] |= ( ( aValue << ( 24+bitroom-aNumBits ) ) >> 24 );
       
  1298 		iSaveByte |= ( ( aValue << ( 24+bitroom-aNumBits ) ) >> 24 );
       
  1299 
       
  1300 		if( aNumBits < bitroom )
       
  1301 			{
       
  1302 			iSaveBufBitPos += aNumBits;
       
  1303 			}
       
  1304 		else
       
  1305 			{
       
  1306 			iSaveBufBitPos += bitroom;
       
  1307 			}
       
  1308 
       
  1309 		if( iSaveBufBitPos == 8 ) 
       
  1310 			{
       
  1311 
       
  1312 			iSaveBufBitPos = 0;
       
  1313 			iSaveBuf[ iSaveBufPos ] = iSaveByte;
       
  1314 
       
  1315 			if( iSaveByte == 255 )
       
  1316 				{
       
  1317 				iSaveBufPos++;
       
  1318 				if( iSaveBufPos == iSaveBufSize )
       
  1319 					{
       
  1320 					FlushSaveBuf();
       
  1321 					}
       
  1322 				iSaveBuf[ iSaveBufPos ] = 0;	// 255,0 = 255 ( escaped 255 )
       
  1323 				}
       
  1324 			iSaveByte = 0;
       
  1325 			iSaveBufPos++;
       
  1326 
       
  1327 			if( iSaveBufPos == iSaveBufSize )
       
  1328 				{
       
  1329 				FlushSaveBuf();
       
  1330 				}
       
  1331 
       
  1332 			}
       
  1333 		aNumBits -= bitroom;
       
  1334 		}
       
  1335 	}
       
  1336 
       
  1337 
       
  1338 void CJpRotate::CreateSaveHuffmanL( TSHuffman* aHuffman, const TUint8* aBits, const TUint8* aVal )
       
  1339 	{
       
  1340 
       
  1341 	
       
  1342 	TInt huffSize[ 16 ];
       
  1343 
       
  1344 	TUint32 huffCode[ 256 ];
       
  1345 	TInt huffValue[ 256 ];
       
  1346 	TInt huffLength[ 256 ];
       
  1347 
       
  1348 	TInt numSymbols = 0;
       
  1349 	TInt i;
       
  1350 
       
  1351 	for( i=0; i<16; i++ )
       
  1352 		{
       
  1353 		TInt size = aBits[ i+1 ];
       
  1354 		huffSize[ i ] = size;
       
  1355 		numSymbols += size;
       
  1356 		}
       
  1357 
       
  1358 	for( i=0; i<numSymbols; i++ )
       
  1359 		{
       
  1360 		huffValue[ i ] = aVal[ i ];
       
  1361 		}
       
  1362 	
       
  1363 	TInt l;
       
  1364 	TInt p = 0;
       
  1365 	for( i=0; i<256; i++ ) huffLength[ i ] = -1;
       
  1366 	for( l=0; l<16; l++ )
       
  1367 		{
       
  1368 		for( i=0; i<huffSize[ l ]; i++ )
       
  1369 			{
       
  1370 			huffLength[ p++ ] = l+1;
       
  1371 			}
       
  1372 		}
       
  1373 
       
  1374 	TInt code = 0;
       
  1375 	huffLength[ p ] = 0;
       
  1376 	TInt si = huffLength[ 0 ];
       
  1377 	
       
  1378 	p = 0;
       
  1379 
       
  1380 	while( huffLength[ p ] )
       
  1381 		{
       
  1382 		while( huffLength[ p ] == si )
       
  1383 			{
       
  1384 			huffCode[ p++ ] = code++;
       
  1385 			}
       
  1386 		code *= 2;
       
  1387 		si++;
       
  1388 		}
       
  1389 
       
  1390 	for( i=0; i<numSymbols; i++ )
       
  1391 		{
       
  1392 		TInt v = huffValue[ i ];
       
  1393 		aHuffman->iLength[ v ] = huffLength[ i ];
       
  1394 		aHuffman->iCode[ v ] = huffCode[ i ];
       
  1395 		}
       
  1396 
       
  1397 
       
  1398 	}
       
  1399 
       
  1400 
       
  1401 void CJpRotate::ConvertQuants( TUint8* aSrc, TUint8* aTgt )
       
  1402 	{
       
  1403 	if( ! iRotate )
       
  1404 		{
       
  1405 		Mem::Copy( aTgt, aSrc, 64 );
       
  1406 		return;
       
  1407 		}
       
  1408 
       
  1409 	for( TInt i=0; i<64; i++ )
       
  1410 		{
       
  1411 		aTgt[ KReZig[ i ] ] = aSrc[ i ];
       
  1412 		}
       
  1413 	}
       
  1414 
       
  1415 
       
  1416 
       
  1417 void CJpRotate::WriteSaveBuffer( const TUint8* aSrc, TInt aBytes )
       
  1418 	{
       
  1419 	TInt pos = 0;
       
  1420 	while( aBytes )
       
  1421 		{
       
  1422 		TInt bytes = aBytes;
       
  1423 		if( iSaveBufPos + bytes > iSaveBufSize )
       
  1424 			{
       
  1425 			bytes = iSaveBufSize - iSaveBufPos;
       
  1426 			}
       
  1427 		Mem::Copy( iSaveBuf + iSaveBufPos, aSrc + pos, bytes );
       
  1428 		iSaveBufPos += bytes;
       
  1429 		if( iSaveBufPos == iSaveBufSize )
       
  1430 			{
       
  1431 			FlushSaveBuf();
       
  1432 			}
       
  1433 		aBytes -= bytes;
       
  1434 		pos += bytes;
       
  1435 		}
       
  1436 	}
       
  1437 
       
  1438 
       
  1439 void CJpRotate::WriteSaveBuffer( TUint8 aValue )
       
  1440 	{
       
  1441 	iSaveBuf[ iSaveBufPos++ ] = aValue;
       
  1442 	if( iSaveBufPos == iSaveBufSize )
       
  1443 		{
       
  1444 		FlushSaveBuf();
       
  1445 		}
       
  1446 	}
       
  1447 
       
  1448 
       
  1449 void CJpRotate::WriteSaveBuffer( TUint16 aValue )
       
  1450 	{
       
  1451 	WriteSaveBuffer( (TUint8) ( aValue / 256 ) );
       
  1452 	WriteSaveBuffer( (TUint8) ( aValue & 255 ) );
       
  1453 	}
       
  1454 
       
  1455 
       
  1456 void CJpRotate::SaveBlocks()
       
  1457 	{
       
  1458 	TInt yBlocks = iComponent[ 0 ].iXFactor * iComponent[ 0 ].iYFactor;
       
  1459 	TInt uBlocks = iComponent[ 1 ].iXFactor * iComponent[ 1 ].iYFactor;
       
  1460 	TInt vBlocks = iComponent[ 2 ].iXFactor * iComponent[ 2 ].iYFactor;
       
  1461 
       
  1462 	TInt blocks = yBlocks + uBlocks + vBlocks;
       
  1463 	TInt blockOffset[ 16 ];
       
  1464 
       
  1465 	TInt x;
       
  1466 	TInt y;
       
  1467 
       
  1468 	TInt i = 0;
       
  1469 	TInt b = 0;
       
  1470 	for( TInt comp = 0; comp<iNumComponents; comp++ )
       
  1471 		{
       
  1472 		TComponent& c = iComponent[ comp ];
       
  1473 
       
  1474 		for( y=0; y<c.iYFactor; y++ )
       
  1475 			{
       
  1476 			for( x=0; x<c.iXFactor; x++ )
       
  1477 				{
       
  1478 				TInt xx = x;
       
  1479 				TInt yy = y;
       
  1480 				TInt fx = c.iXFactor;
       
  1481 				TInt fy = c.iYFactor;
       
  1482 				
       
  1483 
       
  1484 				if( iRotate )
       
  1485 					{
       
  1486 					TInt t = xx; xx = yy; yy = t;
       
  1487 					if( iFlip ) yy = fx - 1 - yy;
       
  1488 					if( iMirror ) xx = fy - 1 - xx;
       
  1489 					t = fx; fx=fy; fy = t;
       
  1490 					}
       
  1491 				else
       
  1492 					{
       
  1493 					if( iFlip ) yy = fy - 1 - yy;
       
  1494 					if( iMirror ) xx = fx - 1 - xx;
       
  1495 					}
       
  1496 
       
  1497 				TInt v = xx + yy * fx; //1302
       
  1498 				//while( v >= n ) v -= n;
       
  1499 				//blockOffset[ i++ ] = b + v;
       
  1500 				blockOffset[ b+v ] = i++;
       
  1501 				}
       
  1502 			}
       
  1503 		b += c.iXFactor*c.iYFactor;
       
  1504 		}
       
  1505 	TInt bw = iData.iSizeInBlocks.iWidth;
       
  1506 	TInt bh = iData.iSizeInBlocks.iHeight;
       
  1507 	
       
  1508 	TInt yDc = 0;
       
  1509 	TInt uDc = 0;
       
  1510 	TInt vDc = 0;
       
  1511 
       
  1512 	TInt count = 0;
       
  1513 	
       
  1514 	TInt blockXAdd;
       
  1515 	TInt blockYAdd;
       
  1516 	TInt blockPos;
       
  1517 
       
  1518 	if( iRotate )
       
  1519 		{
       
  1520 		if( iMirror )
       
  1521 			{
       
  1522 			if( iFlip )
       
  1523 				{
       
  1524 				blockPos = blocks * ( bw * bh - 1 );
       
  1525 				blockXAdd = -blocks * bw;
       
  1526 				blockYAdd = blocks * bw * bh - blocks;
       
  1527 				}
       
  1528 			else
       
  1529 				{
       
  1530 				blockPos = blocks * bw * ( bh - 1 );
       
  1531 				blockXAdd = -blocks * bw;
       
  1532 				blockYAdd = blocks * bw * bh + blocks;
       
  1533 				}
       
  1534 			}
       
  1535 		else
       
  1536 			{
       
  1537 			if( iFlip )
       
  1538 				{
       
  1539 				blockPos = blocks * ( bw - 1 );
       
  1540 				blockXAdd = blocks * bw;
       
  1541 				blockYAdd = -blocks * bw * bh - blocks;
       
  1542 				}
       
  1543 			else
       
  1544 				{
       
  1545 				blockPos = 0;
       
  1546 				blockXAdd = blocks * bw;
       
  1547 				blockYAdd = -blocks * ( bw * bh - 1 );
       
  1548 				}
       
  1549 			}
       
  1550 		TInt t = bw; bw = bh; bh = t;
       
  1551 		}
       
  1552 	else
       
  1553 		{
       
  1554 		if( iMirror )
       
  1555 			{
       
  1556 			if( iFlip )
       
  1557 				{
       
  1558 				blockPos = blocks * ( bw * bh - 1 );
       
  1559 				blockXAdd = -blocks;
       
  1560 				blockYAdd = 0;
       
  1561 				}
       
  1562 			else
       
  1563 				{
       
  1564 				blockPos = blocks * ( bw-1 );
       
  1565 				blockXAdd = -blocks;
       
  1566 				blockYAdd = bw * blocks * 2;
       
  1567 				}
       
  1568 			}
       
  1569 		else
       
  1570 			{
       
  1571 			if( iFlip )
       
  1572 				{
       
  1573 				blockPos = blocks * bw * ( bh-1 );
       
  1574 				blockXAdd = blocks;
       
  1575 				blockYAdd = -blocks*bw*2; 
       
  1576 				}
       
  1577 			else
       
  1578 				{
       
  1579 				blockPos = 0;
       
  1580 				blockXAdd = blocks;
       
  1581 				blockYAdd = 0;
       
  1582 				}
       
  1583 			}
       
  1584 		}
       
  1585 
       
  1586 	TInt numMacroBlocks = bw*bh;
       
  1587 
       
  1588 	for( y=0; y<bh; y++ )
       
  1589 		{
       
  1590 		for( x=0; x<bw; x++ )
       
  1591 			{
       
  1592 
       
  1593 			iCurrentQt = iQt[ 0 ];
       
  1594 			TInt i = 0;
       
  1595 			TInt n;
       
  1596 			for( n=0; n<yBlocks; n++ )
       
  1597 				{
       
  1598 				TInt bo = blockOffset[ i++ ];
       
  1599 				TJpegBasicBlock& bl = iBasicBlock[ blockPos + bo ];
       
  1600 				iBuf = bl.iBuf;
       
  1601 				iBufPos = bl.iOffset;
       
  1602 				iBufBits = bl.iBufBits;
       
  1603 
       
  1604 				iCurrentHuffman = 0;
       
  1605 				iCurrentSaveHuffman = iSaveHuffman[ 0 ];
       
  1606 				DecodeBlockL( bl.iDc - yDc );
       
  1607 				yDc = bl.iDc;
       
  1608 				}
       
  1609 
       
  1610 			iCurrentQt = iQt[ 1 ];
       
  1611 
       
  1612 			for( n=0; n<uBlocks; n++ )
       
  1613 				{
       
  1614 				TJpegBasicBlock& bl = iBasicBlock[ blockPos + blockOffset[ i++ ] ];
       
  1615 				iBuf = bl.iBuf;
       
  1616 				iBufPos = bl.iOffset;
       
  1617 				iBufBits = bl.iBufBits;
       
  1618 
       
  1619 				iCurrentHuffman = 1;
       
  1620 				iCurrentSaveHuffman = iSaveHuffman[ 1 ];
       
  1621 				DecodeBlockL( bl.iDc - uDc );
       
  1622 				uDc = bl.iDc;
       
  1623 				}
       
  1624 
       
  1625 			for( n=0; n<vBlocks; n++ )
       
  1626 				{
       
  1627 				TJpegBasicBlock& bl = iBasicBlock[ blockPos + blockOffset[ i++ ] ];
       
  1628 				iBuf = bl.iBuf;
       
  1629 				iBufPos = bl.iOffset;
       
  1630 				iBufBits = bl.iBufBits;
       
  1631 
       
  1632 				iCurrentHuffman = 1;
       
  1633 				iCurrentSaveHuffman = iSaveHuffman[ 1 ];
       
  1634 				DecodeBlockL( bl.iDc - vDc );
       
  1635 				vDc = bl.iDc;
       
  1636 				}
       
  1637 
       
  1638 
       
  1639 			//
       
  1640 			// Rst ( 0xFFD0..0xFFD7 ) after each macroblock
       
  1641 			//
       
  1642 			/*
       
  1643 			if( iSaveBufBitPos ) 
       
  1644 				{
       
  1645 				WriteBits( 0,8-iSaveBufBitPos );
       
  1646 				}
       
  1647 			WriteSaveBuffer( (TUint16)( 0xffd0 + (count & 7 ) ) );
       
  1648 			
       
  1649 			yDc = 0;
       
  1650 			uDc = 0;
       
  1651 			vDc = 0;
       
  1652 			
       
  1653 			count++;
       
  1654 			*/
       
  1655 
       
  1656 			blockPos += blockXAdd;
       
  1657 
       
  1658 			if( iCallBack )
       
  1659 				{
       
  1660 				iCallBack->JpRotateStatus( count, numMacroBlocks );
       
  1661 				}
       
  1662 
       
  1663 			}
       
  1664 		blockPos += blockYAdd;
       
  1665 		}
       
  1666 
       
  1667 	//RDebug::Print( _L("last access block :%d"), mx );
       
  1668 	}
       
  1669 
       
  1670 
       
  1671 
       
  1672 void CJpRotate::FlushSaveBuf()
       
  1673 	{
       
  1674 	if( &iSaveFile == NULL ) return;		// no flushing without file
       
  1675 	TPtr8 ptr( iSaveBuf, iSaveBufPos );
       
  1676 	ptr.SetLength( iSaveBufPos );
       
  1677 	iSaveFile.Write( ptr );
       
  1678 	iSaveBufPos = 0;
       
  1679 	}