mmplugins/imagingplugins/codecs/ImageProcessor.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <icl/imageprocessor.h>
       
    17 #include "ImageProcessorPriv.h"
       
    18 #include "ImageUtils.h"
       
    19 #include "ImageClientMain.h"
       
    20 
       
    21 //Size of dynamically allocated buffers used by CPixelWriter & CMonochromePixelWriter
       
    22 const TInt KPixelWriterBufferSize = 1024;
       
    23 const TInt KPixelWriterBufferThreeQuarter = 768;
       
    24 
       
    25 /**
       
    26 Constructor for this class.
       
    27 */
       
    28 EXPORT_C CImageProcessorExtension::CImageProcessorExtension()
       
    29 :iOperation(EDecodeNormal)
       
    30 	{
       
    31 	}
       
    32 
       
    33 /**
       
    34 Destructor for this class.
       
    35 */
       
    36 EXPORT_C CImageProcessorExtension::~CImageProcessorExtension()
       
    37 	{
       
    38 	}
       
    39 
       
    40 /**
       
    41 Sets the area of interest of the image to be decoded.
       
    42 
       
    43 @param aRect
       
    44 	   A reference to a TRect that specifies the location and size of the region to be decoded.
       
    45 
       
    46 */
       
    47 EXPORT_C void CImageProcessorExtension::SetClippingRect(const TRect& aRect)
       
    48 	{
       
    49 	iClippingRect = aRect;
       
    50 	}
       
    51 
       
    52 /**
       
    53 Sets the scaling coefficient for the decode.
       
    54 
       
    55 @param aScalingCoeff
       
    56 	   The scaling coefficient.
       
    57 
       
    58 @see TImageConvScaler::SetScalingL
       
    59 */
       
    60 EXPORT_C void CImageProcessorExtension::SetScaling(TInt aScalingCoeff)
       
    61 	{
       
    62 	iScalingCoeff = aScalingCoeff;
       
    63 	}
       
    64 
       
    65 /**
       
    66 Sets the desired size of the destination image for the decode.
       
    67 
       
    68 @param aDesiredSize
       
    69 	   The desired size of the destination image.
       
    70 
       
    71 @see TImageConvScaler::SetScalingL
       
    72 */
       
    73 EXPORT_C void CImageProcessorExtension::SetScaling(const TSize& aDesiredSize)
       
    74 	{
       
    75 	iDesiredSize = aDesiredSize;
       
    76 	}
       
    77 
       
    78 /**
       
    79 Sets the operation to be applied to the image.
       
    80 
       
    81 @param aOperation
       
    82 	   The operation to apply to the image.
       
    83 
       
    84 @see TImageConvScaler::SetScalingL
       
    85 */
       
    86 EXPORT_C void CImageProcessorExtension::SetOperation(TTransformOptions aOperation)
       
    87 	{
       
    88 	iOperation = aOperation;
       
    89 	}
       
    90 
       
    91 /**
       
    92 Sets an initial one-off number of scanlines to be skipped.
       
    93 This must be called prior to calling SetYPosIncrement(),
       
    94 if it is to be used.
       
    95 
       
    96 @param  aNumberOfScanlines
       
    97         The number of scanlines to skip.
       
    98         
       
    99 @see CImageProcessor::SetYPosIncrement()
       
   100 */
       
   101 EXPORT_C void CImageProcessorExtension::SetInitialScanlineSkipPadding(TInt aNumberOfScanlines)
       
   102 	{
       
   103 	iNumberOfScanlinesToSkip = aNumberOfScanlines;
       
   104 	}
       
   105 
       
   106 //
       
   107 // ImageProcessorUtility
       
   108 //
       
   109 
       
   110 //
       
   111 //	CColorImageProcessor
       
   112 //
       
   113 
       
   114 /**
       
   115  * @see CImageProcessor.
       
   116  * @internalComponent
       
   117  */
       
   118 void CColorImageProcessor::CreateBlockBufferL(TInt aBlockArea)
       
   119 	{
       
   120 	delete[] iBlockBuffer;
       
   121 	iBlockBuffer = NULL;
       
   122 
       
   123 	if(aBlockArea)
       
   124 		iBlockBuffer = new (ELeave) TRgb[aBlockArea];
       
   125 
       
   126 	iBlockArea = aBlockArea;
       
   127 	}
       
   128 
       
   129 /**
       
   130  * Destructor.
       
   131  * @see CImageProcessor.
       
   132  * @internalComponent
       
   133  */
       
   134 CColorImageProcessor::~CColorImageProcessor()
       
   135 	{
       
   136 	delete[] iBlockBuffer;
       
   137 	}
       
   138 
       
   139 /**
       
   140  * @see CImageProcessor.
       
   141  * @internalComponent
       
   142  */
       
   143 TBool CColorImageProcessor::SetPixelRun(TRgb aColor,TInt aCount)
       
   144 	{
       
   145 	TBool returnValue = EFalse;
       
   146 
       
   147 	while(aCount--)
       
   148 		returnValue |= SetPixel(aColor);
       
   149 
       
   150 	return returnValue;
       
   151 	}
       
   152 
       
   153 /**
       
   154  * @see CImageProcessor.
       
   155  * @internalComponent
       
   156  */
       
   157 TBool CColorImageProcessor::SetPixels(TRgb* aColorBuffer,TInt aBufferLength)
       
   158 	{
       
   159 	TBool returnValue = EFalse;
       
   160 
       
   161 	while(aBufferLength--)
       
   162 		returnValue |= SetPixel(*aColorBuffer++);
       
   163 
       
   164 	return returnValue;
       
   165 	}
       
   166 
       
   167 /**
       
   168  * @see CImageProcessor.
       
   169  * @internalComponent
       
   170  */
       
   171 TBool CColorImageProcessor::SetMonoPixel(TInt aGray256)
       
   172 	{
       
   173 	return SetPixel(TRgb(aGray256,aGray256,aGray256));
       
   174 	}
       
   175 
       
   176 /**
       
   177  * @see CImageProcessor.
       
   178  * @internalComponent
       
   179  */
       
   180 TBool CColorImageProcessor::SetMonoPixelRun(TInt aGray256,TInt aCount)
       
   181 	{
       
   182 	return SetPixelRun(TRgb(aGray256,aGray256,aGray256),aCount);
       
   183 	}
       
   184 
       
   185 /**
       
   186  * @see CImageProcessor.
       
   187  * @internalComponent
       
   188  */
       
   189 TBool CColorImageProcessor::SetMonoPixels(TUint32* aGray256Buffer,TInt aBufferLength)
       
   190 	{
       
   191 	TBool returnValue = EFalse;
       
   192 
       
   193 	while(aBufferLength--)
       
   194 		{
       
   195 		TUint32 gray256 = *aGray256Buffer++;
       
   196 		returnValue = SetPixel(TRgb(gray256,gray256,gray256));
       
   197 		}
       
   198 	return returnValue;
       
   199 	}
       
   200 
       
   201 /**
       
   202  * @see CImageProcessor.
       
   203  * @internalComponent
       
   204  */
       
   205 TBool CColorImageProcessor::SetMonoPixelBlock(TUint32* aGray256Buffer)
       
   206 	{
       
   207 	ASSERT(iBlockBuffer);
       
   208 
       
   209 	TRgb* blockBufferPtr = iBlockBuffer;
       
   210 	TRgb* blockBufferPtrLimit = blockBufferPtr+iBlockArea;
       
   211 
       
   212 	while(blockBufferPtr<blockBufferPtrLimit)
       
   213 		{
       
   214 		TUint32 gray256 = *aGray256Buffer++;
       
   215 		*blockBufferPtr++ = TRgb(gray256,gray256,gray256);
       
   216 		}
       
   217 
       
   218 	return SetPixelBlock(iBlockBuffer);
       
   219 	}
       
   220 
       
   221 //
       
   222 //	CMonochromeImageProcessor
       
   223 //
       
   224 
       
   225 /**
       
   226  * @see CImageProcessor.
       
   227  */
       
   228 void CMonochromeImageProcessor::CreateBlockBufferL(TInt aBlockArea)
       
   229 	{
       
   230 	delete[] iBlockBuffer;
       
   231 	iBlockBuffer = NULL;
       
   232 
       
   233 	iBlockBuffer = new (ELeave) TUint32[aBlockArea];
       
   234 	iBlockArea = aBlockArea;
       
   235 	}
       
   236 
       
   237 /**
       
   238  * Destructor.
       
   239  * @see CImageProcessor.
       
   240  */
       
   241 CMonochromeImageProcessor::~CMonochromeImageProcessor()
       
   242 	{
       
   243 	delete []iBlockBuffer;
       
   244 	}
       
   245 
       
   246 /**
       
   247  * @see CImageProcessor.
       
   248  */
       
   249 TBool CMonochromeImageProcessor::SetMonoPixelRun(TInt aGray256,TInt aCount)
       
   250 	{
       
   251 	TBool returnValue = EFalse;
       
   252 
       
   253 	while(aCount--)
       
   254 		returnValue = SetMonoPixel(aGray256);
       
   255 
       
   256 	return returnValue;
       
   257 	}
       
   258 
       
   259 /**
       
   260  * @see CImageProcessor.
       
   261  */
       
   262 TBool CMonochromeImageProcessor::SetMonoPixels(TUint32* aGray256Buffer,TInt aBufferLength)
       
   263 	{
       
   264 	TBool returnValue = EFalse;
       
   265 
       
   266 	while(aBufferLength--)
       
   267 		returnValue = SetMonoPixel(*aGray256Buffer++);
       
   268 
       
   269 	return returnValue;
       
   270 	}
       
   271 
       
   272 /**
       
   273  * @see CImageProcessor.
       
   274  */
       
   275 TBool CMonochromeImageProcessor::SetPixel(TRgb aColor)
       
   276 	{
       
   277 	return SetMonoPixel(TColorConvertor::RgbToMonochrome(aColor));
       
   278 	}
       
   279 
       
   280 /**
       
   281  * @see CImageProcessor.
       
   282  */
       
   283 TBool CMonochromeImageProcessor::SetPixelRun(TRgb aColor,TInt aCount)
       
   284 	{
       
   285 	return SetMonoPixelRun(TColorConvertor::RgbToMonochrome(aColor),aCount);
       
   286 	}
       
   287 
       
   288 /**
       
   289  * @see CImageProcessor.
       
   290  */
       
   291 TBool CMonochromeImageProcessor::SetPixels(TRgb* aColorBuffer,TInt aBufferLength)
       
   292 	{
       
   293 	TBool returnValue = EFalse;
       
   294 
       
   295 	while(aBufferLength--)
       
   296 		returnValue = SetMonoPixel(TColorConvertor::RgbToMonochrome(*aColorBuffer++));
       
   297 
       
   298 	return returnValue;
       
   299 	}
       
   300 
       
   301 /**
       
   302  * @see CImageProcessor.
       
   303  */
       
   304 TBool CMonochromeImageProcessor::SetPixelBlock(TRgb* aColorBuffer)
       
   305 	{
       
   306 	ASSERT(iBlockBuffer);
       
   307 
       
   308 	TUint32* blockBufferPtr = iBlockBuffer;
       
   309 	TUint32* blockBufferPtrLimit = blockBufferPtr+iBlockArea;
       
   310 
       
   311 	while(blockBufferPtr<blockBufferPtrLimit)
       
   312 		*blockBufferPtr++ = TColorConvertor::RgbToMonochrome(*aColorBuffer++);
       
   313 
       
   314 	return SetMonoPixelBlock(iBlockBuffer);
       
   315 	}
       
   316 
       
   317 //
       
   318 // CPixelWriter
       
   319 //
       
   320 
       
   321 /**
       
   322  *
       
   323  * Static factory function to create CPixelWriter objects.
       
   324  *
       
   325  * @return  Pointer to a fully constructed CPixelWriter object. 
       
   326  */
       
   327 CPixelWriter* CPixelWriter::NewL()
       
   328 	{
       
   329 	return new(ELeave) CPixelWriter;
       
   330 	}
       
   331 
       
   332 /**
       
   333  *
       
   334  * Default constructor for this class.
       
   335  */
       
   336 CPixelWriter::CPixelWriter():
       
   337 	iYInc(1)
       
   338 	{}	
       
   339 	
       
   340 /**
       
   341  *
       
   342  * Destructor.
       
   343  */
       
   344 CPixelWriter::~CPixelWriter()
       
   345 	{
       
   346 	Reset();
       
   347 	ASSERT(iColorConv==NULL);
       
   348 	ASSERT(iRgbBuffer==NULL);
       
   349 	ASSERT(iIndexBuffer==NULL);
       
   350 	}
       
   351 
       
   352 /**
       
   353  *
       
   354  * @see CImageProcessor
       
   355  */
       
   356 void CPixelWriter::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect)
       
   357 	{
       
   358 	DoPrepareL(aBitmap,aImageRect,NULL);
       
   359 	}
       
   360 
       
   361 /**
       
   362  *
       
   363  * @see CImageProcessor
       
   364  */
       
   365 void CPixelWriter::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize& aRgbBlockSize)
       
   366 	{
       
   367 	DoPrepareL(aBitmap,aImageRect,&aRgbBlockSize);
       
   368 	}
       
   369 
       
   370 /**
       
   371  *
       
   372  * @see CImageProcessor.
       
   373  */
       
   374 void CPixelWriter::SetYPosIncrement(TInt aYInc)
       
   375 	{
       
   376 	iYInc = aYInc - iNumberOfScanlinesToSkip;
       
   377 	}
       
   378 
       
   379 /**
       
   380  *
       
   381  * @see CImageProcessor.
       
   382  */
       
   383 void CPixelWriter::SetLineRepeat(TInt aLineRepeat)
       
   384 	{
       
   385 	ASSERT(aLineRepeat>=0);
       
   386 	iLineRepeat = aLineRepeat;
       
   387 	}
       
   388 
       
   389 /**
       
   390  *
       
   391  * @see CImageProcessor.
       
   392  */
       
   393 void CPixelWriter::SetPixelPadding(TInt aNumberOfPixels)
       
   394 	{
       
   395 	iPixelPadding = aNumberOfPixels;
       
   396 	}
       
   397 
       
   398 /**
       
   399  *
       
   400  * @see CImageProcessor.
       
   401  */
       
   402 TBool CPixelWriter::SetPixel(TRgb aColor)
       
   403 	{
       
   404 	*iRgbBufferPtr++ = aColor;
       
   405 
       
   406 	if (iRgbBufferPtr == iRgbBufferPtrLimit)
       
   407 		return FlushPixels();
       
   408 
       
   409 	return EFalse;
       
   410 	}
       
   411 
       
   412 /**
       
   413  *
       
   414  * @see CImageProcessor.
       
   415  */
       
   416 TBool CPixelWriter::SetPixelRun(TRgb aColor,TInt aCount)
       
   417 	{
       
   418 	while(aCount)
       
   419 		{
       
   420 		TRgb* ptr = iRgbBufferPtr;
       
   421 		TRgb* limit = ptr+aCount;
       
   422 		if(limit>iRgbBufferPtrLimit)
       
   423 			limit = iRgbBufferPtrLimit;
       
   424 
       
   425 		TInt n = limit-ptr;
       
   426 		aCount -= n;
       
   427 
       
   428 		if(n&1)
       
   429 			*ptr++ = aColor;
       
   430 		if(n&2)
       
   431 			{
       
   432 			*ptr++ = aColor;
       
   433 			*ptr++ = aColor;
       
   434 			}
       
   435 		if(n&4)
       
   436 			{
       
   437 			*ptr++ = aColor;
       
   438 			*ptr++ = aColor;
       
   439 			*ptr++ = aColor;
       
   440 			*ptr++ = aColor;
       
   441 			}
       
   442 		while(ptr<limit)
       
   443 			{
       
   444 			*ptr++ = aColor;
       
   445 			*ptr++ = aColor;
       
   446 			*ptr++ = aColor;
       
   447 			*ptr++ = aColor;
       
   448 			*ptr++ = aColor;
       
   449 			*ptr++ = aColor;
       
   450 			*ptr++ = aColor;
       
   451 			*ptr++ = aColor;
       
   452 			}
       
   453 
       
   454 		iRgbBufferPtr = ptr;
       
   455 
       
   456 		if(ptr!=iRgbBufferPtrLimit)
       
   457 			break;
       
   458 
       
   459 		if(FlushPixels())
       
   460 			return ETrue;
       
   461 		}
       
   462 
       
   463 	return EFalse;
       
   464 	}
       
   465 
       
   466 /**
       
   467  *
       
   468  * @see CImageProcessor.
       
   469  */
       
   470 TBool CPixelWriter::SetPixels(TRgb* aColorBuffer, TInt aBufferLength)
       
   471 	{
       
   472 	if (aBufferLength >= KPixelWriterBufferThreeQuarter)
       
   473 		{
       
   474 		TRgb* rgbBuffer = iRgbBuffer;
       
   475 
       
   476 		if (iRgbBufferPtr != rgbBuffer) 
       
   477 			{
       
   478 			// flush rest of the pixels 
       
   479 			if(FlushPixels())
       
   480 				{
       
   481 				return ETrue;
       
   482 				}
       
   483 			}
       
   484 
       
   485 		// use external buffer without copying data
       
   486 		TBool rValue = EFalse;
       
   487 
       
   488 		while (aBufferLength && !rValue)
       
   489 			{
       
   490 			TInt bufferLength = (aBufferLength>KPixelWriterBufferSize)?KPixelWriterBufferSize:aBufferLength;
       
   491 			iRgbBuffer = aColorBuffer;
       
   492 			iRgbBufferPtr = aColorBuffer+bufferLength;
       
   493 			iRgbBufferPtrLimit = aColorBuffer+bufferLength;
       
   494 
       
   495 			rValue = FlushPixels();
       
   496 			aBufferLength -= bufferLength;
       
   497 			aColorBuffer += bufferLength;
       
   498 			}
       
   499 		
       
   500 		// restore pointers to inner buffer
       
   501 		iRgbBuffer = rgbBuffer;
       
   502 		iRgbBufferPtr = rgbBuffer;
       
   503 		iRgbBufferPtrLimit = rgbBuffer+KPixelWriterBufferSize;
       
   504 		
       
   505 		return rValue;
       
   506 		}
       
   507 
       
   508 	while(aBufferLength)
       
   509 		{
       
   510 		TRgb* ptr = iRgbBufferPtr;
       
   511 		TRgb* limit = ptr+aBufferLength;
       
   512 		if(limit>iRgbBufferPtrLimit)
       
   513 			limit = iRgbBufferPtrLimit;
       
   514 
       
   515 		TInt n = limit-ptr;
       
   516 		aBufferLength -= n;
       
   517 
       
   518 		if(n&1)
       
   519 			*ptr++ = *aColorBuffer++;
       
   520 		if(n&2)
       
   521 			{
       
   522 			*ptr++ = *aColorBuffer++;
       
   523 			*ptr++ = *aColorBuffer++;
       
   524 			}
       
   525 		while(ptr<limit)
       
   526 			{
       
   527 			*ptr++ = *aColorBuffer++;
       
   528 			*ptr++ = *aColorBuffer++;
       
   529 			*ptr++ = *aColorBuffer++;
       
   530 			*ptr++ = *aColorBuffer++;
       
   531 			}
       
   532 
       
   533 		iRgbBufferPtr = ptr;
       
   534 
       
   535 		if(ptr!=iRgbBufferPtrLimit)
       
   536 			break;
       
   537 
       
   538 		if(FlushPixels())
       
   539 			return ETrue;
       
   540 		}
       
   541 
       
   542 	return EFalse;
       
   543 	}
       
   544 
       
   545 /**
       
   546  *
       
   547  * @see CImageProcessor.
       
   548  */
       
   549 TBool CPixelWriter::SetPixelBlock(TRgb* aColorBuffer)
       
   550 	{
       
   551 	ASSERT(aColorBuffer);
       
   552 
       
   553 	TUint32* indexBufferPtr = iIndexBuffer;
       
   554 	if (iDisplayMode==EColor16M || iDisplayMode == EColor16MU || iDisplayMode == EColor16MA)
       
   555 		{
       
   556 		indexBufferPtr = reinterpret_cast<TUint32*>(aColorBuffer);
       
   557 		}
       
   558 	else
       
   559 		{
       
   560 		SetPixelBlockIndex(aColorBuffer);
       
   561 		}
       
   562 
       
   563 	TInt ySkip = 0;
       
   564 	if(iNumberOfScanlinesToSkip > 0)
       
   565 		{
       
   566 		ySkip = iNumberOfScanlinesToSkip * iBlockSize.iWidth;
       
   567 		indexBufferPtr += ySkip;
       
   568 		ySkip = iNumberOfScanlinesToSkip;
       
   569 		iNumberOfScanlinesToSkip = 0; // Only call this conditional once.
       
   570 		}
       
   571 	
       
   572 	TInt imageWidth = iImageRegion.iBr.iX;
       
   573 	TInt imageHeight = iImageRegion.iBr.iY;
       
   574 	TInt endOfImage = iDrawBottomUp ? -1 : imageHeight;
       
   575 	
       
   576 	// The minimum number of pixels to render horizontally
       
   577 	TInt minWidth = Min(iBlockSize.iWidth, imageWidth - iPos.iX);
       
   578 	
       
   579 	// The next vertical position.  Note that this is usually the height of the block, but 
       
   580 	// in the case of the first block when clipping is required, this will be reduced by ySkip.
       
   581 	TInt nextYPos = iDrawBottomUp ?	(iPos.iY - iBlockSize.iHeight) + ySkip :
       
   582 									(iPos.iY + iBlockSize.iHeight) - ySkip;
       
   583 	
       
   584 	TInt endPosition = iDrawBottomUp ? Max(nextYPos, endOfImage) : Min(nextYPos, endOfImage);
       
   585 	
       
   586 	// Once the first block has been processed, iYInc is set to block height
       
   587 	iYInc = iDrawBottomUp ? -iBlockSize.iHeight + ySkip : iBlockSize.iHeight - ySkip;
       
   588 				
       
   589 	// Skip unnecessary pixels (for cropping, or padding when rotated)
       
   590 	indexBufferPtr += iPixelPadding;
       
   591 	
       
   592 	TPoint pos(iPos);
       
   593 	iUtil.Begin();
       
   594 	for(;iDrawBottomUp ? pos.iY > endPosition : pos.iY < endPosition; iDrawBottomUp ? pos.iY-- : pos.iY++)
       
   595 		{
       
   596 		iUtil.SetPos(pos);
       
   597 		iUtil.SetPixels(indexBufferPtr, minWidth);
       
   598 		indexBufferPtr += iBlockSize.iWidth; // next line in block
       
   599 		}
       
   600 	iUtil.End();
       
   601 
       
   602 	iPos.iX += iBlockSize.iWidth;
       
   603 	
       
   604 	if (iPos.iX >= imageWidth)
       
   605 		{
       
   606 		return NewLine();
       
   607 		}
       
   608 
       
   609 	return EFalse;
       
   610 	}
       
   611 
       
   612 /**
       
   613  *
       
   614  * @see CImageProcessor.
       
   615  */
       
   616 TBool CPixelWriter::FlushPixels()
       
   617 	{
       
   618 	TRgb* rgbBufferPtrLimit = iRgbBufferPtr;
       
   619 	iRgbBufferPtr = iRgbBuffer;
       
   620 
       
   621 	if(iPos.iY < iImageRegion.iTl.iY || iPos.iY >= iImageRegion.iBr.iY)
       
   622 		return ETrue;
       
   623 
       
   624 	iUtil.Begin();
       
   625 
       
   626 	TBool finished = EFalse;
       
   627 	for (TRgb* rgbBufferPtr = iRgbBuffer; rgbBufferPtr < rgbBufferPtrLimit; )
       
   628 		{
       
   629 		TInt pixelsToSkip = Min(rgbBufferPtrLimit - rgbBufferPtr,iPixelsToSkip);
       
   630 		rgbBufferPtr += pixelsToSkip;
       
   631 		iPixelsToSkip -= pixelsToSkip;
       
   632 
       
   633 		if(iPixelsToSkip)
       
   634 			break;
       
   635 
       
   636 		TInt pixelsToFlush = Min(rgbBufferPtrLimit - rgbBufferPtr,iImageRegion.iBr.iX - iPos.iX);
       
   637 
       
   638 		if(!pixelsToFlush)
       
   639 			break;
       
   640 
       
   641 		SetPixelBufferIndex(rgbBufferPtr,pixelsToFlush);
       
   642 		rgbBufferPtr += pixelsToFlush;
       
   643 
       
   644 		TBool fillDown = iYInc > 0;
       
   645 		TPoint pos(iPos);
       
   646 		TInt posYLimit;
       
   647 		if(fillDown)
       
   648 			posYLimit = Min(pos.iY + iLineRepeat + 1 ,iImageRegion.iBr.iY);
       
   649 		else
       
   650 			posYLimit = Max(pos.iY - iLineRepeat - 1 ,iImageRegion.iTl.iY-1);
       
   651 
       
   652 		for(;fillDown ? pos.iY < posYLimit : pos.iY > posYLimit; fillDown ? pos.iY++ : pos.iY--)
       
   653 			{
       
   654 			if(!iUtil.SetPos(pos-iImageRegion.iTl))
       
   655 				{
       
   656 				iUtil.End();
       
   657 				return ETrue;
       
   658 				}
       
   659 			iUtil.SetPixels(iIndexBuffer,pixelsToFlush);
       
   660 			}
       
   661 
       
   662 		iPos.iX += pixelsToFlush;
       
   663 		if (iPos.iX >= iImageRegion.iBr.iX)
       
   664 			{
       
   665 			finished = NewLine();
       
   666 			if(finished)
       
   667 				break;
       
   668 			}
       
   669 		}
       
   670 
       
   671 	iUtil.End();
       
   672 
       
   673 	return finished;
       
   674 	}
       
   675 
       
   676 /**
       
   677  *
       
   678  * @see CImageProcessor.
       
   679  */
       
   680 TBool CPixelWriter::SetPos(const TPoint& aPosition)
       
   681 	{
       
   682 	if(iImageRegion.Contains(aPosition))
       
   683 		{
       
   684 		FlushPixels();
       
   685 		iPixelsToSkip = 0;
       
   686 		iPos = aPosition;
       
   687 		return ETrue;
       
   688 		}
       
   689 
       
   690 	return EFalse;
       
   691 	}
       
   692 
       
   693 void CPixelWriter::Reset()
       
   694 	{
       
   695 	delete iColorConv;
       
   696 	iColorConv = NULL;
       
   697 
       
   698 	delete[] iRgbBuffer;
       
   699 	iRgbBuffer = NULL;
       
   700 
       
   701 	delete[] iIndexBuffer;
       
   702 	iIndexBuffer = NULL;
       
   703 
       
   704 	iPos.SetXY(0,0);
       
   705 	iPixelsToSkip = 0;
       
   706 	iImageRegion.SetRect(0,0,0,0);
       
   707 	iBlockSize.SetSize(0,0);
       
   708 	
       
   709 	iDrawBottomUp = EFalse;
       
   710 	}
       
   711 
       
   712 void CPixelWriter::DoPrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize* aBlockSize)
       
   713 	{
       
   714 	if( (aImageRect.iTl.iX<0) || (aImageRect.iTl.iY<0) || (aImageRect.Size().iWidth>aBitmap.SizeInPixels().iWidth) || (aImageRect.Size().iHeight>aBitmap.SizeInPixels().iHeight) )
       
   715 		{
       
   716 		User::Leave(KErrArgument);
       
   717 		}
       
   718 
       
   719 	Reset();
       
   720 	
       
   721 	iDisplayMode = aBitmap.DisplayMode();
       
   722 
       
   723 	iImageRegion = aImageRect;
       
   724 
       
   725 	ASSERT(iColorConv==NULL);
       
   726 	iColorConv = TColorConvertor::NewL(aBitmap.DisplayMode());
       
   727 	iUtil.SetBitmapL(&aBitmap);
       
   728 
       
   729 	if (aBlockSize)
       
   730 		{
       
   731 		if (aBlockSize->iWidth <= 0 || aBlockSize->iHeight <= 0)
       
   732 			{
       
   733 			User::Leave(KErrArgument);
       
   734 			}
       
   735 
       
   736 		iBlockSize = *aBlockSize;
       
   737 		iBlockArea = iBlockSize.iWidth * iBlockSize.iHeight;
       
   738 		
       
   739 		ASSERT(iIndexBuffer == NULL);
       
   740 		iIndexBuffer = new(ELeave) TUint32[iBlockArea];
       
   741 
       
   742 		iIndexBufferPtrLimit = iIndexBuffer + iBlockArea;
       
   743 		CreateBlockBufferL(iBlockArea);
       
   744 		
       
   745 		switch(iOperation)
       
   746 			{
       
   747 			case EDecodeRotate180:
       
   748 			case EDecodeRotate270:
       
   749 			case EDecodeHorizontalFlip:
       
   750 			case EDecodeVerticalFlipRotate90:
       
   751 				iDrawBottomUp = ETrue;
       
   752 				break;
       
   753 			default:
       
   754 				iDrawBottomUp = EFalse;
       
   755 			}
       
   756 		
       
   757 		iYInc = iDrawBottomUp ? -iBlockSize.iHeight : iBlockSize.iHeight;
       
   758 		iStartPosition.SetXY(iImageRegion.iTl.iX, iDrawBottomUp ? iImageRegion.iBr.iY - 1 : 0);
       
   759 		iEndPosition.SetXY(iImageRegion.iBr.iX, iDrawBottomUp ?
       
   760 							iImageRegion.iTl.iY - 1 : iImageRegion.iBr.iY);
       
   761 		iPos = iStartPosition;
       
   762 		}
       
   763 	else
       
   764 		{
       
   765 		iPos = iImageRegion.iTl;
       
   766 		iStartPosition = iPos;
       
   767 		iEndPosition = aImageRect.iBr;
       
   768 		
       
   769 		ASSERT(iRgbBuffer == NULL);
       
   770 		iRgbBuffer = new(ELeave) TRgb[KPixelWriterBufferSize];
       
   771 
       
   772 		iRgbBufferPtr = iRgbBuffer;
       
   773 		iRgbBufferPtrLimit = iRgbBuffer + KPixelWriterBufferSize;
       
   774 
       
   775 		ASSERT(iIndexBuffer == NULL);
       
   776 		iIndexBuffer = new(ELeave) TUint32[KPixelWriterBufferSize];
       
   777 
       
   778 		iIndexBufferPtrLimit = iIndexBuffer + KPixelWriterBufferSize;
       
   779 		}
       
   780 	}
       
   781 
       
   782 TBool CPixelWriter::NewLine()
       
   783 	{
       
   784 	iPos.iX = iStartPosition.iX;
       
   785 	iPos.iY += iYInc;
       
   786 
       
   787 	if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
   788 		{
       
   789 		return ETrue;
       
   790 		}
       
   791 	
       
   792 	iPixelsToSkip = iPixelPadding;
       
   793 	return EFalse;
       
   794 	}
       
   795 
       
   796 void CPixelWriter::SetPixelBufferIndex(TRgb* aColorBuffer,TInt aCount)
       
   797 	{
       
   798 	iColorConv->ColorToIndex(REINTERPRET_CAST(TInt*,iIndexBuffer),aColorBuffer,aCount);
       
   799 	}
       
   800 
       
   801 void CPixelWriter::SetPixelBlockIndex(TRgb* aColorBuffer)
       
   802 	{
       
   803 	iColorConv->ColorToIndex(REINTERPRET_CAST(TInt*,iIndexBuffer),aColorBuffer,iIndexBufferPtrLimit-iIndexBuffer);
       
   804 	}
       
   805 
       
   806 //
       
   807 //	CMonochromePixelWriter
       
   808 //
       
   809 
       
   810 /**
       
   811  *
       
   812  * Static factory function to create CMonochromePixelWriter objects.
       
   813  *
       
   814  * @return  Pointer to a fully constructed CMonochromePixelWriter object. 
       
   815  */
       
   816 CMonochromePixelWriter* CMonochromePixelWriter::NewL()
       
   817 	{
       
   818 	return new(ELeave) CMonochromePixelWriter;
       
   819 	}
       
   820 
       
   821 /**
       
   822  *
       
   823  * Default constructor for this class.
       
   824  */
       
   825 CMonochromePixelWriter::CMonochromePixelWriter():
       
   826 	iYInc(1)
       
   827 	{}
       
   828 
       
   829 /**
       
   830  *
       
   831  * Destructor
       
   832  */
       
   833 CMonochromePixelWriter::~CMonochromePixelWriter()
       
   834 	{
       
   835 	Reset();
       
   836 	}
       
   837 
       
   838 /**
       
   839  *
       
   840  * @see CImageProcessor
       
   841  */
       
   842 void CMonochromePixelWriter::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect)
       
   843 	{
       
   844 	DoPrepareL(aBitmap,aImageRect,NULL);
       
   845 	}
       
   846 
       
   847 /**
       
   848  *
       
   849  * @see CImageProcessor
       
   850  */
       
   851 void CMonochromePixelWriter::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize& aRgbBlockSize)
       
   852 	{
       
   853 	DoPrepareL(aBitmap,aImageRect,&aRgbBlockSize);
       
   854 	}
       
   855 
       
   856 /**
       
   857  *
       
   858  * @see CImageProcessor.
       
   859  */
       
   860 void CMonochromePixelWriter::SetYPosIncrement(TInt aYInc)
       
   861 	{
       
   862 	iYInc = aYInc - iNumberOfScanlinesToSkip;
       
   863 	}
       
   864 
       
   865 /**
       
   866  *
       
   867  * @see CImageProcessor.
       
   868  */
       
   869 void CMonochromePixelWriter::SetPixelPadding(TInt aNumberOfPixels)
       
   870 	{
       
   871 	iPixelPadding = aNumberOfPixels;
       
   872 	}
       
   873 
       
   874 /**
       
   875  *
       
   876  * @see CImageProcessor.
       
   877  */
       
   878 void CMonochromePixelWriter::SetLineRepeat(TInt aLineRepeat)
       
   879 	{
       
   880 	ASSERT(aLineRepeat>=0);
       
   881 	iLineRepeat = aLineRepeat;
       
   882 	}
       
   883 
       
   884 /**
       
   885  *
       
   886  * @see CImageProcessor.
       
   887  */
       
   888 TBool CMonochromePixelWriter::SetMonoPixel(TInt aGray256)
       
   889 	{
       
   890 	*iGray256BufferPtr++ = aGray256;
       
   891 
       
   892 	if (iGray256BufferPtr != iGray256BufferPtrLimit)
       
   893 		return EFalse;
       
   894 
       
   895 	return FlushPixels();
       
   896 	}
       
   897 
       
   898 /**
       
   899  *
       
   900  * @see CImageProcessor.
       
   901  */
       
   902 TBool CMonochromePixelWriter::SetMonoPixelRun(TInt aGray256,TInt aCount)
       
   903 	{
       
   904 	while(aCount)
       
   905 		{
       
   906 		TUint32* ptr = iGray256BufferPtr;
       
   907 		TUint32* limit = ptr+aCount;
       
   908 		if(limit>iGray256BufferPtrLimit)
       
   909 			limit = iGray256BufferPtrLimit;
       
   910 
       
   911 		TInt n = limit-ptr;
       
   912 		aCount -= n;
       
   913 
       
   914 		if(n&1)
       
   915 			*ptr++ = aGray256;
       
   916 		if(n&2)
       
   917 			{
       
   918 			*ptr++ = aGray256;
       
   919 			*ptr++ = aGray256;
       
   920 			}
       
   921 		if(n&4)
       
   922 			{
       
   923 			*ptr++ = aGray256;
       
   924 			*ptr++ = aGray256;
       
   925 			*ptr++ = aGray256;
       
   926 			*ptr++ = aGray256;
       
   927 			}
       
   928 		while(ptr<limit)
       
   929 			{
       
   930 			*ptr++ = aGray256;
       
   931 			*ptr++ = aGray256;
       
   932 			*ptr++ = aGray256;
       
   933 			*ptr++ = aGray256;
       
   934 			*ptr++ = aGray256;
       
   935 			*ptr++ = aGray256;
       
   936 			*ptr++ = aGray256;
       
   937 			*ptr++ = aGray256;
       
   938 			}
       
   939 
       
   940 		iGray256BufferPtr = ptr;
       
   941 
       
   942 		if(ptr!=iGray256BufferPtrLimit)
       
   943 			break;
       
   944 
       
   945 		if(FlushPixels())
       
   946 			return ETrue;
       
   947 		}
       
   948 
       
   949 	return EFalse;
       
   950 	}
       
   951 
       
   952 /**
       
   953  *
       
   954  * @see CImageProcessor.
       
   955  */
       
   956 TBool CMonochromePixelWriter::SetMonoPixels(TUint32* aGray256Buffer,TInt aBufferLength)
       
   957 	{
       
   958 
       
   959 	if (aBufferLength >= KPixelWriterBufferThreeQuarter)
       
   960 		{
       
   961 		TUint32* gray256Buffer = iGray256Buffer;
       
   962 
       
   963 		if (iGray256BufferPtr != gray256Buffer) 
       
   964 			{
       
   965 			// flush rest of the pixels 
       
   966 			if(FlushPixels())
       
   967 				{
       
   968 				return ETrue;
       
   969 				}
       
   970 			}
       
   971 
       
   972 		// use external buffer without copying data
       
   973 		TBool rValue = EFalse;
       
   974 		
       
   975 		while (aBufferLength && !rValue)
       
   976 			{
       
   977 			TInt bufferLength = (aBufferLength>KPixelWriterBufferSize)?KPixelWriterBufferSize:aBufferLength;
       
   978 			iGray256Buffer = aGray256Buffer;
       
   979 			iGray256BufferPtr = aGray256Buffer+bufferLength;
       
   980 			iGray256BufferPtrLimit = aGray256Buffer+bufferLength;
       
   981 
       
   982 			rValue = FlushPixels();
       
   983 			aBufferLength -= bufferLength;
       
   984 			aGray256Buffer += bufferLength;
       
   985 			}
       
   986 		
       
   987 		// restore pointers to inner buffer
       
   988 		iGray256Buffer = gray256Buffer;
       
   989 		iGray256BufferPtr = gray256Buffer;
       
   990 		iGray256BufferPtrLimit = gray256Buffer+KPixelWriterBufferSize;
       
   991 		
       
   992 		return rValue;
       
   993 		}
       
   994 
       
   995 	while(aBufferLength)
       
   996 		{
       
   997 		TUint32* ptr = iGray256BufferPtr;
       
   998 		TUint32* limit = ptr+aBufferLength;
       
   999 		if(limit>iGray256BufferPtrLimit)
       
  1000 			limit = iGray256BufferPtrLimit;
       
  1001 
       
  1002 		TInt n = limit-ptr;
       
  1003 		aBufferLength -= n;
       
  1004 
       
  1005 		if(n&1)
       
  1006 			*ptr++ = *aGray256Buffer++;
       
  1007 		if(n&2)
       
  1008 			{
       
  1009 			*ptr++ = *aGray256Buffer++;
       
  1010 			*ptr++ = *aGray256Buffer++;
       
  1011 			}
       
  1012 		while(ptr<limit)
       
  1013 			{
       
  1014 			*ptr++ = *aGray256Buffer++;
       
  1015 			*ptr++ = *aGray256Buffer++;
       
  1016 			*ptr++ = *aGray256Buffer++;
       
  1017 			*ptr++ = *aGray256Buffer++;
       
  1018 			}
       
  1019 
       
  1020 		iGray256BufferPtr = ptr;
       
  1021 
       
  1022 		if(ptr!=iGray256BufferPtrLimit)
       
  1023 			break;
       
  1024 
       
  1025 		if(FlushPixels())
       
  1026 			return ETrue;
       
  1027 		}
       
  1028 
       
  1029 	return EFalse;
       
  1030 	}
       
  1031 
       
  1032 /**
       
  1033  *
       
  1034  * @see CImageProcessor.
       
  1035  */
       
  1036 TBool CMonochromePixelWriter::SetMonoPixelBlock(TUint32* aGray256Buffer)
       
  1037 	{
       
  1038 	SetPixelBlockIndex(aGray256Buffer);
       
  1039 	
       
  1040 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1041 
       
  1042 	TInt ySkip = 0;
       
  1043 	if(iNumberOfScanlinesToSkip > 0)
       
  1044 		{
       
  1045 		ySkip = iNumberOfScanlinesToSkip * iBlockSize.iWidth;
       
  1046 		indexBufferPtr += ySkip;
       
  1047 		ySkip = iNumberOfScanlinesToSkip;
       
  1048 		iNumberOfScanlinesToSkip = 0; // Only call this conditional once.
       
  1049 		}
       
  1050 	
       
  1051 	TInt imageWidth = iImageRegion.iBr.iX;
       
  1052 	TInt imageHeight = iImageRegion.iBr.iY;
       
  1053 	TInt endOfImage = iDrawBottomUp ? -1 : imageHeight;
       
  1054 	
       
  1055 	// The minimum number of pixels to render horizontally
       
  1056 	TInt minWidth = Min(iBlockSize.iWidth, imageWidth - iPos.iX);
       
  1057 	
       
  1058 	// The next vertical position.  Note that this is usually the height of the block, but 
       
  1059 	// in the case of the first block when clipping is required, this will be reduced by ySkip.
       
  1060 	TInt nextYPos = iDrawBottomUp ?	(iPos.iY - iBlockSize.iHeight) + ySkip :
       
  1061 										(iPos.iY + iBlockSize.iHeight) - ySkip;
       
  1062 	
       
  1063 	TInt endPosition = iDrawBottomUp ? Max(nextYPos, endOfImage) : Min(nextYPos, endOfImage);
       
  1064 	
       
  1065 	// Once the first block has been processed, iYInc is set to block height
       
  1066 	iYInc = iDrawBottomUp ? -iBlockSize.iHeight + ySkip : iBlockSize.iHeight - ySkip;
       
  1067 				
       
  1068 	// Skip unnecessary pixels (for cropping, or padding when rotated)
       
  1069 	indexBufferPtr += iPixelPadding;
       
  1070 	
       
  1071 	TPoint pos(iPos);
       
  1072 	iUtil.Begin();
       
  1073 	for(;iDrawBottomUp ? pos.iY > endPosition : pos.iY < endPosition; iDrawBottomUp ? pos.iY-- : pos.iY++)
       
  1074 		{
       
  1075 		iUtil.SetPos(pos);
       
  1076 		iUtil.SetPixels(indexBufferPtr, minWidth);
       
  1077 		indexBufferPtr += iBlockSize.iWidth; // next line in block
       
  1078 		}
       
  1079 	iUtil.End();
       
  1080 
       
  1081 	iPos.iX += iBlockSize.iWidth;
       
  1082 	
       
  1083 	if (iPos.iX >= imageWidth)
       
  1084 		{
       
  1085 		return NewLine();
       
  1086 		}
       
  1087 
       
  1088 	return EFalse;
       
  1089 	}
       
  1090 
       
  1091 /**
       
  1092  *
       
  1093  * @see CImageProcessor.
       
  1094  */
       
  1095 TBool CMonochromePixelWriter::FlushPixels()
       
  1096 	{
       
  1097 	TUint32* gray256BufferPtrLimit = iGray256BufferPtr;
       
  1098 	iGray256BufferPtr = iGray256Buffer;
       
  1099 
       
  1100 	if(iPos.iY < iImageRegion.iTl.iY || iPos.iY >= iImageRegion.iBr.iY)
       
  1101 		return ETrue;
       
  1102 
       
  1103 	iUtil.Begin();
       
  1104 
       
  1105 	TBool finished = EFalse;
       
  1106 	for (TUint32* gray256BufferPtr = iGray256Buffer; gray256BufferPtr < gray256BufferPtrLimit; )
       
  1107 		{
       
  1108 		TInt pixelsToSkip = Min(gray256BufferPtrLimit - gray256BufferPtr,iPixelsToSkip);
       
  1109 		gray256BufferPtr += pixelsToSkip;
       
  1110 		iPixelsToSkip -= pixelsToSkip;
       
  1111 
       
  1112 		if(iPixelsToSkip)
       
  1113 			break;
       
  1114 
       
  1115 		TInt pixelsToFlush = Min(gray256BufferPtrLimit - gray256BufferPtr,iImageRegion.iBr.iX - iPos.iX);
       
  1116 
       
  1117 		if(!pixelsToFlush)
       
  1118 			break;
       
  1119 
       
  1120 		SetPixelBufferIndex(gray256BufferPtr,pixelsToFlush);
       
  1121 		gray256BufferPtr += pixelsToFlush;
       
  1122 
       
  1123 		TBool fillDown = iYInc > 0;
       
  1124 		TPoint pos(iPos);
       
  1125 		TInt posYLimit;
       
  1126 		if(fillDown)
       
  1127 			posYLimit = Min(pos.iY + iLineRepeat + 1 ,iImageRegion.iBr.iY);
       
  1128 		else
       
  1129 			posYLimit = Max(pos.iY - iLineRepeat - 1 ,iImageRegion.iTl.iY-1);
       
  1130 
       
  1131 		for(;fillDown ? pos.iY < posYLimit : pos.iY > posYLimit; fillDown ? pos.iY++ : pos.iY--)
       
  1132 			{
       
  1133 			if(!iUtil.SetPos(pos-iImageRegion.iTl))
       
  1134 				{
       
  1135 				iUtil.End();
       
  1136 				return ETrue;
       
  1137 				}
       
  1138 			iUtil.SetPixels(iIndexBuffer,pixelsToFlush);
       
  1139 			}
       
  1140 
       
  1141 		iPos.iX += pixelsToFlush;
       
  1142 		if (iPos.iX >= iImageRegion.iBr.iX)
       
  1143 			{
       
  1144 			finished = NewLine();
       
  1145 			if(finished)
       
  1146 				break;
       
  1147 			}
       
  1148 		}
       
  1149 
       
  1150 	iUtil.End();
       
  1151 
       
  1152 	return finished;
       
  1153 	}
       
  1154 
       
  1155 /**
       
  1156  *
       
  1157  * @see CImageProcessor.
       
  1158  */
       
  1159 TBool CMonochromePixelWriter::SetPos(const TPoint& aPosition)
       
  1160 	{
       
  1161 	if(iImageRegion.Contains(aPosition))
       
  1162 		{
       
  1163 		FlushPixels();
       
  1164 		iPixelsToSkip = 0;
       
  1165 		iPos = aPosition;
       
  1166 		return ETrue;
       
  1167 		}
       
  1168 
       
  1169 	return EFalse;
       
  1170 	}
       
  1171 
       
  1172 void CMonochromePixelWriter::Reset()
       
  1173 	{
       
  1174 	delete iColorConv;
       
  1175 	iColorConv = NULL;
       
  1176 
       
  1177 	delete[] iGray256Buffer;
       
  1178 	iGray256Buffer = NULL;
       
  1179 
       
  1180 	delete[] iIndexBuffer;
       
  1181 	iIndexBuffer = NULL;
       
  1182 
       
  1183 	iPos.SetXY(0,0);
       
  1184 	iPixelsToSkip = 0;
       
  1185 	iImageRegion.SetRect(0,0,0,0);
       
  1186 	iBlockSize.SetSize(0,0);
       
  1187 	
       
  1188 	iDrawBottomUp = EFalse;
       
  1189 	}
       
  1190 
       
  1191 void CMonochromePixelWriter::DoPrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize* aBlockSize)
       
  1192 	{
       
  1193 	if( (aImageRect.iTl.iX<0) || (aImageRect.iTl.iY<0) || (aImageRect.Size().iWidth>aBitmap.SizeInPixels().iWidth) || (aImageRect.Size().iHeight>aBitmap.SizeInPixels().iHeight) )
       
  1194 		{
       
  1195 		User::Leave(KErrArgument);
       
  1196 		}
       
  1197 
       
  1198 	Reset();
       
  1199 
       
  1200 	iImageRegion = aImageRect;
       
  1201 
       
  1202 	iColorConv = TColorConvertor::NewL(aBitmap.DisplayMode());
       
  1203 	iUtil.SetBitmapL(&aBitmap);
       
  1204 
       
  1205 	if (aBlockSize)
       
  1206 		{
       
  1207 		if (aBlockSize->iWidth <= 0 || aBlockSize->iHeight <= 0)
       
  1208 			{
       
  1209 			User::Leave(KErrArgument);
       
  1210 			}
       
  1211 
       
  1212 		iBlockSize = *aBlockSize;
       
  1213 		iBlockArea = iBlockSize.iWidth * iBlockSize.iHeight;
       
  1214 		
       
  1215 		ASSERT(iIndexBuffer == NULL);
       
  1216 		iIndexBuffer = new(ELeave) TUint32[iBlockArea];
       
  1217 
       
  1218 		iIndexBufferPtrLimit = iIndexBuffer + iBlockArea;
       
  1219 		CreateBlockBufferL(iBlockArea);
       
  1220 		
       
  1221 		switch(iOperation)
       
  1222 			{
       
  1223 			case EDecodeRotate180:
       
  1224 			case EDecodeRotate270:
       
  1225 			case EDecodeHorizontalFlip:
       
  1226 			case EDecodeVerticalFlipRotate90:
       
  1227 				iDrawBottomUp = ETrue;
       
  1228 				break;
       
  1229 			default:
       
  1230 				iDrawBottomUp = EFalse;		
       
  1231 			}
       
  1232 		
       
  1233 		iYInc = iDrawBottomUp ? -iBlockSize.iHeight : iBlockSize.iHeight;
       
  1234 		iStartPosition.SetXY(iImageRegion.iTl.iX, iDrawBottomUp ? iImageRegion.iBr.iY - 1 : 0);
       
  1235 		iEndPosition.SetXY(iImageRegion.iBr.iX, iDrawBottomUp ?
       
  1236 							iImageRegion.iTl.iY - 1 : iImageRegion.iBr.iY);
       
  1237 		iPos = iStartPosition;
       
  1238 		}
       
  1239 	else
       
  1240 		{
       
  1241 		iPos = iImageRegion.iTl;
       
  1242 		iStartPosition = iPos;
       
  1243 		iEndPosition = aImageRect.iBr;
       
  1244 
       
  1245 		ASSERT(iGray256Buffer == NULL);
       
  1246 		iGray256Buffer = new(ELeave) TUint32[KPixelWriterBufferSize];
       
  1247 
       
  1248 		iGray256BufferPtr = iGray256Buffer;
       
  1249 		iGray256BufferPtrLimit = iGray256Buffer + KPixelWriterBufferSize;
       
  1250 
       
  1251 		ASSERT(iIndexBuffer == NULL);
       
  1252 		iIndexBuffer = new(ELeave) TUint32[KPixelWriterBufferSize];
       
  1253 
       
  1254 		iIndexBufferPtrLimit = iIndexBuffer + KPixelWriterBufferSize;
       
  1255 		}
       
  1256 	
       
  1257 	for(TInt i=0; i<256; i++)
       
  1258 		{
       
  1259 		iIndexLookup[i] = iColorConv->ColorIndex(TRgb(i,i,i));	
       
  1260 		}
       
  1261 	}
       
  1262 
       
  1263 TBool CMonochromePixelWriter::NewLine()
       
  1264 	{
       
  1265 	iPos.iX = iStartPosition.iX;
       
  1266 	iPos.iY += iYInc;
       
  1267 
       
  1268 	if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
  1269 		{
       
  1270 		return ETrue;
       
  1271 		}
       
  1272 	
       
  1273 	iPixelsToSkip = iPixelPadding;
       
  1274 	return EFalse;
       
  1275 	}
       
  1276 
       
  1277 void CMonochromePixelWriter::SetPixelBlockIndex(TUint32* aGray256Buffer)
       
  1278 	{
       
  1279 	CMonochromePixelWriter::SetPixelBufferIndex(aGray256Buffer,iBlockArea);
       
  1280 	}
       
  1281 
       
  1282 void CMonochromePixelWriter::SetPixelBufferIndex(TUint32* aGray256Buffer,TInt aCount)
       
  1283 	{
       
  1284 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1285 	TUint32* indexBufferPtrLimit = indexBufferPtr+aCount;
       
  1286 	TUint32* indexLookup = iIndexLookup;
       
  1287 
       
  1288 	if(aCount&1)
       
  1289 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1290 	if(aCount&2)
       
  1291 		{
       
  1292 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1293 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1294 		}
       
  1295 	while (indexBufferPtr < indexBufferPtrLimit)
       
  1296 		{
       
  1297 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1298 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1299 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1300 		*indexBufferPtr++ = indexLookup[*aGray256Buffer++];
       
  1301 		}
       
  1302 	}
       
  1303 
       
  1304 //
       
  1305 // CErrorDiffuser::TColorError
       
  1306 //
       
  1307 
       
  1308 inline CErrorDiffuser::TColorError::TColorError():
       
  1309 	iRedError(0),
       
  1310 	iGreenError(0),
       
  1311 	iBlueError(0)
       
  1312 	{}
       
  1313 
       
  1314 inline CErrorDiffuser::TColorError::TColorError(TInt aRedError,TInt aGreenError,TInt aBlueError):
       
  1315 	iRedError(aRedError),
       
  1316 	iGreenError(aGreenError),
       
  1317 	iBlueError(aBlueError)
       
  1318 	{}
       
  1319 
       
  1320 inline void CErrorDiffuser::TColorError::AdjustColor(TRgb& aColor) const
       
  1321 	{
       
  1322 	TInt red = ColorCcomponent::ClampColorComponent((iRedError >> 4) + aColor.Red());
       
  1323 	TInt green = ColorCcomponent::ClampColorComponent((iGreenError >> 4) + aColor.Green());
       
  1324 	TInt blue = ColorCcomponent::ClampColorComponent((iBlueError >> 4) + aColor.Blue());
       
  1325 	aColor = TRgb(red,green,blue);
       
  1326 	}
       
  1327 
       
  1328 inline void CErrorDiffuser::TColorError::SetError(TRgb aIdealColor,TRgb aActualColor)
       
  1329 	{
       
  1330 	iRedError = aIdealColor.Red() - aActualColor.Red();
       
  1331 	iGreenError = aIdealColor.Green() - aActualColor.Green();
       
  1332 	iBlueError = aIdealColor.Blue() - aActualColor.Blue();
       
  1333 	}
       
  1334 
       
  1335 inline CErrorDiffuser::TColorError CErrorDiffuser::TColorError::operator+(const TColorError& aColorError) const
       
  1336 	{
       
  1337 	TInt redError = iRedError + aColorError.iRedError;
       
  1338 	TInt greenError = iGreenError + aColorError.iGreenError;
       
  1339 	TInt blueError = iBlueError + aColorError.iBlueError;
       
  1340 	return TColorError(redError,greenError,blueError);
       
  1341 	}
       
  1342 
       
  1343 inline CErrorDiffuser::TColorError CErrorDiffuser::TColorError::operator-(const TColorError& aColorError) const
       
  1344 	{
       
  1345 	TInt redError = iRedError - aColorError.iRedError;
       
  1346 	TInt greenError = iGreenError - aColorError.iGreenError;
       
  1347 	TInt blueError = iBlueError - aColorError.iBlueError;
       
  1348 	return TColorError(redError,greenError,blueError);
       
  1349 	}
       
  1350 
       
  1351 inline CErrorDiffuser::TColorError CErrorDiffuser::TColorError::operator<<(TInt aShift) const
       
  1352 	{
       
  1353 	TInt redError = iRedError << aShift;
       
  1354 	TInt greenError = iGreenError << aShift;
       
  1355 	TInt blueError = iBlueError << aShift;
       
  1356 	return TColorError(redError,greenError,blueError);
       
  1357 	}
       
  1358 
       
  1359 inline CErrorDiffuser::TColorError& CErrorDiffuser::TColorError::operator+=(const TColorError& aColorError)
       
  1360 	{
       
  1361 	iRedError += aColorError.iRedError;
       
  1362 	iGreenError += aColorError.iGreenError;
       
  1363 	iBlueError += aColorError.iBlueError;
       
  1364 	return *this;
       
  1365 	}
       
  1366 
       
  1367 CErrorDiffuser::CErrorDiffuser()
       
  1368 	{
       
  1369 	}
       
  1370 
       
  1371 CErrorDiffuser::~CErrorDiffuser()
       
  1372 	{
       
  1373 	Reset();
       
  1374 	}
       
  1375 
       
  1376 void CErrorDiffuser::DoPrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize* aBlockSize)
       
  1377 	{
       
  1378 	CPixelWriter::DoPrepareL(aBitmap,aImageRect,aBlockSize);
       
  1379 
       
  1380 	TInt scanlineErrorBufferLength = iImageRegion.iBr.iX+2;
       
  1381 
       
  1382 	if (iBlockArea > 0)
       
  1383 		{
       
  1384 		ASSERT(iEdgeErrorBuffer == NULL);
       
  1385 		iEdgeErrorBuffer = new(ELeave) TColorError[iBlockSize.iHeight];
       
  1386 
       
  1387 		scanlineErrorBufferLength += iBlockSize.iWidth;
       
  1388 		}
       
  1389 
       
  1390 	ASSERT(iScanlineErrorBuffer == NULL);
       
  1391 	iScanlineErrorBuffer = new(ELeave) TColorError[scanlineErrorBufferLength];
       
  1392 
       
  1393 	if (iDisplayMode == EColor64K) 
       
  1394 		{
       
  1395 			ASSERT(iRedErrorLookupTable == NULL);
       
  1396 			iRedErrorLookupTable = new(ELeave) TInt8[256];
       
  1397 			ASSERT(iGreenErrorLookupTable == NULL);
       
  1398 			iGreenErrorLookupTable = new(ELeave) TInt8[256];
       
  1399 			
       
  1400 			for (TInt i=0;i<256;i++) 
       
  1401 				{
       
  1402 					TInt tmp = i & 0xf8;
       
  1403 					iRedErrorLookupTable[i] = i - (tmp | (tmp >> 5));
       
  1404 					tmp = i & 0xfc;
       
  1405 					iGreenErrorLookupTable[i] = i - (tmp | (tmp >> 6));
       
  1406 				}
       
  1407 		}
       
  1408 	}
       
  1409 
       
  1410 void CErrorDiffuser::SetPixelBufferIndex(TRgb* aColorBuffer,TInt aCount)
       
  1411 	{
       
  1412 	// use optimized function for EColor64K mode
       
  1413 	if (iDisplayMode == EColor64K) 
       
  1414 		{
       
  1415 		SetPixelBufferColor64KIndex(aColorBuffer, aCount);
       
  1416 		return;
       
  1417 		}
       
  1418 
       
  1419 	TInt clearX = iPos.iX;
       
  1420 
       
  1421 	TInt yDiff = iPos.iY - iLastPos.iY;
       
  1422 	if(yDiff != 0)									// On a new line?
       
  1423 		{
       
  1424 		new(&iNextError) TColorError;
       
  1425 		clearX = iImageRegion.iBr.iX;				// To clear to end of line
       
  1426 
       
  1427 		if(yDiff == -1 || yDiff == 1)				// Now on ajacent line?
       
  1428 			{
       
  1429 			clearX -= iLastPos.iX;					// Clear end of previous line
       
  1430 			if(clearX)
       
  1431 				{
       
  1432 				Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TColorError));
       
  1433 				}
       
  1434 			clearX = iPos.iX;						// To clear up to current position
       
  1435 			}
       
  1436 		iLastPos.iX = iImageRegion.iTl.iX;			// Start of this line
       
  1437 		}
       
  1438 
       
  1439 	clearX -= iLastPos.iX;
       
  1440 	if(clearX > 0)									// Treat any skipped pixels as if they produced no error
       
  1441 		{
       
  1442 		new(&iNextError) TColorError;
       
  1443 		Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TColorError));
       
  1444 		}
       
  1445 
       
  1446 	iLastPos.iY = iPos.iY;
       
  1447 	iLastPos.iX = iPos.iX+aCount;
       
  1448 
       
  1449 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1450 	TUint32* indexBufferPtrLimit = indexBufferPtr+aCount;
       
  1451 	TColorError* scanlineErrorBufferPtr = iScanlineErrorBuffer + iPos.iX;
       
  1452 	TColorError error;
       
  1453 	TRgb color;
       
  1454 
       
  1455 	while(indexBufferPtr<indexBufferPtrLimit)
       
  1456 		{
       
  1457 		color = *aColorBuffer++;
       
  1458 
       
  1459 		iNextError.AdjustColor(color);
       
  1460 		TUint32 index = iColorConv->ColorIndex(color);
       
  1461 		*indexBufferPtr++ = index;
       
  1462 
       
  1463 		error.SetError(color, iColorConv->Color(index));
       
  1464 
       
  1465 		iNextError = (error << 3) - error; // Set right error for this pixel
       
  1466 
       
  1467 		*scanlineErrorBufferPtr++ += error + (error << 1); // Set left-down error for this pixel
       
  1468 
       
  1469 		*scanlineErrorBufferPtr += error + (error << 2); // Set down error for this pixel
       
  1470 
       
  1471 		iNextError += *(scanlineErrorBufferPtr+1);
       
  1472 
       
  1473 		*(scanlineErrorBufferPtr+1) = error; // Set right-down error for this pixel
       
  1474 		}
       
  1475 	}
       
  1476 
       
  1477 // faster function (see listing) then Bitmap Util ClampColorComponent
       
  1478 inline TInt CErrorDiffuser::ClipColorComponent(TInt value)
       
  1479     {
       
  1480     if (TUint(value) > 0xFF)
       
  1481         {
       
  1482         value = value < 0 ? 0 : 0xFF;
       
  1483         }
       
  1484     return value;
       
  1485     }
       
  1486 
       
  1487 void CErrorDiffuser::SetPixelBufferColor64KIndex(TRgb* aColorBuffer,TInt aCount)
       
  1488 	{
       
  1489 	TInt clearX = iPos.iX;
       
  1490 
       
  1491 	TInt yDiff = iPos.iY - iLastPos.iY;
       
  1492 	if(yDiff != 0)									// On a new line?
       
  1493 		{
       
  1494 		iNextRedError = 0;
       
  1495 		iNextGreenError = 0;
       
  1496 		iNextBlueError = 0;
       
  1497 		clearX = iImageRegion.iBr.iX;				// To clear to end of line
       
  1498 
       
  1499 		if(yDiff == -1 || yDiff == 1)				// Now on ajacent line?
       
  1500 			{
       
  1501 			clearX -= iLastPos.iX;					// Clear end of previous line
       
  1502 			if(clearX > 0) 
       
  1503 				{
       
  1504 				Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TColorError));
       
  1505 				}
       
  1506 			clearX = iPos.iX;						// To clear up to current position
       
  1507 			}
       
  1508 		iLastPos.iX = iImageRegion.iTl.iX;			// Start of this line
       
  1509 		}
       
  1510 
       
  1511 	clearX -= iLastPos.iX;
       
  1512 	if(clearX > 0)									// Treat any skipped pixels as if they produced no error
       
  1513 		{
       
  1514 		iNextRedError = 0;
       
  1515 		iNextGreenError = 0;
       
  1516 		iNextBlueError = 0;
       
  1517 		Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TColorError));
       
  1518 		}
       
  1519 
       
  1520 	iLastPos.iY = iPos.iY;
       
  1521 	iLastPos.iX = iPos.iX+aCount;
       
  1522 
       
  1523 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1524 	TUint32* indexBufferPtrLimit = indexBufferPtr+aCount;
       
  1525 
       
  1526 	TColorError* scanlineErrorBufferPtr = iScanlineErrorBuffer + iPos.iX;
       
  1527 
       
  1528 	TInt redError = iNextRedError;
       
  1529 	TInt greenError = iNextGreenError;
       
  1530 	TInt blueError = iNextBlueError;
       
  1531 	
       
  1532 	while(indexBufferPtr<indexBufferPtrLimit)
       
  1533 		{
       
  1534 		// red			
       
  1535 		register TInt red = aColorBuffer->Red();
       
  1536 		red = ClipColorComponent(red + (redError >> 4));
       
  1537 
       
  1538 		register TInt error = iRedErrorLookupTable[red];
       
  1539 		
       
  1540 		// Set right error for red component
       
  1541 		scanlineErrorBufferPtr->iRedError += error + (error << 1); // Set left-down error for this pixel
       
  1542 		(scanlineErrorBufferPtr+1)->iRedError += error + (error << 2); // Set down error for this pixel
       
  1543 		redError = (scanlineErrorBufferPtr+2)->iRedError + (error << 3) - error; // Set right error for this pixel
       
  1544 		(scanlineErrorBufferPtr+2)->iRedError = error; // Set right-down error for this pixel
       
  1545 
       
  1546 		// green			
       
  1547 		register TInt green = aColorBuffer->Green();
       
  1548 			
       
  1549 		green = ClipColorComponent(green + (greenError >> 4));
       
  1550 
       
  1551 		error = iGreenErrorLookupTable[green];
       
  1552 		
       
  1553 		// Set right error for green component
       
  1554 		scanlineErrorBufferPtr->iGreenError += error + (error << 1); // Set left-down error for this pixel
       
  1555 		(scanlineErrorBufferPtr+1)->iGreenError += error + (error << 2); // Set down error for this pixel
       
  1556 		greenError = (scanlineErrorBufferPtr+2)->iGreenError + (error << 3) - error; // Set right error for this pixel
       
  1557 		(scanlineErrorBufferPtr+2)->iGreenError = error; // Set right-down error for this pixel
       
  1558 
       
  1559 		// blue			
       
  1560 		register TInt blue = aColorBuffer->Blue();
       
  1561 			
       
  1562 		blue = ClipColorComponent(blue + (blueError >> 4));
       
  1563 		
       
  1564 		*indexBufferPtr++ = ((red & 0xf8) << 8) | ((green & 0xfc) << 3) | ((blue & 0xf8) >> 3);
       
  1565 		
       
  1566 		error = iRedErrorLookupTable[blue];// use the same lookup table for blue color
       
  1567 
       
  1568 		// Set right error for blue component
       
  1569 		scanlineErrorBufferPtr->iBlueError += error + (error << 1); // Set left-down error for this pixel
       
  1570 		(scanlineErrorBufferPtr+1)->iBlueError += error + (error << 2); // Set down error for this pixel
       
  1571 		blueError = (scanlineErrorBufferPtr+2)->iBlueError + (error << 3) - error; // Set right error for this pixel
       
  1572 		(scanlineErrorBufferPtr+2)->iBlueError = error; // Set right-down error for this pixel
       
  1573 
       
  1574 		scanlineErrorBufferPtr++;
       
  1575 		aColorBuffer++;
       
  1576 		}
       
  1577 
       
  1578 		iNextRedError = redError;
       
  1579 		iNextGreenError = greenError;
       
  1580 		iNextBlueError = blueError;
       
  1581 
       
  1582 
       
  1583 	}
       
  1584 
       
  1585 void CErrorDiffuser::SetPixelBlockIndex(TRgb* aColorBuffer)
       
  1586 	{
       
  1587 	if(iPos.iY!=iLastPos.iY)
       
  1588 		{
       
  1589 		Mem::FillZ(iEdgeErrorBuffer,sizeof(TColorError) * iBlockSize.iHeight);
       
  1590 		}
       
  1591 
       
  1592 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1593 
       
  1594 	TColorError error;
       
  1595 	TColorError* edgeErrorBuffer = iEdgeErrorBuffer;
       
  1596 
       
  1597 	for (TInt row = 0; row < iBlockSize.iHeight; row++)
       
  1598 		{
       
  1599 		TColorError* errorValue = iScanlineErrorBuffer + iPos.iX;
       
  1600 		TColorError nextError = *edgeErrorBuffer + *errorValue;
       
  1601 		*edgeErrorBuffer = error;
       
  1602 
       
  1603 		for (TInt col = 0; col < iBlockSize.iWidth; col++)
       
  1604 			{
       
  1605 			TRgb bufferColor = *aColorBuffer++;
       
  1606 			nextError.AdjustColor(bufferColor);
       
  1607 
       
  1608 			TUint32 index = iColorConv->ColorIndex(bufferColor);
       
  1609 			*indexBufferPtr++ = index;
       
  1610 
       
  1611 			error.SetError(bufferColor,iColorConv->Color(index));
       
  1612 
       
  1613 			if (col > 0)
       
  1614 				*(errorValue - 1) += error + (error << 1); // Set left-down error for this pixel
       
  1615 			else
       
  1616 				*errorValue = error + (error << 1);
       
  1617 
       
  1618 			*errorValue += error + (error << 2); // Set down error for this pixel
       
  1619 			errorValue++;
       
  1620 
       
  1621 			nextError = (error << 3) - error; // Set right error for this pixel
       
  1622 
       
  1623 			if (col < iBlockSize.iWidth)
       
  1624 				{
       
  1625 				nextError += *errorValue;
       
  1626 				*errorValue = error; // Set right-down error for this pixel
       
  1627 				}
       
  1628 
       
  1629 			}
       
  1630 
       
  1631 		*edgeErrorBuffer++ += nextError;
       
  1632 		}
       
  1633 
       
  1634 	iLastPos.iY = iPos.iY;
       
  1635 	iLastPos.iX = iPos.iX+iBlockSize.iWidth;
       
  1636 	}
       
  1637 
       
  1638 void CErrorDiffuser::Reset()
       
  1639 	{
       
  1640 	CPixelWriter::Reset();
       
  1641 
       
  1642 	delete[] iScanlineErrorBuffer;
       
  1643 	iScanlineErrorBuffer = NULL;
       
  1644 
       
  1645 	delete[] iEdgeErrorBuffer;
       
  1646 	iEdgeErrorBuffer = NULL;
       
  1647 	
       
  1648 	delete iRedErrorLookupTable;
       
  1649 	iRedErrorLookupTable = NULL;
       
  1650 	
       
  1651 	delete iGreenErrorLookupTable;
       
  1652 	iGreenErrorLookupTable = NULL;
       
  1653 
       
  1654 	}
       
  1655 
       
  1656 //
       
  1657 // CMonochromeErrorDiffuser
       
  1658 //
       
  1659 
       
  1660 
       
  1661 /**
       
  1662  *
       
  1663  * Static factory function to create CMonochromeErrorDiffuser objects.
       
  1664  *
       
  1665  * @return  Pointer to a fully constructed CMonochromeErrorDiffuser object. 
       
  1666  */
       
  1667 CMonochromeErrorDiffuser* CMonochromeErrorDiffuser::NewL()
       
  1668 	{
       
  1669 	return new(ELeave) CMonochromeErrorDiffuser;
       
  1670 	}
       
  1671 
       
  1672 CMonochromeErrorDiffuser::CMonochromeErrorDiffuser()
       
  1673 	{}
       
  1674 
       
  1675 CMonochromeErrorDiffuser::~CMonochromeErrorDiffuser()
       
  1676 	{
       
  1677 	Reset();
       
  1678 	}
       
  1679 
       
  1680 void CMonochromeErrorDiffuser::DoPrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize* aBlockSize)
       
  1681 	{
       
  1682 	CMonochromePixelWriter::DoPrepareL(aBitmap,aImageRect,aBlockSize);
       
  1683 
       
  1684 	TInt scanlineErrorBufferLength = iImageRegion.iBr.iX+2;
       
  1685 
       
  1686 	if (iBlockArea > 0)
       
  1687 		{
       
  1688 		ASSERT(iEdgeErrorBuffer == NULL);
       
  1689 		iEdgeErrorBuffer = new(ELeave) TInt[iBlockSize.iHeight];
       
  1690 
       
  1691 		Mem::FillZ(iEdgeErrorBuffer,sizeof(TInt) * iBlockSize.iHeight);
       
  1692 		scanlineErrorBufferLength += iBlockSize.iWidth;
       
  1693 		}
       
  1694 
       
  1695 	ASSERT(iScanlineErrorBuffer == NULL);
       
  1696 	iScanlineErrorBuffer = new(ELeave) TInt[scanlineErrorBufferLength];
       
  1697 
       
  1698 	Mem::FillZ(iScanlineErrorBuffer,sizeof(TInt) * scanlineErrorBufferLength);
       
  1699 	}
       
  1700 
       
  1701 void CMonochromeErrorDiffuser::SetPixelBufferIndex(TUint32* aGray256Buffer,TInt aCount)
       
  1702 	{
       
  1703 	TInt clearX = iPos.iX;
       
  1704 
       
  1705 	TInt yDiff = iPos.iY - iLastPos.iY;
       
  1706 	if(yDiff != 0)									// On a new line?
       
  1707 		{
       
  1708 		iNextError = 0;
       
  1709 		clearX = iImageRegion.iBr.iX;				// To clear to end of line
       
  1710 
       
  1711 		if(yDiff == -1 || yDiff == 1)				// Now on ajacent line?
       
  1712 			{
       
  1713 			clearX -= iLastPos.iX;					// Clear end of previous line
       
  1714 			if(clearX)
       
  1715 				Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TInt));
       
  1716 			clearX = iPos.iX;						// To clear up to current position
       
  1717 			}
       
  1718 		iLastPos.iX = iImageRegion.iTl.iX;			// Start of this line
       
  1719 		}
       
  1720 
       
  1721 	clearX -= iLastPos.iX;
       
  1722 	if(clearX > 0)									// Treat any skipped pixels as if they produced no error
       
  1723 		{
       
  1724 		iNextError = 0;
       
  1725 		Mem::FillZ(iScanlineErrorBuffer + iLastPos.iX + 2, clearX * sizeof(TInt));
       
  1726 		}
       
  1727 
       
  1728 	iLastPos.iY = iPos.iY;
       
  1729 	iLastPos.iX = iPos.iX+aCount;
       
  1730 
       
  1731 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1732 	TUint32* indexBufferPtrLimit = indexBufferPtr+aCount;
       
  1733 
       
  1734 	TInt* scanlineErrorBufferPtr = iScanlineErrorBuffer + iPos.iX;
       
  1735 	TInt nextError = iNextError;
       
  1736 
       
  1737 	while(indexBufferPtr<indexBufferPtrLimit)
       
  1738 		{
       
  1739 		TInt gray256 = *aGray256Buffer++;
       
  1740 
       
  1741 		TInt error = gray256 + (nextError >> 4);
       
  1742 		TUint32 index = iIndexLookup[ColorCcomponent::ClampColorComponent(error)];
       
  1743 		*indexBufferPtr++ = index;
       
  1744 
       
  1745 		error -= TColorConvertor::RgbToMonochrome(iColorConv->Color(index));
       
  1746 
       
  1747 		nextError = (error << 3) - error; // Set right error for this pixel
       
  1748 
       
  1749 		*scanlineErrorBufferPtr++ += error + (error << 1); // Set left-down error for this pixel
       
  1750 
       
  1751 		*scanlineErrorBufferPtr += error + (error << 2); // Set down error for this pixel
       
  1752 
       
  1753 		nextError += *(scanlineErrorBufferPtr+1);
       
  1754 
       
  1755 		*(scanlineErrorBufferPtr+1) = error; // Set right-down error for this pixel
       
  1756 		}
       
  1757 
       
  1758 	iNextError = nextError;
       
  1759 	}
       
  1760 
       
  1761 void CMonochromeErrorDiffuser::SetPixelBlockIndex(TUint32* aGray256Buffer)
       
  1762 	{
       
  1763 	if(iPos.iY!=iLastPos.iY)
       
  1764 		{
       
  1765 		Mem::FillZ(iEdgeErrorBuffer,sizeof(TInt) * iBlockSize.iHeight);
       
  1766 		}
       
  1767 
       
  1768 	TUint32* indexBufferPtr = iIndexBuffer;
       
  1769 
       
  1770 	TInt error = 0;
       
  1771 	TInt* edgeErrorBuffer = iEdgeErrorBuffer;
       
  1772 
       
  1773 	for (TInt row = 0; row < iBlockSize.iHeight; row++)
       
  1774 		{
       
  1775 		TInt* errorValue = iScanlineErrorBuffer + iPos.iX;
       
  1776 		TInt nextError = *edgeErrorBuffer + *errorValue;
       
  1777 		*edgeErrorBuffer = error;
       
  1778 
       
  1779 		for (TInt col = 0; col < iBlockSize.iWidth; col++)
       
  1780 			{
       
  1781 			TInt gray256 = *aGray256Buffer++;
       
  1782 
       
  1783 			error = gray256 + (nextError >> 4); // Same as /16
       
  1784 			
       
  1785 			TUint32 index = iIndexLookup[ColorCcomponent::ClampColorComponent(error)];
       
  1786 			*indexBufferPtr++ = index;
       
  1787 
       
  1788 			error -= TColorConvertor::RgbToMonochrome(iColorConv->Color(index));
       
  1789 
       
  1790 			if (col > 0)
       
  1791 				*(errorValue - 1) += error + (error << 1); // Set left-down error for this pixel
       
  1792 			else
       
  1793 				*errorValue = error + (error << 1);
       
  1794 
       
  1795 			*errorValue += error + (error << 2); // Set down error for this pixel
       
  1796 			errorValue++;
       
  1797 
       
  1798 			nextError = (error << 3) - error; // Set right error for this pixel
       
  1799 
       
  1800 			if (col < iBlockSize.iWidth)
       
  1801 				{
       
  1802 				nextError += *errorValue;
       
  1803 				*errorValue = error; // Set right-down error for this pixel
       
  1804 				}
       
  1805 			}
       
  1806 
       
  1807 		*edgeErrorBuffer++ += nextError;
       
  1808 		}
       
  1809 
       
  1810 	iLastPos.iY = iPos.iY;
       
  1811 	iLastPos.iX = iPos.iX+iBlockSize.iWidth;
       
  1812 	}
       
  1813 
       
  1814 void CMonochromeErrorDiffuser::Reset()
       
  1815 	{
       
  1816 	CMonochromePixelWriter::Reset();
       
  1817 
       
  1818 	delete[] iScanlineErrorBuffer;
       
  1819 	iScanlineErrorBuffer = NULL;
       
  1820 
       
  1821 	delete[] iEdgeErrorBuffer;
       
  1822 	iEdgeErrorBuffer = NULL;
       
  1823 	}
       
  1824 
       
  1825 //
       
  1826 // CThumbnailProcessor
       
  1827 //
       
  1828 
       
  1829 /**
       
  1830  *
       
  1831  * Static factory function to create CThumbnailProcessor objects.
       
  1832  *
       
  1833  * @param	"aImageProc"
       
  1834  *          A pointer to an externally constructed CImageProcessorExtension object.
       
  1835  *          This will be deleted when the CThumbnailProcessor object is deleted.
       
  1836  * @param	"aReductionFactor"
       
  1837  *          The reduction factor to use.
       
  1838  * @return  Pointer to a fully constructed CThumbnailProcessor object. 
       
  1839  */
       
  1840 CThumbnailProcessor* CThumbnailProcessor::NewL(CImageProcessorExtension* aImageProc,TInt aReductionFactor)
       
  1841 	{
       
  1842 	return new(ELeave) CThumbnailProcessor(aImageProc,aReductionFactor);
       
  1843 	}
       
  1844 
       
  1845 CThumbnailProcessor::CThumbnailProcessor(CImageProcessorExtension* aImageProc,TInt aReductionFactor):
       
  1846 	iImageProc(aImageProc),
       
  1847 	iYInc(1),
       
  1848 	iReductionFactor(aReductionFactor)
       
  1849 		{}
       
  1850 
       
  1851 CThumbnailProcessor::~CThumbnailProcessor()
       
  1852 	{
       
  1853 	delete iImageProc;
       
  1854 	delete[] iReducedPixelBuffer;
       
  1855 	delete[] iReducedSumBuffer;
       
  1856 	}
       
  1857 
       
  1858 void CThumbnailProcessor::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect)
       
  1859 	{
       
  1860 	PrepareCommonL(aImageRect);
       
  1861 	iYInc = 1;
       
  1862 
       
  1863 	TInt bufferSize = (iImageRegion.iBr.iX + (1<<iReductionFactor) -1 ) >> iReductionFactor;
       
  1864 
       
  1865 	ASSERT(iReducedSumBuffer == NULL);
       
  1866 	iReducedSumBuffer = new(ELeave) TColorSum[bufferSize];
       
  1867 	Mem::FillZ(iReducedSumBuffer,bufferSize * sizeof(TColorSum));
       
  1868 
       
  1869 	iImageProc->PrepareL(aBitmap,iReducedImageRegion);
       
  1870 
       
  1871 	ASSERT(iReducedPixelBuffer == NULL);
       
  1872 	iReducedPixelBuffer = new(ELeave) TRgb[iReducedImageRegion.iBr.iX];
       
  1873 	}
       
  1874 
       
  1875 void CThumbnailProcessor::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize& aRgbBlockSize)
       
  1876 	{
       
  1877 	PrepareCommonL(aImageRect);
       
  1878 
       
  1879 	CreateBlockBufferL(aRgbBlockSize.iWidth*aRgbBlockSize.iHeight);
       
  1880 
       
  1881 	iOriginalBlockSize = aRgbBlockSize;
       
  1882 	iYInc = iDrawBottomUp ? -iOriginalBlockSize.iHeight : iOriginalBlockSize.iHeight;
       
  1883 
       
  1884 	iReducedBlockSize = aRgbBlockSize;
       
  1885 	iReducedBlockSize.iWidth >>= iReductionFactor;
       
  1886 	iReducedBlockSize.iHeight >>= iReductionFactor;
       
  1887 
       
  1888 	iImageProc->SetInitialScanlineSkipPadding(iNumberOfScanlinesToSkip >> iReductionFactor);
       
  1889 	iImageProc->SetPixelPadding(iPixelPadding >> iReductionFactor);
       
  1890 	iImageProc->PrepareL(aBitmap,iReducedImageRegion,iReducedBlockSize);
       
  1891 
       
  1892 	ASSERT(iReducedPixelBuffer == NULL);
       
  1893 	iReducedPixelBuffer = new(ELeave) TRgb[iReducedBlockSize.iWidth * iReducedBlockSize.iHeight];
       
  1894 	}
       
  1895 
       
  1896 void CThumbnailProcessor::PrepareCommonL(const TRect& aImageRect)
       
  1897 	{
       
  1898 	ASSERT(iReductionFactor > 0);
       
  1899 	iImageRegion = aImageRect;
       
  1900 
       
  1901 	TInt roundUp = (1<<iReductionFactor)-1;
       
  1902 	iReducedImageRegion.iTl.iX = aImageRect.iTl.iX >> iReductionFactor;
       
  1903 	iReducedImageRegion.iTl.iY = aImageRect.iTl.iY >> iReductionFactor;
       
  1904 	
       
  1905 	TSize size = aImageRect.Size();
       
  1906 	size.iWidth = (size.iWidth + roundUp) >> iReductionFactor;
       
  1907 	size.iHeight = (size.iHeight + roundUp) >> iReductionFactor;
       
  1908 	iReducedImageRegion.iBr = iReducedImageRegion.iTl + size;
       
  1909 
       
  1910 	switch(iOperation)
       
  1911 		{
       
  1912 		case EDecodeRotate180:
       
  1913 		case EDecodeRotate270:
       
  1914 		case EDecodeHorizontalFlip:
       
  1915 		case EDecodeVerticalFlipRotate90:
       
  1916 			iDrawBottomUp = ETrue;
       
  1917 			iImageProc->SetOperation(iOperation);
       
  1918 			break;
       
  1919 		default:
       
  1920 			iDrawBottomUp = EFalse;
       
  1921 		}
       
  1922 	iStartPosition.SetXY(iImageRegion.iTl.iX, iDrawBottomUp ? aImageRect.iBr.iY - 1 : 0);
       
  1923 	iEndPosition.SetXY(aImageRect.iBr.iX, iDrawBottomUp ? aImageRect.iTl.iY - 1 : aImageRect.iBr.iY);
       
  1924 	iPos = iStartPosition;
       
  1925 
       
  1926 	iPositionChanged = ETrue;
       
  1927 
       
  1928 	iEndOfLineX = iEndPosition.iX + iPixelPadding;
       
  1929 
       
  1930 	delete[] iReducedPixelBuffer;
       
  1931 	iReducedPixelBuffer = NULL;
       
  1932 
       
  1933 	delete[] iReducedSumBuffer;
       
  1934 	iReducedSumBuffer = NULL;
       
  1935 	}
       
  1936 
       
  1937 TBool CThumbnailProcessor::SetPixel(TRgb aColor)
       
  1938 	{
       
  1939 	TInt x = iPos.iX;
       
  1940 
       
  1941 	if (x < iImageRegion.iBr.iX)
       
  1942 		{
       
  1943 		TColorSum* sumPtr = iReducedSumBuffer + (x >> iReductionFactor);
       
  1944 		sumPtr->iRed += aColor.Red();
       
  1945 		sumPtr->iGreen += aColor.Green();
       
  1946 		sumPtr->iBlue += aColor.Blue();
       
  1947 		sumPtr->iCount++;
       
  1948 		}
       
  1949 
       
  1950 	x++;
       
  1951 	iPos.iX = x;
       
  1952 
       
  1953 	if (x == iEndOfLineX)
       
  1954 		return NewLine();
       
  1955 
       
  1956 	return EFalse;
       
  1957 	}
       
  1958 
       
  1959 TBool CThumbnailProcessor::NewLine()
       
  1960 	{
       
  1961 	TInt newY = iPos.iY + iYInc;
       
  1962 
       
  1963 	TBool finished = (newY < iStartPosition.iY || newY >= iEndPosition.iY);
       
  1964 	TBool outsideOfBuffer = ((newY ^ iPos.iY) >> iReductionFactor) != 0;
       
  1965 
       
  1966 	if(finished || outsideOfBuffer)
       
  1967 		{
       
  1968 		DoFlushPixels();
       
  1969 		}
       
  1970 
       
  1971 	iPos.iX = iStartPosition.iX;
       
  1972 	iPos.iY = newY;
       
  1973 
       
  1974 	if(iPositionChanged && outsideOfBuffer)
       
  1975 		{
       
  1976 		iImageProc->SetPos(TPoint(iPos.iX >> iReductionFactor,iPos.iY >> iReductionFactor));
       
  1977 		iPositionChanged = EFalse;
       
  1978 		}
       
  1979 
       
  1980 	return finished;
       
  1981 	}
       
  1982 
       
  1983 TBool CThumbnailProcessor::SetPixelBlock(TRgb* aColorBuffer)
       
  1984 	{
       
  1985 	if ((iPos.iX >> iReductionFactor) < iReducedImageRegion.iBr.iX)
       
  1986 		{
       
  1987 		ASSERT(aColorBuffer);
       
  1988 
       
  1989 		if(iPositionChanged)
       
  1990 			{
       
  1991 			iImageProc->SetPos(TPoint(iPos.iX >> iReductionFactor,iPos.iY >> iReductionFactor));
       
  1992 			iPositionChanged = EFalse;
       
  1993 			}
       
  1994 
       
  1995 		TInt xOuterStop = iReducedBlockSize.iWidth<<iReductionFactor;
       
  1996 		TInt yOuterStop = iReducedBlockSize.iHeight<<iReductionFactor;
       
  1997 
       
  1998 		TInt outerStep = 1<<iReductionFactor;
       
  1999 		TInt divisionFactor = 2*iReductionFactor;
       
  2000 
       
  2001 		TRgb* reducedPixelBuffer = iReducedPixelBuffer;
       
  2002 
       
  2003 		for (TInt yOuter = 0; yOuter < yOuterStop; yOuter += outerStep)
       
  2004 			{
       
  2005 			for (TInt xOuter = 0; xOuter < xOuterStop; xOuter += outerStep)
       
  2006 				{
       
  2007 				TRgb* colorBuffer = &aColorBuffer[yOuter * iOriginalBlockSize.iWidth + xOuter];
       
  2008 				TInt red = 0;
       
  2009 				TInt green = 0;
       
  2010 				TInt blue = 0;
       
  2011 
       
  2012 				for (TInt yInner = 0; yInner < outerStep; yInner++)
       
  2013 					{
       
  2014 					for (TInt xInner = 0; xInner < outerStep; xInner++)
       
  2015 						{
       
  2016 						red += colorBuffer[xInner].Red();
       
  2017 						green += colorBuffer[xInner].Green();
       
  2018 						blue += colorBuffer[xInner].Blue();
       
  2019 						}
       
  2020 					colorBuffer += iOriginalBlockSize.iWidth;
       
  2021 					}
       
  2022 
       
  2023 				red >>= divisionFactor;
       
  2024 				green >>= divisionFactor;
       
  2025 				blue >>= divisionFactor;
       
  2026 
       
  2027 				*reducedPixelBuffer++ = TRgb(red,green,blue);
       
  2028 				}
       
  2029 			}
       
  2030 
       
  2031 		iImageProc->SetPixelBlock(iReducedPixelBuffer);
       
  2032 		}
       
  2033 
       
  2034 	iPos.iX += iOriginalBlockSize.iWidth;
       
  2035 	if (iPos.iX >= iEndOfLineX)
       
  2036 		{
       
  2037 		iPos.iX = iStartPosition.iX;
       
  2038 		iPos.iY += iYInc;
       
  2039 		if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
  2040 			{
       
  2041 			return ETrue;
       
  2042 			}
       
  2043 		}
       
  2044 
       
  2045 	return EFalse;
       
  2046 
       
  2047 	}
       
  2048 
       
  2049 TBool CThumbnailProcessor::FlushPixels()
       
  2050 	{
       
  2051 	DoFlushPixels();
       
  2052 	iImageProc->FlushPixels();
       
  2053 
       
  2054 	iPositionChanged = ETrue;
       
  2055 
       
  2056 	if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
  2057 		{
       
  2058 		return ETrue;
       
  2059 		}
       
  2060 
       
  2061 	return EFalse;
       
  2062 	}
       
  2063 
       
  2064 void CThumbnailProcessor::DoFlushPixels()
       
  2065 	{
       
  2066 	if(!iReducedSumBuffer)
       
  2067 		return;
       
  2068 
       
  2069 	TColorSum* reducedSumPtr = iReducedSumBuffer + iReducedImageRegion.iTl.iX;
       
  2070 	TColorSum* reducedSumPtrLimit = iReducedSumBuffer + iReducedImageRegion.iBr.iX;
       
  2071 
       
  2072 	while(reducedSumPtr < reducedSumPtrLimit)
       
  2073 		{
       
  2074 
       
  2075 		while(reducedSumPtr->iCount==0)
       
  2076 			{
       
  2077 			reducedSumPtr++;
       
  2078 			if(reducedSumPtr==reducedSumPtrLimit)
       
  2079 				return;
       
  2080 			}
       
  2081 
       
  2082 		if(iPositionChanged)
       
  2083 			iImageProc->SetPos(TPoint(reducedSumPtr - iReducedSumBuffer,iPos.iY >> iReductionFactor));
       
  2084 
       
  2085 		TRgb* reducedPixelBufferPtr = iReducedPixelBuffer;
       
  2086 		TInt fullCountFactor = 2*iReductionFactor;
       
  2087 
       
  2088 		while(reducedSumPtr < reducedSumPtrLimit)
       
  2089 			{
       
  2090 			TInt count = reducedSumPtr->iCount;
       
  2091 			TUint32 red;
       
  2092 			TUint32 green;
       
  2093 			TUint32 blue;
       
  2094 
       
  2095 			if(count == (1<<fullCountFactor))
       
  2096 				{
       
  2097 				red = reducedSumPtr->iRed >> fullCountFactor;
       
  2098 				green = reducedSumPtr->iGreen >> fullCountFactor;
       
  2099 				blue = reducedSumPtr->iBlue >> fullCountFactor;
       
  2100 				}
       
  2101 			else if(count!=0)
       
  2102 				{
       
  2103 				red = reducedSumPtr->iRed / count;
       
  2104 				green = reducedSumPtr->iGreen / count;
       
  2105 				blue = reducedSumPtr->iBlue / count;
       
  2106 				}
       
  2107 			else
       
  2108 				break;
       
  2109 
       
  2110 			*reducedPixelBufferPtr++ = TRgb(red,green,blue);
       
  2111 
       
  2112 			reducedSumPtr++;
       
  2113 			}
       
  2114 
       
  2115 		TInt numPixels = reducedPixelBufferPtr-iReducedPixelBuffer;
       
  2116 		iImageProc->SetPixels(iReducedPixelBuffer,numPixels);
       
  2117 
       
  2118 		Mem::FillZ(reducedSumPtr-numPixels,numPixels * sizeof(TColorSum));
       
  2119 		}
       
  2120 
       
  2121 	}
       
  2122 
       
  2123 TBool CThumbnailProcessor::SetPos(const TPoint& aPosition)
       
  2124 	{
       
  2125 	if(iImageRegion.Contains(aPosition)==EFalse)
       
  2126 		return EFalse;
       
  2127 
       
  2128 	if((aPosition.iY ^ iPos.iY) >> iReductionFactor)
       
  2129 		DoFlushPixels();
       
  2130 
       
  2131 	iPositionChanged = ETrue;
       
  2132 	iPos = aPosition;
       
  2133 
       
  2134 	return ETrue;
       
  2135 	}
       
  2136 
       
  2137 void CThumbnailProcessor::SetYPosIncrement(TInt aYInc)
       
  2138 	{
       
  2139 	iYInc = aYInc;
       
  2140 
       
  2141 	TInt reducedYInc = aYInc >> iReductionFactor;
       
  2142 	if(reducedYInc==0)
       
  2143 		reducedYInc = 1;
       
  2144 
       
  2145 	iImageProc->SetYPosIncrement(reducedYInc);
       
  2146 	}
       
  2147 
       
  2148 void CThumbnailProcessor::SetLineRepeat(TInt aLineRepeat)
       
  2149 	{
       
  2150 	TInt reducedLineRepeat = aLineRepeat >> iReductionFactor;
       
  2151 	iImageProc->SetLineRepeat(reducedLineRepeat);
       
  2152 	}
       
  2153 
       
  2154 void CThumbnailProcessor::SetPixelPadding(TInt aNumberOfPixels)
       
  2155 	{
       
  2156 	iPixelPadding = aNumberOfPixels;
       
  2157 	iEndOfLineX = iEndPosition.iX + iPixelPadding;
       
  2158 	}
       
  2159 
       
  2160 //
       
  2161 // CMonochromeThumbnailProcessor
       
  2162 //
       
  2163 
       
  2164 /**
       
  2165  *
       
  2166  * Static factory function to create CMonochromeThumbnailProcessor objects.
       
  2167  *
       
  2168  * @param	"aImageProc"
       
  2169  *          A pointer to an externally constructed CImageProcessorExtension object.
       
  2170  *          This will be deleted when the CMonochromeThumbnailProcessor object is deleted.
       
  2171  * @param	aReductionFactor"
       
  2172  *          The reduction factor to use.
       
  2173  * @return  Pointer to a fully constructed CMonochromeThumbnailProcessor object. 
       
  2174  */
       
  2175 CMonochromeThumbnailProcessor* CMonochromeThumbnailProcessor::NewL(CImageProcessorExtension* aImageProc,TInt aReductionFactor)
       
  2176 	{
       
  2177 	return new(ELeave) CMonochromeThumbnailProcessor(aImageProc,aReductionFactor);
       
  2178 	}
       
  2179 
       
  2180 CMonochromeThumbnailProcessor::CMonochromeThumbnailProcessor(CImageProcessorExtension* aImageProc,TInt aReductionFactor):
       
  2181 	iImageProc(aImageProc),
       
  2182 	iYInc(1),
       
  2183 	iReductionFactor(aReductionFactor)
       
  2184 		{}
       
  2185 
       
  2186 CMonochromeThumbnailProcessor::~CMonochromeThumbnailProcessor()
       
  2187 	{
       
  2188 	delete iImageProc;
       
  2189 	delete[] iReducedPixelBuffer;
       
  2190 	delete[] iReducedSumBuffer;
       
  2191 	}
       
  2192 
       
  2193 void CMonochromeThumbnailProcessor::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect)
       
  2194 	{
       
  2195 	PrepareCommonL(aImageRect);
       
  2196 	iYInc = 1;
       
  2197 	
       
  2198 	TInt bufferSize = (iImageRegion.iBr.iX + (1<<iReductionFactor) -1 ) >> iReductionFactor;
       
  2199 
       
  2200 	ASSERT(iReducedSumBuffer == NULL);
       
  2201 	iReducedSumBuffer = new(ELeave) TMonochromeSum[bufferSize];
       
  2202 	Mem::FillZ(iReducedSumBuffer,bufferSize * sizeof(TMonochromeSum));
       
  2203 
       
  2204 	iImageProc->PrepareL(aBitmap,iReducedImageRegion);
       
  2205 
       
  2206 	ASSERT(iReducedPixelBuffer == NULL);
       
  2207 	iReducedPixelBuffer = new(ELeave) TUint32[iReducedImageRegion.iBr.iX];
       
  2208 	}
       
  2209 
       
  2210 void CMonochromeThumbnailProcessor::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect,const TSize& aRgbBlockSize)
       
  2211 	{
       
  2212 	PrepareCommonL(aImageRect);
       
  2213 
       
  2214 	CreateBlockBufferL(aRgbBlockSize.iWidth*aRgbBlockSize.iHeight);
       
  2215 
       
  2216 	iOriginalBlockSize = aRgbBlockSize;
       
  2217 	iYInc = iDrawBottomUp ? -iOriginalBlockSize.iHeight : iOriginalBlockSize.iHeight;
       
  2218 
       
  2219 
       
  2220 	iReducedBlockSize = aRgbBlockSize;
       
  2221 	iReducedBlockSize.iWidth >>= iReductionFactor;
       
  2222 	iReducedBlockSize.iHeight >>= iReductionFactor;
       
  2223 
       
  2224 	iImageProc->SetInitialScanlineSkipPadding(iNumberOfScanlinesToSkip >> iReductionFactor);
       
  2225 	iImageProc->SetPixelPadding(iPixelPadding >> iReductionFactor);
       
  2226 	iImageProc->PrepareL(aBitmap,iReducedImageRegion,iReducedBlockSize);
       
  2227 
       
  2228 	ASSERT(iReducedPixelBuffer == NULL);
       
  2229 	iReducedPixelBuffer = new(ELeave) TUint32[iReducedBlockSize.iWidth * iReducedBlockSize.iHeight];
       
  2230 	}
       
  2231 
       
  2232 void CMonochromeThumbnailProcessor::PrepareCommonL(const TRect& aImageRect)
       
  2233 	{
       
  2234 	ASSERT(iReductionFactor > 0);
       
  2235 	iImageRegion = aImageRect;
       
  2236 
       
  2237 	TInt roundUp = (1<<iReductionFactor)-1;
       
  2238 	iReducedImageRegion.iTl.iX = aImageRect.iTl.iX >> iReductionFactor;
       
  2239 	iReducedImageRegion.iTl.iY = aImageRect.iTl.iY >> iReductionFactor;
       
  2240 
       
  2241 	TSize size = aImageRect.Size();
       
  2242 	size.iWidth = (size.iWidth + roundUp) >> iReductionFactor;
       
  2243 	size.iHeight = (size.iHeight + roundUp) >> iReductionFactor;
       
  2244 	iReducedImageRegion.iBr = iReducedImageRegion.iTl + size;
       
  2245 	
       
  2246 	switch(iOperation)
       
  2247 		{
       
  2248 		case EDecodeRotate180:
       
  2249 		case EDecodeRotate270:
       
  2250 		case EDecodeHorizontalFlip:
       
  2251 		case EDecodeVerticalFlipRotate90:
       
  2252 			iDrawBottomUp = ETrue;
       
  2253 			iImageProc->SetOperation(iOperation);
       
  2254 			break;
       
  2255 		default:
       
  2256 			iDrawBottomUp = EFalse;
       
  2257 		}
       
  2258 	iStartPosition.SetXY(iImageRegion.iTl.iX, iDrawBottomUp ? aImageRect.iBr.iY - 1 : 0);
       
  2259 	iEndPosition.SetXY(aImageRect.iBr.iX, iDrawBottomUp ? aImageRect.iTl.iY - 1 : aImageRect.iBr.iY);
       
  2260 	iPos = iStartPosition;
       
  2261 	
       
  2262 	iPositionChanged = ETrue;
       
  2263 
       
  2264 	iEndOfLineX = iEndPosition.iX + iPixelPadding;
       
  2265 
       
  2266 	delete[] iReducedPixelBuffer;
       
  2267 	iReducedPixelBuffer = NULL;
       
  2268 
       
  2269 	delete iReducedSumBuffer;
       
  2270 	iReducedSumBuffer = NULL;
       
  2271 	}
       
  2272 
       
  2273 TBool CMonochromeThumbnailProcessor::SetMonoPixel(TInt aGray256)
       
  2274 	{
       
  2275 	TInt x = iPos.iX;
       
  2276 
       
  2277 	if (x < iImageRegion.iBr.iX)
       
  2278 		{
       
  2279 		TMonochromeSum* sumPtr = iReducedSumBuffer + (x >> iReductionFactor);
       
  2280 		sumPtr->iLevel += aGray256;
       
  2281 		sumPtr->iCount++;
       
  2282 		}
       
  2283 
       
  2284 	x++;
       
  2285 	iPos.iX = x;
       
  2286 
       
  2287 	if (x == iEndOfLineX)
       
  2288 		return NewLine();
       
  2289 
       
  2290 	return EFalse;
       
  2291 	}
       
  2292 
       
  2293 TBool CMonochromeThumbnailProcessor::SetMonoPixelRun(TInt aGray256,TInt aCount)
       
  2294 	{
       
  2295 	while (aCount != 0)
       
  2296 		{
       
  2297 		TInt x		= iPos.iX;
       
  2298 		TInt xLimit = x+aCount;
       
  2299 
       
  2300 		iPos.iX = xLimit;
       
  2301 
       
  2302 		if (xLimit > iImageRegion.iBr.iX)
       
  2303 			xLimit = iImageRegion.iBr.iX;
       
  2304 
       
  2305 		if (xLimit > x)
       
  2306 			{
       
  2307 			TInt numPixels = xLimit-x;
       
  2308 
       
  2309 			TInt reductionFactor = iReductionFactor;
       
  2310 			TInt reductionCount = 1<<reductionFactor;	//number of horizontal pixel in a TMonochromeSum
       
  2311 
       
  2312 			TMonochromeSum* sumPtr = iReducedSumBuffer + (x >> reductionFactor);
       
  2313 
       
  2314 			TInt n = reductionCount-(x&(reductionCount-1));	//number of pixels to complete current TMonochromeSum
       
  2315 
       
  2316 			if(numPixels > n)
       
  2317 				{
       
  2318 				sumPtr->iCount += n;					//Complete first TMonochromeSum in run
       
  2319 				sumPtr->iLevel += n * aGray256;
       
  2320 				sumPtr++;
       
  2321 				numPixels -= n;
       
  2322 
       
  2323 				while(numPixels > reductionCount)			//Complete middle TMonochromeSum(s) in run
       
  2324 					{
       
  2325 					sumPtr->iCount += reductionCount;
       
  2326 					sumPtr->iLevel += aGray256 << reductionFactor;
       
  2327 					sumPtr++;
       
  2328 					numPixels -= reductionCount;
       
  2329 					}
       
  2330 				}
       
  2331 
       
  2332 			sumPtr->iCount += numPixels;				//Update last/only TMonochromeSum in run
       
  2333 			sumPtr->iLevel += numPixels * aGray256;
       
  2334 			}
       
  2335 
       
  2336 		if (iPos.iX < iEndOfLineX)
       
  2337 			break;
       
  2338 
       
  2339 		aCount = iPos.iX - iEndOfLineX;
       
  2340 
       
  2341 		if(NewLine())
       
  2342 			return ETrue;
       
  2343 		}
       
  2344 
       
  2345 	return EFalse;
       
  2346 	}
       
  2347 
       
  2348 TBool CMonochromeThumbnailProcessor::NewLine()
       
  2349 	{
       
  2350 	TInt newY = iPos.iY + iYInc;
       
  2351 
       
  2352 	TBool finished = (newY < iStartPosition.iY || newY >= iEndPosition.iY);
       
  2353 	TBool outsideOfBuffer = ((newY ^ iPos.iY) >> iReductionFactor) != 0;
       
  2354 
       
  2355 	if(finished || outsideOfBuffer)
       
  2356 		{
       
  2357 		DoFlushPixels();
       
  2358 		}
       
  2359 
       
  2360 	iPos.iX = iStartPosition.iX;
       
  2361 	iPos.iY = newY;
       
  2362 
       
  2363 	if(iPositionChanged && outsideOfBuffer)
       
  2364 		{
       
  2365 		iImageProc->SetPos(TPoint(iPos.iX >> iReductionFactor,iPos.iY >> iReductionFactor));
       
  2366 		iPositionChanged = EFalse;
       
  2367 		}
       
  2368 
       
  2369 	return finished;
       
  2370 	}
       
  2371 
       
  2372 TBool CMonochromeThumbnailProcessor::SetMonoPixelBlock(TUint32* aGray256Buffer)
       
  2373 	{
       
  2374 	if ((iPos.iX >> iReductionFactor) < iReducedImageRegion.iBr.iX)
       
  2375 		{
       
  2376 		ASSERT(aGray256Buffer);
       
  2377 
       
  2378 		if(iPositionChanged)
       
  2379 			{
       
  2380 			iImageProc->SetPos(TPoint(iPos.iX >> iReductionFactor,iPos.iY >> iReductionFactor));
       
  2381 			iPositionChanged = EFalse;
       
  2382 			}
       
  2383 
       
  2384 		TInt xOuterStop = iReducedBlockSize.iWidth<<iReductionFactor;
       
  2385 		TInt yOuterStop = iReducedBlockSize.iHeight<<iReductionFactor;
       
  2386 
       
  2387 		TInt outerStep = 1<<iReductionFactor;
       
  2388 		TInt divisionFactor = 2*iReductionFactor;
       
  2389 
       
  2390 		TUint32* reducedPixelBuffer = iReducedPixelBuffer;
       
  2391 
       
  2392 		for (TInt yOuter = 0; yOuter < yOuterStop; yOuter += outerStep)
       
  2393 			{
       
  2394 			for (TInt xOuter = 0; xOuter < xOuterStop; xOuter += outerStep)
       
  2395 				{
       
  2396 				TUint32* gray256Buffer = &aGray256Buffer[yOuter * iOriginalBlockSize.iWidth + xOuter];
       
  2397 				TInt level = 0;
       
  2398 
       
  2399 				for (TInt yInner = 0; yInner < outerStep; yInner++)
       
  2400 					{
       
  2401 					for (TInt xInner = 0; xInner < outerStep; xInner++)
       
  2402 						level += gray256Buffer[xInner];
       
  2403 
       
  2404 					gray256Buffer += iOriginalBlockSize.iWidth;
       
  2405 					}
       
  2406 
       
  2407 				level >>= divisionFactor;
       
  2408 				*reducedPixelBuffer++ = level;
       
  2409 				}
       
  2410 			}
       
  2411 
       
  2412 		iImageProc->SetMonoPixelBlock(iReducedPixelBuffer);
       
  2413 		}
       
  2414 
       
  2415 	iPos.iX += iOriginalBlockSize.iWidth;
       
  2416 	if (iPos.iX >= iEndOfLineX)
       
  2417 		{
       
  2418 		iPos.iX = iStartPosition.iX;
       
  2419 		iPos.iY += iYInc;
       
  2420 		if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
  2421 			{
       
  2422 			return ETrue;
       
  2423 			}
       
  2424 		}
       
  2425 
       
  2426 	return EFalse;
       
  2427 
       
  2428 	}
       
  2429 
       
  2430 TBool CMonochromeThumbnailProcessor::FlushPixels()
       
  2431 	{
       
  2432 	DoFlushPixels();
       
  2433 	iImageProc->FlushPixels();
       
  2434 
       
  2435 	iPositionChanged = ETrue;
       
  2436 
       
  2437 		if(iPos.iY < iStartPosition.iY || iPos.iY >= iEndPosition.iY)
       
  2438 			{
       
  2439 			return ETrue;
       
  2440 			}
       
  2441 
       
  2442 	return EFalse;
       
  2443 	}
       
  2444 
       
  2445 void CMonochromeThumbnailProcessor::DoFlushPixels()
       
  2446 	{
       
  2447 	if(!iReducedSumBuffer)
       
  2448 		return;
       
  2449 
       
  2450 	TMonochromeSum* reducedSumPtr = iReducedSumBuffer + iReducedImageRegion.iTl.iX;
       
  2451 	TMonochromeSum* reducedSumPtrLimit = iReducedSumBuffer + iReducedImageRegion.iBr.iX;
       
  2452 
       
  2453 	while(reducedSumPtr < reducedSumPtrLimit)
       
  2454 		{
       
  2455 
       
  2456 		while(reducedSumPtr->iCount==0)
       
  2457 			{
       
  2458 			reducedSumPtr++;
       
  2459 			if(reducedSumPtr==reducedSumPtrLimit)
       
  2460 				return;
       
  2461 			}
       
  2462 
       
  2463 		if(iPositionChanged)
       
  2464 			iImageProc->SetPos(TPoint(reducedSumPtr - iReducedSumBuffer,iPos.iY >> iReductionFactor));
       
  2465 
       
  2466 		TUint32* reducedPixelBufferPtr = iReducedPixelBuffer;
       
  2467 		TInt fullCountFactor = 2*iReductionFactor;
       
  2468 		TInt fullCount = 1<<fullCountFactor;
       
  2469 
       
  2470 		do
       
  2471 			{
       
  2472 			TInt level = reducedSumPtr->iLevel;
       
  2473 			TInt count = reducedSumPtr->iCount;
       
  2474 
       
  2475 			if(count==fullCount)
       
  2476 				level >>= fullCountFactor;
       
  2477 			else if(count!=0)
       
  2478 				level /= count;
       
  2479 			else
       
  2480 				break;
       
  2481 
       
  2482 			*reducedPixelBufferPtr++ = level;
       
  2483 
       
  2484 			reducedSumPtr++;
       
  2485 			}
       
  2486 		while(reducedSumPtr < reducedSumPtrLimit);
       
  2487 
       
  2488 		TInt numPixels = reducedPixelBufferPtr-iReducedPixelBuffer;
       
  2489 		iImageProc->SetMonoPixels(iReducedPixelBuffer,numPixels);
       
  2490 
       
  2491 		Mem::FillZ(reducedSumPtr-numPixels,numPixels * sizeof(TMonochromeSum));
       
  2492 		}
       
  2493 
       
  2494 	}
       
  2495 
       
  2496 TBool CMonochromeThumbnailProcessor::SetPos(const TPoint& aPosition)
       
  2497 	{
       
  2498 	if(iImageRegion.Contains(aPosition)==EFalse)
       
  2499 		return EFalse;
       
  2500 
       
  2501 	if((aPosition.iY ^ iPos.iY) >> iReductionFactor)
       
  2502 		DoFlushPixels();
       
  2503 
       
  2504 	iPositionChanged = ETrue;
       
  2505 	iPos = aPosition;
       
  2506 
       
  2507 	return ETrue;
       
  2508 	}
       
  2509 
       
  2510 void CMonochromeThumbnailProcessor::SetYPosIncrement(TInt aYInc)
       
  2511 	{
       
  2512 	iYInc = aYInc;
       
  2513 
       
  2514 	TInt reducedYInc = aYInc >> iReductionFactor;
       
  2515 	if(reducedYInc==0)
       
  2516 		reducedYInc = 1;
       
  2517 
       
  2518 	iImageProc->SetYPosIncrement(reducedYInc);
       
  2519 	}
       
  2520 
       
  2521 void CMonochromeThumbnailProcessor::SetLineRepeat(TInt aLineRepeat)
       
  2522 	{
       
  2523 	TInt reducedLineRepeat = aLineRepeat >> iReductionFactor;
       
  2524 	iImageProc->SetLineRepeat(reducedLineRepeat);
       
  2525 	}
       
  2526 
       
  2527 void CMonochromeThumbnailProcessor::SetPixelPadding(TInt aNumberOfPixels)
       
  2528 	{
       
  2529 	iPixelPadding = aNumberOfPixels;
       
  2530 	iEndOfLineX = iEndPosition.iX + iPixelPadding;
       
  2531 	}
       
  2532