imageeditorengine/src/CJpegSave.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 // Jpeg encoder class
       
    22 
       
    23 #include "CJpegSave.h"
       
    24 #include <fbs.h>
       
    25 #include <e32math.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 
       
    39 
       
    40 //Table K.1 from JPEG specification
       
    41 const int jpeg_luma_quantizer[64] = {
       
    42         16, 11, 10, 16, 24, 40, 51, 61,
       
    43         12, 12, 14, 19, 26, 58, 60, 55,
       
    44         14, 13, 16, 24, 40, 57, 69, 56,
       
    45         14, 17, 22, 29, 51, 87, 80, 62,
       
    46         18, 22, 37, 56, 68, 109, 103, 77,
       
    47         24, 35, 55, 64, 81, 104, 113, 92,
       
    48         49, 64, 78, 87, 103, 121, 120, 101,
       
    49         72, 92, 95, 98, 112, 100, 103, 99
       
    50 };
       
    51 
       
    52 
       
    53 // Table K.2 from JPEG specification
       
    54 const int jpeg_chroma_quantizer[64] = {
       
    55         17, 18, 24, 47, 99, 99, 99, 99,
       
    56         18, 21, 26, 66, 99, 99, 99, 99,
       
    57         24, 26, 56, 99, 99, 99, 99, 99,
       
    58         47, 66, 99, 99, 99, 99, 99, 99,
       
    59         99, 99, 99, 99, 99, 99, 99, 99,
       
    60         99, 99, 99, 99, 99, 99, 99, 99,
       
    61         99, 99, 99, 99, 99, 99, 99, 99,
       
    62         99, 99, 99, 99, 99, 99, 99, 99
       
    63 };
       
    64 
       
    65 
       
    66 
       
    67 // Set up the standard Huffman tables (cf. JPEG standard section K.3)
       
    68 // IMPORTANT: these are only valid for 8-bit data precision!
       
    69 
       
    70 const TUint8 bits_dc_luminance[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
       
    71 const TUint8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    72 const TUint8 bits_dc_chrominance[17] = { 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
       
    73 const TUint8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
       
    74 
       
    75 const TUint8 bits_ac_luminance[17] = {  0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
       
    76 const TUint8 val_ac_luminance[] =
       
    77 	{
       
    78 	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
       
    79 	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
       
    80 	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
       
    81 	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
       
    82 	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
       
    83 	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
       
    84 	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
       
    85 	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
       
    86 	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
       
    87 	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
       
    88 	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
       
    89 	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
       
    90 	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
       
    91 	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
       
    92 	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
       
    93 	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
       
    94 	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
       
    95 	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
       
    96 	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
       
    97 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
    98 	0xf9, 0xfa 
       
    99 	};
       
   100 
       
   101 const TUint8 bits_ac_chrominance[17] = { 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
       
   102 
       
   103 const TUint8 val_ac_chrominance[] =
       
   104 	{ 
       
   105 	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
       
   106 	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
       
   107 	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
       
   108 	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
       
   109 	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
       
   110 	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
       
   111 	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
       
   112 	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
       
   113 	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
       
   114 	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
       
   115 	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
       
   116 	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
       
   117 	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
       
   118 	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
       
   119 	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
       
   120 	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
       
   121 	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
       
   122 	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
       
   123 	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
       
   124 	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
       
   125 	0xf9, 0xfa 
       
   126 	};
       
   127 
       
   128 
       
   129 // Jpeg store huffman lookup
       
   130 class TSHuffman
       
   131 	{
       
   132 	public:
       
   133 		TUint8 iLength[ 256 ];
       
   134 		TInt8 iCode[ 256 ];
       
   135 	};
       
   136 
       
   137 
       
   138 
       
   139 CJpegSave* CJpegSave::NewL( RFs* aFs, RFile* aFile )
       
   140 	{
       
   141 	CJpegSave* self = NewLC( aFs, aFile );
       
   142 	CleanupStack::Pop( self );
       
   143 	return self;
       
   144 	}
       
   145 	
       
   146 	
       
   147 	
       
   148 CJpegSave* CJpegSave::NewLC( RFs* aFs, RFile* aFile )
       
   149 	{
       
   150 	CJpegSave* self = new( ELeave )CJpegSave( aFs, aFile );
       
   151 	CleanupStack::PushL( self );
       
   152 	self->ConstructL();
       
   153 	return self;
       
   154 	}	
       
   155 
       
   156 
       
   157 
       
   158 CJpegSave::~CJpegSave()
       
   159 	{
       
   160 	delete iHuffman[ 0 ];
       
   161 	delete iHuffman[ 1 ];
       
   162 	delete iHuffman[ 2 ];
       
   163 	delete iHuffman[ 3 ];
       
   164 	delete iSaveBuf;
       
   165 	iFs = NULL;
       
   166 	iSaveFile = NULL;
       
   167 	iCurrentHuffman = NULL;
       
   168 	iCurrentQuant = NULL;
       
   169 	}
       
   170 
       
   171 
       
   172 
       
   173 CJpegSave::CJpegSave( RFs* aFs, RFile* aFile )
       
   174 	: iFs( aFs )
       
   175 	, iSaveFile( aFile )
       
   176 	{
       
   177 	}
       
   178 
       
   179 
       
   180 
       
   181 void CJpegSave::ConstructL()
       
   182 	{
       
   183 	TSHuffman* huff = new( ELeave )TSHuffman;
       
   184 	CleanupStack::PushL(huff);
       
   185 	CreateHuffmanL( huff, bits_dc_luminance, val_dc_luminance );
       
   186 	iHuffman[ 0 ] = huff;
       
   187 	CleanupStack::Pop();
       
   188 
       
   189 	huff = new( ELeave )TSHuffman;
       
   190 	CleanupStack::PushL(huff);
       
   191 	CreateHuffmanL( huff, bits_dc_chrominance, val_dc_chrominance );
       
   192 	iHuffman[ 1 ] = huff;
       
   193 	CleanupStack::Pop();
       
   194 
       
   195 	huff = new( ELeave )TSHuffman;
       
   196 	CleanupStack::PushL(huff);
       
   197 	CreateHuffmanL( huff, bits_ac_luminance, val_ac_luminance );
       
   198 	iHuffman[ 2 ] = huff;
       
   199 	CleanupStack::Pop();
       
   200 	
       
   201 	huff = new( ELeave )TSHuffman;
       
   202 	CleanupStack::PushL(huff);
       
   203 	CreateHuffmanL( huff, bits_ac_chrominance, val_ac_chrominance );
       
   204 	iHuffman[ 3 ] = huff;
       
   205 	CleanupStack::Pop();
       
   206 	
       
   207 	iSaveByte = 0;
       
   208 	iSaveBufPos = 0;
       
   209 	iSaveBufBitPos = 0;
       
   210 
       
   211 	}
       
   212 
       
   213 
       
   214 
       
   215 void CJpegSave::StartSaveL( const TSize& aSize, TPtr8 aExif, TInt aSaveBufferSize, TInt aQuality )
       
   216 	{
       
   217 	iSaveBufSize = aSaveBufferSize;
       
   218 	if (iSaveBuf)
       
   219 		{
       
   220 		delete iSaveBuf;
       
   221 		iSaveBuf = NULL;
       
   222 		}
       
   223 		
       
   224 	iSaveBuf = new( ELeave )TUint8[ iSaveBufSize ];
       
   225 
       
   226 	// create quantization tables
       
   227 	MakeTables( aQuality, iYQuant, iUVQuant );
       
   228 
       
   229 
       
   230 	TSize size = aSize;
       
   231 	TInt len;
       
   232 	
       
   233 	// D8 Start Of Image
       
   234 
       
   235 	WriteSaveBuffer( (TUint16)0xffd8 );
       
   236 
       
   237 	
       
   238 
       
   239 	//
       
   240 	// Exif ( if any )
       
   241 	// 
       
   242 	
       
   243 	if( aExif.Length() != 0 )
       
   244 		{
       
   245 		WriteSaveBuffer( (TUint16) 0xffe1 );
       
   246 		
       
   247 		TUint32 l = aExif.Length() + 6 + 2; // +header+tagsize
       
   248 		WriteSaveBuffer( (TUint16) l );
       
   249 
       
   250 		// exif header is 6 bytes ( 45 78 69 66 00 00 "Exif.." )
       
   251 		WriteSaveBuffer( (TUint8) 0x45 );
       
   252 		WriteSaveBuffer( (TUint8) 0x78 );
       
   253 		WriteSaveBuffer( (TUint8) 0x69 );
       
   254 		WriteSaveBuffer( (TUint8) 0x66 );
       
   255 		WriteSaveBuffer( (TUint8) 0x00 );
       
   256 		WriteSaveBuffer( (TUint8) 0x00 );
       
   257 
       
   258 		l -= ( 6+2 ); // minus header, minus tag size
       
   259 		
       
   260 		// save exif chunck
       
   261 		WriteSaveBuffer( aExif.Ptr(), l );
       
   262 		}
       
   263 	else
       
   264 		{
       
   265 		//
       
   266 		// if no exif, standard application segment here
       
   267 		//
       
   268 
       
   269 		// E0 jpeg application segment
       
   270 		WriteSaveBuffer( (TUint16)0xffe0 );
       
   271 		
       
   272 		// segment length
       
   273 		WriteSaveBuffer( (TUint16)16 );
       
   274 
       
   275 		// 0x4a, 0x46, 0x49, 0x46, 0x00 JFIF #0
       
   276 		WriteSaveBuffer( (TUint8) 0x4a );
       
   277 		WriteSaveBuffer( (TUint8) 0x46 );
       
   278 		WriteSaveBuffer( (TUint8) 0x49 );
       
   279 		WriteSaveBuffer( (TUint8) 0x46 );
       
   280 		WriteSaveBuffer( (TUint8) 0x00 );
       
   281 
       
   282 		WriteSaveBuffer( (TUint8) 0x01 );	// major revision number
       
   283 		WriteSaveBuffer( (TUint8) 0x01 );	// minor revision number
       
   284 
       
   285 		// 0=aspect ratio, 1=dots/inch, 2=dots/cm
       
   286 		WriteSaveBuffer( (TUint8) 0x01 );
       
   287 
       
   288 		TInt dpi = 72;
       
   289 		// x dpi
       
   290 		WriteSaveBuffer( (TUint16) dpi );
       
   291 
       
   292 		// y dpi
       
   293 		WriteSaveBuffer( (TUint16) dpi );
       
   294 
       
   295 		// thumbnail width
       
   296 		WriteSaveBuffer( (TUint8) 0 );
       
   297 		
       
   298 		// thumbnail height
       
   299 		WriteSaveBuffer( (TUint8) 0 );
       
   300 
       
   301 
       
   302 		}
       
   303 	
       
   304 
       
   305 
       
   306 	//
       
   307 	// quant table
       
   308 	//
       
   309 
       
   310 	TUint8 quant[ 2 ][ 64 ];
       
   311 
       
   312 	TInt i;
       
   313 	TInt n;
       
   314 	for( i=0; i<64; i++ )
       
   315 		{
       
   316 		quant[ 0 ][ i ] = iYQuant[ i ];
       
   317 		quant[ 1 ][ i ] = iUVQuant[ i ];
       
   318 		}
       
   319 
       
   320 
       
   321 	for( n=0; n<2; n++ )
       
   322 		{
       
   323 		WriteSaveBuffer( (TUint16) 0xffdb );
       
   324 
       
   325 		len = 2 + 1 * 65;
       
   326 		// chunk length
       
   327 		WriteSaveBuffer( (TUint16) len );
       
   328 
       
   329 		// quantization table #
       
   330 		WriteSaveBuffer( (TUint8) n );
       
   331 		
       
   332 		// quantization table
       
   333 		WriteSaveBuffer( quant[ n ], 64 );
       
   334 		}
       
   335 
       
   336 
       
   337 
       
   338 
       
   339 
       
   340 	//
       
   341 	// Huffman Table
       
   342 	//
       
   343 
       
   344 	const TUint8* nBits[ 4 ];
       
   345 	const TUint8* values[ 4 ];
       
   346 	
       
   347 	nBits[ 0 ] = bits_dc_luminance;
       
   348 	nBits[ 1 ] = bits_dc_chrominance;
       
   349 	nBits[ 2 ] = bits_ac_luminance;
       
   350 	nBits[ 3 ] = bits_ac_chrominance;
       
   351 	values[ 0 ] = val_dc_luminance;
       
   352 	values[ 1 ] = val_dc_chrominance;
       
   353 	values[ 2 ] = val_ac_luminance;
       
   354 	values[ 3 ] = val_ac_chrominance;
       
   355 
       
   356 	
       
   357 	for( n=0; n<4; n++ )
       
   358 		{
       
   359 		WriteSaveBuffer( (TUint16) 0xffc4 );
       
   360 		
       
   361 		TInt numSymbols = 0;
       
   362 		for( i=0; i<16; i++ )
       
   363 			{
       
   364 			TUint8 size = nBits[ n ][ i + 1 ];
       
   365 			numSymbols += size;
       
   366 			}
       
   367 		
       
   368 		len = 2 + 1 + 16 + numSymbols;
       
   369 		// chunk length
       
   370 		WriteSaveBuffer( (TUint16) len );
       
   371 		
       
   372 		// huffman table #
       
   373 		WriteSaveBuffer( (TUint8)( ( n / 2 ) * 16 + ( n & 1 ) ) );
       
   374 
       
   375 		// bit lengths for huffman table codes
       
   376 		for( i=0; i<16; i++ )
       
   377 			{
       
   378 			TUint8 size = nBits[ n ][ i + 1 ];
       
   379 			WriteSaveBuffer( size );
       
   380 			}
       
   381 		
       
   382 		// huffman table symbols
       
   383 		WriteSaveBuffer( values[ n ], numSymbols );
       
   384 		}
       
   385 	
       
   386 
       
   387 
       
   388 
       
   389 
       
   390 	//
       
   391 	// Start of frame
       
   392 	//
       
   393 	WriteSaveBuffer( (TUint16)0xffc0 );
       
   394 	
       
   395 	len = 8 + 3 * 3;
       
   396 	// chunk length
       
   397 	WriteSaveBuffer( (TUint16)len );
       
   398 	
       
   399 	// precision
       
   400 	WriteSaveBuffer( (TUint8)8 );
       
   401 
       
   402 	// image height
       
   403 	WriteSaveBuffer( (TUint16)size.iHeight );
       
   404 
       
   405 	// image width
       
   406 	WriteSaveBuffer( (TUint16)size.iWidth );
       
   407 	
       
   408 	// number of components
       
   409 	WriteSaveBuffer( (TUint8)3 );
       
   410 
       
   411 	// component 0:
       
   412 	
       
   413 	WriteSaveBuffer( (TUint8)1 );				// number of component
       
   414 	WriteSaveBuffer( (TUint8) ( 1 + 16*2 ) );	// sampling factor
       
   415 	WriteSaveBuffer( (TUint8)0 );				// number of quantization table
       
   416 
       
   417 	// component 1:
       
   418 	WriteSaveBuffer( (TUint8)2 );				// number of component
       
   419 	WriteSaveBuffer( (TUint8) ( 1 + 16*1 ) );	// sampling factor
       
   420 	WriteSaveBuffer( (TUint8)1 );				// number of quantization table
       
   421 
       
   422 	// component 2:
       
   423 	WriteSaveBuffer( (TUint8)3 );				// number of component
       
   424 	WriteSaveBuffer( (TUint8) ( 1 + 16*1 ) );	// sampling factor
       
   425 	WriteSaveBuffer( (TUint8)1 );				// number of quantization table
       
   426 
       
   427 
       
   428 	//
       
   429 	// Start Of Scan ( SOS )
       
   430 	//
       
   431 	WriteSaveBuffer( (TUint16)0xffda );
       
   432 	
       
   433 	len = 3 + 3*2 + 3;
       
   434 	// chunk length
       
   435 	WriteSaveBuffer( (TUint16)len );
       
   436 	
       
   437 	// number of components
       
   438 	WriteSaveBuffer( (TUint8)3 );	
       
   439 
       
   440 	/// component1:
       
   441 	// component ID
       
   442 	WriteSaveBuffer( (TUint8)1 );
       
   443 	// component huffman table ac(low4) dc(hi4)
       
   444 	WriteSaveBuffer( (TUint8)0 );
       
   445 
       
   446 	/// component2:
       
   447 	// component ID
       
   448 	WriteSaveBuffer( (TUint8)2 );
       
   449 	// component huffman table ac(low4) dc(hi4)
       
   450 	WriteSaveBuffer( (TUint8)17 );
       
   451 
       
   452 	/// component3:
       
   453 	// component ID
       
   454 	WriteSaveBuffer( (TUint8)3 );
       
   455 	// component huffman table ac(low4) dc(hi4)
       
   456 	WriteSaveBuffer( (TUint8)17 );
       
   457 	
       
   458 	// stuffing ( actually dctsize-1 can be stored )
       
   459 	WriteSaveBuffer( (TUint8)0 );
       
   460 	WriteSaveBuffer( (TUint8)63 );	// dctsize - 1
       
   461 	WriteSaveBuffer( (TUint8)0 );
       
   462 
       
   463 	iDy = 0;
       
   464 	iDu = 0;
       
   465 	iDv = 0;
       
   466 	}
       
   467 
       
   468 
       
   469 
       
   470 void CJpegSave::SaveBlock( const TBitmapHandle& aBitmap )
       
   471 	{
       
   472 	//
       
   473 	// Macroblocks:
       
   474 	//
       
   475 	TInt by[ 256 ];
       
   476 	TInt bu[ 64 ];
       
   477 	TInt bv[ 64 ];
       
   478 	TInt dct[ 64 ];
       
   479 
       
   480 	
       
   481 	Rgb2Yuv( (TUint32*)aBitmap.iData, aBitmap.iSize.iWidth, by, bu, bv );
       
   482 	
       
   483 	iCurrentQuant = (TUint8*)iYQuant;
       
   484 	
       
   485 	Dct( by, dct );
       
   486 	dct[ 0 ] -= iDy;
       
   487 	iDy += WriteDct( dct, iHuffman[ 0 ], iHuffman[ 2 ] );
       
   488 	
       
   489 	Dct( by+64, dct );
       
   490 	dct[ 0 ] -= iDy;
       
   491 	iDy += WriteDct( dct, iHuffman[ 0 ], iHuffman[ 2 ] );
       
   492 	
       
   493 	iCurrentQuant = (TUint8*)iUVQuant;
       
   494 	Dct( bu, dct );
       
   495 	dct[ 0 ] -= iDu;
       
   496 	iDu += WriteDct( dct, iHuffman[ 1 ], iHuffman[ 3 ] );
       
   497 	
       
   498 	Dct( bv, dct );
       
   499 	dct[ 0 ] -= iDv;
       
   500 	iDv += WriteDct( dct, iHuffman[ 1 ], iHuffman[ 3 ] );
       
   501 
       
   502 	}
       
   503 
       
   504 
       
   505 
       
   506 void CJpegSave::FinalizeSave()
       
   507 	{
       
   508 	
       
   509 	//
       
   510 	// End Of Image ( EOI )
       
   511 	//
       
   512 
       
   513 	// flush last bits to save buffer
       
   514 	if( iSaveBufBitPos )
       
   515 		{
       
   516 		WriteBits( 0, 8-iSaveBufBitPos );
       
   517 		}
       
   518 
       
   519 	// end of image tag
       
   520 	WriteSaveBuffer( (TUint16)0xffd9 );
       
   521 
       
   522 	// there might still be stuff in save buffer
       
   523 	FlushSaveBuf();		
       
   524 	}
       
   525 
       
   526 
       
   527 TPtrC8 CJpegSave::Finalize()
       
   528 	{
       
   529 	
       
   530 	//
       
   531 	// End Of Image ( EOI )
       
   532 	//
       
   533 
       
   534 	// flush last bits to save buffer
       
   535 	if( iSaveBufBitPos )
       
   536 		{
       
   537 		WriteBits( 0, 8-iSaveBufBitPos );
       
   538 		}
       
   539 
       
   540 	// end of image tag
       
   541 	WriteSaveBuffer( (TUint16)0xffd9 );
       
   542 	
       
   543 	return TPtrC8( iSaveBuf, iSaveBufPos );
       
   544 	}
       
   545 
       
   546 
       
   547 
       
   548 void CJpegSave::WriteHuffman( TInt aValue )
       
   549 	{
       
   550 	TInt code = iCurrentHuffman->iCode[ aValue ];
       
   551 	TInt len = iCurrentHuffman->iLength[ aValue ];
       
   552 	WriteBits( code, len );
       
   553 	}
       
   554 
       
   555 
       
   556 
       
   557 void CJpegSave::CreateHuffmanL( TSHuffman* aHuffman, const TUint8* aBits, const TUint8* aVal )
       
   558 	{
       
   559 	TInt huffSize[ 16 ];
       
   560 
       
   561 	TUint32 huffCode[ 256 ];
       
   562 	TInt huffValue[ 256 ];
       
   563 	TInt huffLength[ 256 ];
       
   564 
       
   565 	TInt numSymbols = 0;
       
   566 	TInt i;
       
   567 
       
   568 	for( i=0; i<16; i++ )
       
   569 		{
       
   570 		TInt size = aBits[ i+1 ];
       
   571 		huffSize[ i ] = size;
       
   572 		numSymbols += size;
       
   573 		}
       
   574 
       
   575 	for( i=0; i<numSymbols; i++ )
       
   576 		{
       
   577 		huffValue[ i ] = aVal[ i ];
       
   578 		}
       
   579 	
       
   580 	TInt l;
       
   581 	TInt p = 0;
       
   582 	for( i=0; i<256; i++ ) huffLength[ i ] = -1;
       
   583 	for( l=0; l<16; l++ )
       
   584 		{
       
   585 		for( i=0; i<huffSize[ l ]; i++ )
       
   586 			{
       
   587 			huffLength[ p++ ] = l+1;
       
   588 			}
       
   589 		}
       
   590 
       
   591 	TInt code = 0;
       
   592 	huffLength[ p ] = 0;
       
   593 	TInt si = huffLength[ 0 ];
       
   594 	
       
   595 	p = 0;
       
   596 
       
   597 	while( huffLength[ p ] )
       
   598 		{
       
   599 		while( huffLength[ p ] == si )
       
   600 			{
       
   601 			huffCode[ p++ ] = code++;
       
   602 			}
       
   603 		code *= 2;
       
   604 		si++;
       
   605 		}
       
   606 
       
   607 	for( i=0; i<numSymbols; i++ )
       
   608 		{
       
   609 		TInt v = huffValue[ i ];
       
   610 		aHuffman->iLength[ v ] = huffLength[ i ];
       
   611 		aHuffman->iCode[ v ] = huffCode[ i ];
       
   612 		}
       
   613 	}
       
   614 
       
   615 
       
   616 
       
   617 void CJpegSave::WriteBits( TUint32 aValue, TInt aNumBits )
       
   618 	{
       
   619 
       
   620 	aValue &= ( ( 1 << aNumBits ) - 1 );
       
   621 	while( aNumBits > 0 )
       
   622 		{
       
   623 		TInt bitroom = 8 - iSaveBufBitPos;
       
   624 		iSaveByte |= ( ( aValue << ( 24+bitroom-aNumBits ) ) >> 24 );
       
   625 
       
   626 		if( aNumBits < bitroom )
       
   627 			{
       
   628 			iSaveBufBitPos += aNumBits;
       
   629 			}
       
   630 		else
       
   631 			{
       
   632 			iSaveBufBitPos += bitroom;
       
   633 			}
       
   634 
       
   635 		if( iSaveBufBitPos == 8 ) 
       
   636 			{
       
   637 			iSaveBufBitPos = 0;
       
   638 			iSaveBuf[ iSaveBufPos ] = iSaveByte;
       
   639 
       
   640 			if( iSaveByte == 255 )
       
   641 				{
       
   642 				iSaveBufPos++;
       
   643 				if( iSaveBufPos == iSaveBufSize )
       
   644 					{
       
   645 					FlushSaveBuf();
       
   646 					}
       
   647 				iSaveBuf[ iSaveBufPos ] = 0;	// 255,0 = 255 ( escaped 255 )
       
   648 				}
       
   649 			iSaveByte = 0;
       
   650 			iSaveBufPos++;
       
   651 
       
   652 			if( iSaveBufPos == iSaveBufSize )
       
   653 				{
       
   654 				FlushSaveBuf();
       
   655 				}
       
   656 
       
   657 			}
       
   658 		aNumBits -= bitroom;
       
   659 		}
       
   660 	}
       
   661 
       
   662 
       
   663 
       
   664 TInt CJpegSave::WriteDct( TInt* aDct, TSHuffman* aDc, TSHuffman* aAc )
       
   665 	{
       
   666 	TInt rv = 0;
       
   667 	TInt nullCount = 0;
       
   668 	bool theEnd = false;
       
   669 
       
   670 	for( TInt i=0; i<64; i++ )
       
   671 		{
       
   672 		if( i == 0 )
       
   673 			{
       
   674 			iCurrentHuffman = aDc;
       
   675 			}
       
   676 		else
       
   677 			{
       
   678 			iCurrentHuffman = aAc;
       
   679 			}
       
   680 
       
   681 		TInt value = aDct[ KZigZag[ i ] ] / iCurrentQuant[ i ];
       
   682 		if( i==0 ) rv = value * iCurrentQuant[ 0 ];
       
   683 			
       
   684 		bool doSave = true;
       
   685 
       
   686 		if( i > 0 && value == 0 )
       
   687 			{
       
   688 			
       
   689 			if( nullCount < 14 )
       
   690 				{
       
   691 				nullCount++;
       
   692 				doSave = false;
       
   693 				}
       
   694 			else
       
   695 				{
       
   696 				value = 0; // end of block, too many zeros
       
   697 				nullCount = 0;
       
   698 				theEnd = true;
       
   699 				}
       
   700 
       
   701 			}
       
   702 		
       
   703 		if( i == 63 && nullCount > 0 )
       
   704 			{
       
   705 			doSave = true;
       
   706 			value = 0;
       
   707 			nullCount = 0;
       
   708 			theEnd = true;
       
   709 			}
       
   710 
       
   711 		if( doSave )
       
   712 			{
       
   713 			bool minus = false;
       
   714 			if( value < 0 )
       
   715 				{
       
   716 				minus = true;
       
   717 				value = -value;
       
   718 				}
       
   719 			TInt v = value;
       
   720 			TInt vl = 0;
       
   721 			
       
   722 			while( v )
       
   723 				{
       
   724 				v >>= 1;
       
   725 				vl++;
       
   726 				}
       
   727 
       
   728 			if( minus ) 
       
   729 				{
       
   730 				TInt a = ( 1 << vl ) - 1;
       
   731 				value ^= a;
       
   732 				}
       
   733 
       
   734 			WriteHuffman( vl + nullCount * 16 );
       
   735 			WriteBits( value, vl );
       
   736 			if( theEnd ) // this is the end
       
   737 				{
       
   738 				break;
       
   739 				}
       
   740 			nullCount = 0;
       
   741 			}
       
   742 		}
       
   743 	return rv;
       
   744 	}
       
   745 
       
   746 
       
   747 
       
   748 void CJpegSave::Dct( TInt* aSrc, TInt* aTgt )
       
   749 	{
       
   750 	const TInt w1 = 237;
       
   751 	const TInt w2 = 98;
       
   752 	const TInt w3 = 181;
       
   753 	const TInt w4 = 251;
       
   754 	const TInt w5 = 50;
       
   755 	const TInt w6 = 213;
       
   756 	const TInt w7 = 142;
       
   757 
       
   758 	TInt s[8];
       
   759 	TInt t[6];
       
   760 	TInt r[4];
       
   761 	
       
   762 	int j;
       
   763 
       
   764 	
       
   765 	TInt* tp = aTgt;
       
   766 
       
   767 	for( j=0; j<8; j++ )
       
   768 		{
       
   769 		s[0] = aSrc[j +  0] + aSrc[j + 56];
       
   770 		s[1] = aSrc[j +  8] + aSrc[j + 48];
       
   771 		s[2] = aSrc[j + 16] + aSrc[j + 40];
       
   772 		s[3] = aSrc[j + 24] + aSrc[j + 32];
       
   773 		s[4] = aSrc[j + 24] - aSrc[j + 32];
       
   774 		s[5] = aSrc[j + 16] - aSrc[j + 40];
       
   775 		s[6] = aSrc[j +  8] - aSrc[j + 48];
       
   776 		s[7] = aSrc[j +  0] - aSrc[j + 56];
       
   777 		
       
   778 		t[0] = s[0] + s[3];
       
   779 		t[1] = s[1] + s[2];
       
   780 		t[2] = s[1] - s[2];
       
   781 		t[3] = s[0] - s[3];
       
   782 		t[4] = (s[6] - s[5]) * w3;
       
   783 		t[5] = (s[6] + s[5]) * w3;
       
   784 		
       
   785 		r[0] = s[4] * 256 + t[4];
       
   786 		r[1] = s[4] * 256 - t[4];
       
   787 		r[2] = s[7] * 256 - t[5];
       
   788 		r[3] = s[7] * 256 + t[5];
       
   789 		
       
   790 		*tp++ = (t[0] + t[1]) * w3 / 256;
       
   791 		*tp++ = (r[0] * w5 + r[3] * w4) / 256 / 256;
       
   792 		*tp++ = (t[2] * w2 + t[3] * w1) / 256;
       
   793 		*tp++ = (r[2] * w6 - r[1] * w7) / 256 / 256;
       
   794 		*tp++ = (t[0] - t[1]) * w3 / 256;
       
   795 		*tp++ = (r[1] * w6 + r[2] * w7) / 256 / 256;
       
   796 		*tp++ = (t[3] * w2 - t[2] * w1) / 256;
       
   797 		*tp++ = (r[3] * w5 - r[0] * w4) / 256 / 256;
       
   798 		}
       
   799 
       
   800 	for( j=0; j<8; j++ )
       
   801 		{
       
   802 		s[0] = aTgt[j + 0] + aTgt[j + 56];
       
   803 		s[1] = aTgt[j + 8] + aTgt[j + 48];
       
   804 		s[2] = aTgt[j + 16] + aTgt[j + 40];
       
   805 		s[3] = aTgt[j + 24] + aTgt[j + 32];
       
   806 		s[4] = aTgt[j + 24] - aTgt[j + 32];
       
   807 		s[5] = aTgt[j + 16] - aTgt[j + 40];
       
   808 		s[6] = aTgt[j + 8] - aTgt[j + 48];
       
   809 		s[7] = aTgt[j + 0] - aTgt[j + 56];
       
   810 		
       
   811 		t[0] = s[0] + s[3];
       
   812 		t[1] = s[1] + s[2];
       
   813 		t[2] = s[1] - s[2];
       
   814 		t[3] = s[0] - s[3];
       
   815 		t[4] = (s[6] - s[5]) * w3;
       
   816 		t[5] = (s[6] + s[5]) * w3;
       
   817 		
       
   818 		r[0] = s[4] * 256 + t[4];
       
   819 		r[1] = s[4] * 256 - t[4];
       
   820 		r[2] = s[7] * 256 - t[5];
       
   821 		r[3] = s[7] * 256 + t[5];
       
   822 		
       
   823 		aTgt[ 0 + j] = (t[0] + t[1]) * w3 / 256 / 4;
       
   824 		aTgt[32 + j] = (t[0] - t[1]) * w3 / 256 / 4;
       
   825 		aTgt[ 8 + j] = (r[0] * w5 + r[3] * w4) / 256 / 256 / 4;
       
   826 		aTgt[56 + j] = (r[3] * w5 - r[0] * w4) / 256 / 256 / 4;
       
   827 		aTgt[24 + j] = (r[2] * w6 - r[1] * w7) / 256 / 256 / 4;
       
   828 		aTgt[40 + j] = (r[1] * w6 + r[2] * w7) / 256 / 256 / 4;
       
   829 		aTgt[16 + j] = (t[2] * w2 + t[3] * w1) / 256 / 4;
       
   830 		aTgt[48 + j] = (t[3] * w2 - t[2] * w1) / 256 / 4;
       
   831 		}
       
   832 
       
   833 	}
       
   834 
       
   835 
       
   836 
       
   837 void CJpegSave::Rgb2Yuv( TUint32* aRgb, TInt /*aWidth*/, TInt* aY, TInt* aU, TInt* aV )
       
   838 	{
       
   839 	TInt pos = 0;
       
   840 	TInt yy;
       
   841 	TInt xx;
       
   842 	TInt y;
       
   843 	for( yy=0; yy<1; yy++ )
       
   844 	for( xx=0; xx<2; xx++ )
       
   845 	for( y=0; y<8; y++ )
       
   846 		{
       
   847 		TInt cpos = xx*4 + y*8;
       
   848 		TInt x;
       
   849 		for( x=0; x<8; x++ )
       
   850 			{
       
   851 			TUint32 c = aRgb[ x + xx*8 + y*16 + yy * 128 ];
       
   852 			TInt r = ( c >> 16 ) & 0xff;
       
   853 			TInt g = ( c >> 8 ) & 0xff;
       
   854 			TInt b = c & 0xff;
       
   855 
       
   856 			TInt cy = ( 19595*r + 38470*g + 7471*b ) >> 16;
       
   857 			//TInt cy = 0.29900*r + 0.58700*g + 0.11400*b;
       
   858 			//if( y<0 ) cy=0;
       
   859 			//if( y>255 ) cy=255;
       
   860 			aY[ pos++ ] = cy - 128;
       
   861 
       
   862 			if( x & 1 )
       
   863 				{
       
   864 				TInt t = ( ( -11059*r - 21710*g + 32768*b ) >> 16 );
       
   865 				//TInt t = -0.16874*r - 0.33126*g + 0.50000*b + 128;
       
   866 				//if( t<-128 ) t=-128;
       
   867 				//if( t>127 ) t=127;
       
   868 				aU[ cpos ] = t;
       
   869 
       
   870 				t = ( ( 32768*r - 27439*g - 5329*b ) >> 16 );
       
   871 				//t = 0.50000*r - 0.41869*g - 0.08131*b + 128;
       
   872 				//if( t<-128 ) t=-128;
       
   873 				//if( t>127 ) t=127;
       
   874 				aV[ cpos++ ] = t;
       
   875 				}
       
   876 			}
       
   877 		}
       
   878 
       
   879 
       
   880 	// 1:1:1 macroblock version
       
   881 	/*
       
   882 	TUint32* p = aRgb;
       
   883 	TInt mod = ( aWidth - 8 );
       
   884 	TInt pos = 0;
       
   885 	TInt y;
       
   886 	
       
   887 	for( y=0; y<8; y++ )
       
   888 		{
       
   889 		TInt x;
       
   890 		for( x=0; x<8; x++ )
       
   891 			{
       
   892 			TUint32 c = *p++;
       
   893 			TInt r = c >> 16;
       
   894 			TInt g = ( c >> 8 ) & 0xff;
       
   895 			TInt b = c & 0xff;
       
   896 
       
   897 			TInt y = ( 19595*r + 38470*g + 7471*b ) >> 16;
       
   898 			//TInt y = 0.29900*r + 0.58700*g + 0.11400*b;
       
   899 			if( y<0 ) y=0;
       
   900 			if( y>255 ) y=255;
       
   901 			aY[ pos ] = y - 128;
       
   902 			
       
   903 
       
   904 			TInt t = ( ( -11059*r - 21710*g + 32768*b ) >> 16 );
       
   905 			//TInt t = -0.16874*r - 0.33126*g + 0.50000*b + 128;
       
   906 			if( t<-128 ) t=-128;
       
   907 			if( t>127 ) t=127;
       
   908 			aU[ pos ] = t;
       
   909 
       
   910 			t = ( ( 32768*r - 27439*g - 5329*b ) >> 16 );
       
   911 			//t = 0.50000*r - 0.41869*g - 0.08131*b + 128;
       
   912 			if( t<-128 ) t=-128;
       
   913 			if( t>127 ) t=127;
       
   914 			aV[ pos ] = t;
       
   915 			pos++;
       
   916 			}
       
   917 		p += mod;
       
   918 		}
       
   919 */
       
   920 
       
   921 	}
       
   922 
       
   923 
       
   924 
       
   925 void CJpegSave::MakeTables( TInt aQuality, TUint8* aY, TUint8* aUV )
       
   926 	{
       
   927 	TInt i;
       
   928 	TInt factor = aQuality;
       
   929 
       
   930 	if( aQuality < 1 ) factor = 1;
       
   931 	if( aQuality > 99 ) factor = 99;
       
   932 	if( aQuality < 50 )
       
   933 		{
       
   934 		aQuality = 5000 / factor;
       
   935 		}
       
   936 	else
       
   937 		{
       
   938 		aQuality = 200 - factor*2;
       
   939 		}
       
   940 
       
   941 
       
   942 	for( i=0; i < 64; i++ )
       
   943 		{
       
   944 		TInt y = ( jpeg_luma_quantizer[i] * aQuality + 50) / 100;
       
   945 		TInt uv = ( jpeg_chroma_quantizer[i] * aQuality + 50) / 100;
       
   946 
       
   947 		if( y < 1) y = 1;
       
   948 		if( uv < 1) uv = 1;
       
   949 		if( y > 255) y = 255;
       
   950 		if( uv > 255) uv = 255;
       
   951 
       
   952 		aY[ i ] = y;
       
   953 		aUV[ i ] = uv;
       
   954 		}
       
   955 	}
       
   956 
       
   957 
       
   958 
       
   959 void CJpegSave::WriteSaveBuffer( const TUint8* aSrc, TInt aBytes )
       
   960 	{
       
   961 	TInt pos = 0;
       
   962 	while( aBytes )
       
   963 		{
       
   964 		TInt bytes = aBytes;
       
   965 		if( iSaveBufPos + bytes > iSaveBufSize )
       
   966 			{
       
   967 			bytes = iSaveBufSize - iSaveBufPos;
       
   968 			}
       
   969 		Mem::Copy( iSaveBuf + iSaveBufPos, aSrc + pos, bytes );
       
   970 		iSaveBufPos += bytes;
       
   971 		if( iSaveBufPos == iSaveBufSize )
       
   972 			{
       
   973 			FlushSaveBuf();
       
   974 			}
       
   975 		aBytes -= bytes;
       
   976 		pos += bytes;
       
   977 		}
       
   978 	}
       
   979 
       
   980 
       
   981 
       
   982 void CJpegSave::WriteSaveBuffer( TUint8 aValue )
       
   983 	{
       
   984 	iSaveBuf[ iSaveBufPos++ ] = aValue;
       
   985 	if( iSaveBufPos == iSaveBufSize )
       
   986 		{
       
   987 		FlushSaveBuf();
       
   988 		}
       
   989 	}
       
   990 
       
   991 
       
   992 
       
   993 void CJpegSave::WriteSaveBuffer( TUint16 aValue )
       
   994 	{
       
   995 	WriteSaveBuffer( (TUint8) ( aValue / 256 ) );
       
   996 	WriteSaveBuffer( (TUint8) ( aValue & 255 ) );
       
   997 	}
       
   998 
       
   999 
       
  1000 
       
  1001 void CJpegSave::FlushSaveBuf()
       
  1002 	{
       
  1003 	if( &iSaveFile == NULL ) return;		// no flushing without file
       
  1004 	TPtr8 ptr( iSaveBuf, iSaveBufPos );
       
  1005 	ptr.SetLength( iSaveBufPos );
       
  1006 	if( iSaveFile )iSaveFile->Write( ptr );
       
  1007 	iSaveBufPos = 0;
       
  1008 	}
       
  1009