os/graphics/fbs/fontandbitmapserver/sfbs/BMPUTIL.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-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 <fbs.h>
    17 #include <graphics/lookuptable.h>
    18 #include "fbsdefs.h"
    19 #include "UTILS.H"
    20 
    21 GLREF_C void Panic(TFbsPanic aPanic);
    22 
    23 /* Macros used in support of EColor16M mode bitmaps in TBitmapUtil.
    24 PTR2UINT, UINT2PTR defined to ease byte pointer arithmatic using
    25 the existing iWordPos word sized pointer.
    26 i MACROS redefine the meaning of members in the class for 16M use.
    27 All in the name of Binary Compatibility - adding 16M support but
    28 without wasting memory or increasing the size of this class's objects. */
    29 #define PTR2UINT(_ptr)      reinterpret_cast<TUint32>(_ptr)
    30 #define UINT2PTR(_expr)     reinterpret_cast<TUint32*>(_expr)
    31 #define iNUM_WASTE_BYTES    iMask
    32 #define iSTART_OF_SCAN_LINE iWordPos
    33 #define iPIXEL_BYTE_OFFSET  iPixelShift
    34 #define iPIXEL_ADDRESS      UINT2PTR(PTR2UINT(iWordPos)+iPixelShift)
    35 
    36 
    37 /** Constructs a TBitmapUtil object for the specified bitmap. 
    38 
    39 @note The use of extended or compressed bitmaps is not supported by TBitmapUtil.
    40 
    41 @param aBitmap The bitmap on which this TBitmapUtil will operate. */
    42 EXPORT_C TBitmapUtil::TBitmapUtil(CFbsBitmap* aBitmap):
    43     iFbsBitmap(aBitmap),	// Address of bitmap to navigate and modify.
    44 	iWordPos(NULL),			// Non16M: Address of the word containing the bits
    45 							//         of the current pixel.
    46 							// 16M: Redefined to iSTART_OF_SCAN_LINE - word address
    47 							//      of the scan line containing the current pixel.
    48 	iMinWordPos(NULL),		// Member holds the word address of the top left pixel.
    49 	iMaxWordPos(NULL),		// Member holds address of the word following the last
    50 							// word in the last scan line of the bitmap.
    51 	iBpp(0),				// Number of bits needed for each pixel's data.
    52 	iPixelShift(0),			// Non16M: Right shift factor to convert pixel index
    53 	                        //         to word index into scan line.
    54 							// 16M: Redefined to iPIXEL_BYTE_OFFSET - index to first
    55 							//      byte in pixel from the start of the scan line.
    56 	iBitShift(0),			// Non16M: Changing index of right shift require to
    57 	                        //         move pixel bits into LSB of word.
    58 							// 16M: Not used, always 0
    59 	iMask(0),               // Non16M: Mask of LSB required to hold
    60 	                        //         pixel data eg. 16cols 0x0f
    61 							// 16M: Redefined to iNUM_WASTE_BYTES - number of
    62 							//      padding bytes at end of scan line 0,3,6,9 as 16M
    63 							//      scanlines are always multiples of 12 bytes.
    64 	iScanlineWordLength(0), // Number of 4-byte words in bitmap scan line
    65 	iWritten(EFalse)
    66 	{
    67 	ASSERT(iFbsBitmap);
    68 	__ASSERT_DEBUG(iFbsBitmap->Header().iCompression == ENoBitmapCompression, Panic(EFbsPanicInvalidBitmapType));
    69 	}
    70 
    71 /** Sets the current pixel position to the specified position and prepares
    72 the bitmap for access to its pixel data.
    73 
    74 This function must be called before using any of the other functions provided
    75 by this class, otherwise damage to data may occur. It must also be matched
    76 by a subsequent call to End().
    77 
    78 @pre The bitmap which was passed on class construction has been created and holds 
    79 	a valid handle.
    80 @param aPosition The position to which the current pixel position should be
    81 set. */
    82 EXPORT_C void TBitmapUtil::Begin(const TPoint& aPosition)
    83 	{
    84 	iFbsBitmap->BeginDataAccess();
    85 	TSize bmpsize(iFbsBitmap->SizeInPixels());
    86 	ASSERT(bmpsize.iWidth > 0 && bmpsize.iHeight > 0);
    87 
    88 	iWritten = EFalse;
    89 
    90 	TDisplayMode dm=iFbsBitmap->DisplayMode();
    91 	TInt numBytesInScanline = CFbsBitmap::ScanLineLength(bmpsize.iWidth,dm);
    92 	switch(dm)
    93 		{
    94 	case EGray2:
    95 		iMask=1;
    96 		iPixelShift=5;
    97 		iBpp=1;
    98 		break;
    99 	case EGray4:
   100 		iMask=3;
   101 		iPixelShift=4;
   102 		iBpp=2;
   103 		break;
   104 	case EGray16:
   105 	case EColor16:
   106 		iMask=0xf;
   107 		iPixelShift=3;
   108 		iBpp=4;
   109 		break;
   110 	case EGray256:
   111 	case EColor256:
   112 		iMask=0xff;
   113 		iPixelShift=2;
   114 		iBpp=8;
   115 		break;
   116 	case EColor4K:
   117 	case EColor64K:
   118 		iMask=0xffff;
   119 		iPixelShift=1;
   120 		iBpp=16;
   121 		break;
   122 	/* Bit twiddling not used in the EColor16M, members redefined for
   123      different use.	 */
   124 	case EColor16M:
   125 		iNUM_WASTE_BYTES = numBytesInScanline-(bmpsize.iWidth*3);
   126 		iPIXEL_BYTE_OFFSET=0;
   127 		iBpp=24; // Indicates 16M display mode, flag for member functions
   128 		         // to switch functionality.
   129 		break;
   130 	case EColor16MU:
   131 	case EColor16MA:
   132 	case EColor16MAP:
   133 		iMask=0xffffffff;
   134 		iPixelShift=0;
   135 		iBpp=32;
   136 		break;
   137 	default: //shouldn't reach this point
   138 		Panic(EFbsBitmapInvalidMode);
   139 		}
   140 
   141 	iMinWordPos=(TUint32*)iFbsBitmap->DataAddress();
   142 	iScanlineWordLength = numBytesInScanline / 4;
   143 	iMaxWordPos = iMinWordPos + (bmpsize.iHeight * iScanlineWordLength);
   144 
   145 	TPoint correct(aPosition);
   146 	if(correct.iX<0) correct.iX=0;
   147 	if(correct.iY<0) correct.iY=0;
   148 	if(correct.iX>=bmpsize.iWidth) correct.iX=bmpsize.iWidth;
   149 	if(correct.iY>=bmpsize.iHeight) correct.iY=bmpsize.iHeight;
   150 	SetPos(correct);
   151 	}
   152 
   153 /** Sets the current pixel position to the specified position and prepares
   154 the bitmap for access to its pixel data.
   155 
   156 This function is deprecated. Use the other overload, Begin(const TPoint&).
   157 @deprecated
   158 
   159 @param aPosition The position to which the current pixel position should be
   160 set.
   161 @param aUtil Not used.
   162 @panic FBCLI 10 The bitmap's display mode is ERgb or ENone. */
   163 EXPORT_C void TBitmapUtil::Begin(const TPoint& aPosition, const TBitmapUtil& /*aUtil*/)
   164 	{
   165 	Begin(aPosition);
   166 	}
   167 
   168 /** Marks the end of the access to the bitmap data.
   169 This function must be called when finished using all the other functions
   170 provided by this class.
   171 
   172 There must be exactly one call to End() for each previous call to Begin()
   173 for a given TBitmapUtil object. */
   174 EXPORT_C void TBitmapUtil::End()
   175 	{
   176 	iFbsBitmap->EndDataAccess(!iWritten);
   177 	}
   178 
   179 
   180 
   181 /** Gets the value of the pixel at the current pixel position.
   182 
   183 In normal usage, the value returned will immediately be used as the parameter
   184 to a call to SetPixel(). To remove the overhead of constructing a TRgb, the
   185 function uses a TUint32 rather than a TRgb to hold an RGB value.
   186 
   187 @return The value of the pixel at the current pixel position. */
   188 EXPORT_C TUint32 TBitmapUtil::GetPixel() const
   189 	{
   190 	if (iBpp!=24)
   191 		// 1,2,4,8,12,16,32-bit pixels
   192 		return((*iWordPos>>iBitShift)&iMask);
   193 	else
   194 		{
   195 		// 24-bit pixels
   196 		// Due to machine word alignment requirement on ARM, need to copy
   197 		// pixel data at iWordPos a byte at a time if address is not aligned
   198 		// on a 4 byte boundary i.e. 1st or 2nd least sig. bits set.
   199 		if (iPIXEL_BYTE_OFFSET & 0x3)
   200 			{
   201 			TUint32 pixel = 0;
   202 			Mem::Copy(&pixel, iPIXEL_ADDRESS, 3);
   203 			return pixel;
   204 			}
   205 		else
   206 			return (*( iPIXEL_ADDRESS )&0x00ffffff);
   207 		}
   208 	}
   209 
   210 /** Sets the value of the pixel at the current pixel position.
   211 
   212 To remove the overhead of constructing a TRgb, the function uses a TUint32
   213 rather than a TRgb to hold an RGB value.
   214 
   215 @param aValue The value to which the pixel at the current pixel position is
   216 to be set. */
   217 EXPORT_C void TBitmapUtil::SetPixel(TUint32 aValue)
   218 	{
   219 	iWritten = ETrue;
   220 	if (iBpp!=24)
   221 		{
   222 		// 1,2,4,8,12,16,32-bit pixels
   223 		*iWordPos&=~(iMask<<iBitShift);
   224 		*iWordPos|=(aValue&iMask)<<iBitShift;
   225 		if(iBpp==32 && iFbsBitmap && iFbsBitmap->DisplayMode() == EColor16MU)
   226 				{
   227 				*iWordPos|= 0xff000000;
   228 				}
   229 		}
   230 	else
   231 		{
   232 		// 24-bit pixels
   233 		// Due to machine word alignment requirement on ARM, need to copy
   234 		// pixel data at iWordPos a byte at a time if address is not aligned
   235 		// on a 4 byte boundary i.e. 1st or 2nd least sig. bits set.
   236 		if (iPIXEL_BYTE_OFFSET & 0x3)
   237 			Mem::Copy(iPIXEL_ADDRESS, &aValue, 3);
   238 		else
   239 			{
   240 			*(iPIXEL_ADDRESS) &= ~0xffffff;
   241 			*(iPIXEL_ADDRESS) |= (aValue&0x00ffffff);
   242 			}
   243 		}
   244 	}
   245 
   246 /** Sets the value of the pixel at the current pixel position to that returned
   247 by aSource.GetPixel().
   248 
   249 @param aSource The TBitmapUtil of the source bitmap, whose pixel value is
   250 used to set the pixel at the current pixel position. */
   251 EXPORT_C void TBitmapUtil::SetPixel(const TBitmapUtil& aSource)
   252 	{
   253 	SetPixel(aSource.GetPixel());
   254 	}
   255 
   256 /** Sets a new current pixel position.
   257 
   258 @param aPosition The new current pixel position. */
   259 EXPORT_C void TBitmapUtil::SetPos(const TPoint& aPosition)
   260 	{
   261 	TSize bmpsize(iFbsBitmap->SizeInPixels());
   262 	TPoint correct(aPosition);
   263 
   264 	correct.iX%=bmpsize.iWidth;
   265 	correct.iY%=bmpsize.iHeight;
   266 	if(correct.iX<0) correct.iX+=bmpsize.iWidth;
   267 	if(correct.iY<0) correct.iY+=bmpsize.iHeight;
   268 
   269 	iWordPos=iMinWordPos;
   270 	iWordPos+=iScanlineWordLength*correct.iY;
   271 	if (iBpp!=24)
   272 		{
   273 		// 1,2,4,8,12,16,32-bit pixels
   274 		iWordPos+=correct.iX>>iPixelShift;
   275 		iBitShift=(correct.iX*iBpp)%32;
   276 		}
   277 	else
   278 		{
   279 		// 24-bit pixels
   280 		// iSTART_OF_SCAN_LINE (iWordPos) has correct value at this point
   281 		// iBitShift not used in 16M modes
   282 		iPIXEL_BYTE_OFFSET = correct.iX*3;	// Byte offset in iY scan line to iX pixel
   283 		}
   284 }
   285 
   286 /** Decrements the x co-ordinate of the current pixel position. */
   287 EXPORT_C void TBitmapUtil::DecXPos()
   288 	{
   289 	if (iBpp!=24)
   290 		{
   291 		// 1,2,4,8,12,16,32-bit pixels
   292 		iBitShift-=iBpp;
   293 		if(iBitShift<0)
   294 			{
   295 			iBitShift+=32;
   296 			iWordPos--;
   297 			if(iWordPos<iMinWordPos) iWordPos=iMaxWordPos-1;
   298 			}
   299 		}
   300 	else
   301 		{
   302 		// 24-bit pixels
   303 		iPIXEL_BYTE_OFFSET -= 3;
   304 
   305 		// Scanline underflow?
   306 		if (iPIXEL_BYTE_OFFSET < 0)
   307 			{
   308 			iPIXEL_BYTE_OFFSET = (iScanlineWordLength*4)-iNUM_WASTE_BYTES-3;
   309 
   310 			// Bitmap underflow?
   311 		    if (iSTART_OF_SCAN_LINE == iMinWordPos)
   312 				iSTART_OF_SCAN_LINE = iMaxWordPos-iScanlineWordLength;
   313 			else
   314 		        iSTART_OF_SCAN_LINE -= iScanlineWordLength;
   315 			}
   316 		}
   317 	}
   318 
   319 /** Decrements the y co-ordinate of the current pixel position. */
   320 EXPORT_C void TBitmapUtil::DecYPos()
   321 	{
   322 	iWordPos-=iScanlineWordLength;
   323 	if(iWordPos<iMinWordPos) iWordPos+=iMaxWordPos-iMinWordPos;
   324 	}
   325 
   326 /** Increments the x co-ordinate of the current pixel position. */
   327 EXPORT_C void TBitmapUtil::IncXPos()
   328 	{
   329 	if (iBpp!=24)
   330 		{
   331 		// 1,2,4,8,12,16,32-bit pixels
   332 		iBitShift+=iBpp;
   333 		if(iBitShift>=32)
   334 			{
   335 			iBitShift=0;
   336 			iWordPos++;
   337 			if(iWordPos>=iMaxWordPos) iWordPos=iMinWordPos;
   338 			}
   339 		}
   340 	else
   341 		{
   342 		// 24-bit pixels
   343 		iPIXEL_BYTE_OFFSET += 3;
   344 
   345 		// Scanline overflow?
   346 		if (iPIXEL_BYTE_OFFSET >=
   347 				(iScanlineWordLength*4)-static_cast<TInt>(iNUM_WASTE_BYTES))
   348 			{
   349 			iPIXEL_BYTE_OFFSET = 0;
   350 			iSTART_OF_SCAN_LINE += iScanlineWordLength;
   351 
   352 			// Bitmap overflow?
   353 			if (iSTART_OF_SCAN_LINE >= iMaxWordPos)
   354 				iSTART_OF_SCAN_LINE = iMinWordPos;
   355 			}
   356 		}
   357 	}
   358 
   359 /** Increments the y co-ordinate of the current pixel position. */
   360 EXPORT_C void TBitmapUtil::IncYPos()
   361 	{
   362 	iWordPos+=iScanlineWordLength;
   363 	if(iWordPos>=iMaxWordPos) iWordPos-=iMaxWordPos-iMinWordPos;
   364 	}
   365 
   366 
   367 
   368 //
   369 // CDitherColor256
   370 //
   371 
   372 class TDitherColorError
   373 	{
   374 public:
   375 	inline TDitherColorError() {};
   376 	inline TDitherColorError(TInt aRed,TInt aGreen,TInt aBlue) : iRed(aRed), iGreen(aGreen), iBlue(aBlue) {}
   377 public:
   378 	TInt iRed;
   379 	TInt iGreen;
   380 	TInt iBlue;
   381 	};
   382 
   383 NONSHARABLE_CLASS(CDitherColor256) : public CBase
   384 	{
   385 public:
   386 	void ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil = NULL);
   387 	void Reset();
   388 	void ConvertLine(TUint8* aDestination,TRgb* aSource);
   389 	~CDitherColor256();
   390 private:
   391 	const TColor256Util* iColorUtil;
   392 	TInt iLineWidth;
   393 	TDitherColorError* iErrorBuffer;
   394 	TInt iErrorBufferLength;
   395 	};
   396 
   397 CDitherColor256::~CDitherColor256()
   398 	{
   399 	delete[] iErrorBuffer;
   400 	}
   401 
   402 void CDitherColor256::ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil)
   403 	{
   404 	if(iErrorBufferLength<=aLineWidth)
   405 		{
   406 		delete[] iErrorBuffer;
   407 		iErrorBuffer = NULL;
   408 		}
   409 
   410 	if(!iErrorBuffer)
   411 		{
   412 		iErrorBuffer = new (ELeave) TDitherColorError[aLineWidth+1];
   413 		iErrorBufferLength = aLineWidth+1;
   414 		}
   415 
   416 	iLineWidth = aLineWidth;
   417 	if(!aColorUtil)
   418 		aColorUtil = TColor256Util::Default();
   419 	iColorUtil = aColorUtil;
   420 
   421 	Reset();
   422 	}
   423 
   424 void CDitherColor256::Reset()
   425 	{
   426 	Mem::FillZ(iErrorBuffer,iErrorBufferLength*sizeof(iErrorBuffer[0]));
   427 	}
   428 
   429 void CDitherColor256::ConvertLine(TUint8* aDestination,TRgb* aSource)
   430 	{
   431 	TUint8* dstLimit = aDestination+iLineWidth;
   432 	TDitherColorError* errorBuffer = iErrorBuffer;
   433 
   434 	TInt r = errorBuffer->iRed;
   435 	TInt g = errorBuffer->iGreen;
   436 	TInt b = errorBuffer->iBlue;
   437 	errorBuffer->iRed = 0;
   438 	errorBuffer->iGreen = 0;
   439 	errorBuffer->iBlue = 0;
   440 
   441 	while(aDestination<dstLimit)
   442 		{
   443 
   444 		{
   445 		TInt value = 0;
   446 
   447 		r += aSource->Red();
   448 		if(r>255)
   449 			value = 255;
   450 		else if(r>0)
   451 			value = r;
   452 
   453 		g += aSource->Green();
   454 		if(g>255)
   455 			value |= 255<<8;
   456 		else if(g>0)
   457 			value |= g<<8;
   458 
   459 		b += aSource->Blue();
   460 		if(b>255)
   461 			value |= 255<<16;
   462 		else if(b>0)
   463 			value |= b<<16;
   464 
   465 		aSource++;
   466 
   467 		value = iColorUtil->Color256(TRgb(value));
   468 		*(aDestination) = (TUint8)value;
   469 		value = iColorUtil->Color256(value).Value();
   470 
   471 		r -= value&0xFF;
   472 		g -= (value>>8)&0xFF;
   473 		b -= (value>>16)&0xFF;
   474 		}
   475 
   476 		{
   477 		TInt x = r>>2;
   478 		r = (r>>1)-(r>>3);
   479 		errorBuffer->iRed += r;
   480 		r += errorBuffer[1].iRed;
   481 		errorBuffer[1].iRed = x;
   482 
   483 		x = g>>2;
   484 		g = (g>>1)-(g>>3);
   485 		errorBuffer->iGreen += g;
   486 		g += errorBuffer[1].iGreen;
   487 		errorBuffer[1].iGreen = x;
   488 
   489 		x = b>>2;
   490 		b = (b>>1)-(b>>3);
   491 		errorBuffer->iBlue += b;
   492 		b += errorBuffer[1].iBlue;
   493 		errorBuffer[1].iBlue = x;
   494 
   495 		errorBuffer++;
   496 		}
   497 
   498 		aDestination++;
   499 		}
   500 	}
   501 
   502 //
   503 // CFbsColor256BitmapUtil
   504 //
   505 
   506 inline CFbsColor256BitmapUtil::CFbsColor256BitmapUtil()
   507 	{ }
   508 
   509 /** Allocates and constructs a new 256 colour bitmap utility object, optionally
   510 specifying a palette.
   511 
   512 @param aPalette The palette of colours to use for the destination 256 colour
   513 bitmap. If there are more than 256 colours in the palette, only the first
   514 256 are used. May be NULL, in which case the system default 256 colour palette
   515 is used.
   516 @return The newly constructed object. */
   517 EXPORT_C CFbsColor256BitmapUtil* CFbsColor256BitmapUtil::NewL(const CPalette* aPalette)
   518 	{
   519 	CFbsColor256BitmapUtil* self = new (ELeave) CFbsColor256BitmapUtil;
   520 	CleanupStack::PushL(self);
   521 	if(aPalette)
   522 		{
   523 		self->iColor256Util = new (ELeave) TColor256Util;
   524 		self->iColor256Util->Construct(*aPalette);
   525 		}
   526 	// coverity[leave_without_push : FALSE]
   527 	// class member variables should not be pushed onto the cleanupstack 
   528 	self->iDither = new (ELeave) CDitherColor256;
   529 	CleanupStack::Pop();
   530 	return self;
   531 	}
   532 
   533 CFbsColor256BitmapUtil::~CFbsColor256BitmapUtil()
   534 	{
   535 	delete iColor256Util;
   536 	delete iDither;
   537 	}
   538 
   539 /** Copies the contents of a source bitmap to a destination 256 colour bitmap.
   540 Both bitmaps must be the same size and the destination bitmap's display mode
   541 must be EColor256.
   542 
   543 @param aColor256Destination The destination to copy the bitmap to. Its display
   544 mode must be EColor256.
   545 @param aSource The source bitmap to copy from. Its display mode can be EColor16M,
   546 EColor64K, EColor4K or EColor256.
   547 @param aDither Specify EFloydSteinberg for Floyd-Steinberg dithering. By default,
   548 no dithering.
   549 @return KErrNone, if successful; otherwise, another of the system-wide error
   550 codes. KErrNotSupported is returned if aSource's display mode is not one of
   551 the values listed.
   552 @panic EFbsColor256UtilError Either aColor256Destination's display mode is
   553 not EColor256, or the two bitmaps are not the same size. */
   554 EXPORT_C TInt CFbsColor256BitmapUtil::CopyBitmap(CFbsBitmap* aColor256Destination,CFbsBitmap* aSource,TDither aDither)
   555 	{
   556 	aSource->BeginDataAccess();
   557 	aColor256Destination->BeginDataAccess();
   558 	const TDisplayMode sourceMode = aSource->DisplayMode();
   559 
   560 	TSize size(aSource->SizeInPixels());
   561 	TInt width = size.iWidth;
   562 	TInt height = size.iHeight;
   563 
   564 	// Check we are being askes to copy a bitmap to a color256 bitmap of the same size
   565 	if( aColor256Destination->DisplayMode()!=EColor256 || aColor256Destination->SizeInPixels()!=size )
   566 		Panic(EFbsColor256UtilError);
   567 
   568 	if( sourceMode!=EColor256 && sourceMode!=EColor4K && sourceMode!=EColor64K &&
   569 		sourceMode!=EColor16M && sourceMode!=EColor16MU && sourceMode!=EColor16MA && sourceMode!=EColor16MAP)
   570 		{
   571 		aSource->EndDataAccess(ETrue);
   572 		aColor256Destination->EndDataAccess(ETrue);
   573 		return KErrNotSupported;
   574 		}
   575 
   576 	// get a TColor256Utils to use
   577 	const TColor256Util* colorUtil = iColor256Util;
   578 	if(!colorUtil)
   579 		colorUtil = TColor256Util::Default();
   580 
   581 	if(aDither==EFloydSteinberg)
   582 		{
   583 		TRAPD(err,iDither->ConstructL(width,colorUtil));
   584 		if(err!=KErrNone)
   585 			{
   586 			aSource->EndDataAccess(ETrue);
   587 			aColor256Destination->EndDataAccess(ETrue);
   588 			return err;
   589 			}
   590 		}
   591 
   592 	TRgb* pixelBuffer = new TRgb[width];
   593 	if(!pixelBuffer)
   594 		{
   595 		aSource->EndDataAccess(ETrue);
   596 		aColor256Destination->EndDataAccess(ETrue);
   597 		return KErrNoMemory;
   598 		}
   599 
   600 	TUint8* src = (TUint8*)aSource->DataAddress();
   601 	TInt srcPitch = aSource->ScanLineLength(width,sourceMode);
   602 	TUint8* dst = (TUint8*)aColor256Destination->DataAddress();
   603 	TInt dstPitch = aColor256Destination->ScanLineLength(width,EColor256);
   604 
   605 	while(height--)
   606 		{
   607 		TInt i(0);
   608 		switch(sourceMode)
   609 			{
   610 			case EColor256:
   611 				for(i=0; i<width; i++)
   612 					pixelBuffer[i] = TRgb::Color256(((TUint8*)src)[i]);
   613 				break;
   614 			case EColor4K:
   615 				for(i=0; i<width; i++)
   616 					pixelBuffer[i] = TRgb::_Color4K(((TUint16*)src)[i]);
   617 				break;
   618 			case EColor64K:
   619 				for(i=0; i<width; i++)
   620 					pixelBuffer[i] = TRgb::_Color64K(((TUint16*)src)[i]);
   621 				break;
   622 			case EColor16M:
   623 				{
   624 				TUint8* data = src;
   625 				TUint8* dataLimit = data+width*3;
   626 				i = 0;
   627 				while(data<dataLimit)
   628 					{
   629 					TUint32 value = *(data++)<<16;
   630 					value += *(data++)<<8;
   631 					value += *(data++);
   632 					pixelBuffer[i++] = TRgb(value);
   633 					}
   634 				}
   635 				break;
   636 			case EColor16MU:
   637 				{
   638 				TInt32* data = reinterpret_cast<TInt32*> (src);
   639 				TInt32* dataLimit = data+width;
   640 				i = 0;
   641 				while(data<dataLimit)
   642 					{
   643 					pixelBuffer[i++] = TRgb::_Color16MU(*data++);
   644 					}
   645 				}
   646 				break;
   647 			case EColor16MA:
   648 				{
   649 				TInt32* data = reinterpret_cast<TInt32*> (src);
   650 				TInt32* dataLimit = data+width;
   651 				i = 0;
   652 				while(data<dataLimit)
   653 					{
   654 					pixelBuffer[i++] = TRgb::_Color16MA(*data++);
   655 					}
   656 				}
   657 				break;
   658 			case EColor16MAP:
   659 				{
   660 				// perform division of color channels by alpha.
   661 				TInt32* data = reinterpret_cast<TInt32*> (src);
   662 				TInt32* dataLimit = data+width;
   663 				while(data<dataLimit)
   664 					{
   665 					pixelBuffer[i++] = TRgb::_Color16MAP(*data++);
   666 					}
   667 				}
   668 				break;
   669 			default:
   670 				break;
   671 			}
   672 		if(aDither==EFloydSteinberg)
   673 			iDither->ConvertLine(dst,pixelBuffer);
   674 		else
   675 			colorUtil->Color256(dst,pixelBuffer,width);
   676 		dst += dstPitch;
   677 		src += srcPitch;
   678 		}
   679 
   680 	aSource->EndDataAccess(ETrue);
   681 	aColor256Destination->EndDataAccess(EFalse);
   682 
   683 	delete[] pixelBuffer;
   684 	return KErrNone;
   685 	}
   686 
   687 /**
   688 
   689 Required to ensure BC between NGage and 7.0S platforms.
   690 Function is exported at ordinal corresponding to where NGage platform
   691 has extended this library and must not be moved. */
   692 EXPORT_C void DummyReserved1()
   693 	{
   694 	User::Panic(_L("Dummy Function"), 0);
   695 	}
   696 
   697