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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <graphics/lookuptable.h>
21 GLREF_C void Panic(TFbsPanic aPanic);
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)
37 /** Constructs a TBitmapUtil object for the specified bitmap.
39 @note The use of extended or compressed bitmaps is not supported by TBitmapUtil.
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
68 __ASSERT_DEBUG(iFbsBitmap->Header().iCompression == ENoBitmapCompression, Panic(EFbsPanicInvalidBitmapType));
71 /** Sets the current pixel position to the specified position and prepares
72 the bitmap for access to its pixel data.
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().
78 @pre The bitmap which was passed on class construction has been created and holds
80 @param aPosition The position to which the current pixel position should be
82 EXPORT_C void TBitmapUtil::Begin(const TPoint& aPosition)
84 iFbsBitmap->BeginDataAccess();
85 TSize bmpsize(iFbsBitmap->SizeInPixels());
86 ASSERT(bmpsize.iWidth > 0 && bmpsize.iHeight > 0);
90 TDisplayMode dm=iFbsBitmap->DisplayMode();
91 TInt numBytesInScanline = CFbsBitmap::ScanLineLength(bmpsize.iWidth,dm);
122 /* Bit twiddling not used in the EColor16M, members redefined for
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.
137 default: //shouldn't reach this point
138 Panic(EFbsBitmapInvalidMode);
141 iMinWordPos=(TUint32*)iFbsBitmap->DataAddress();
142 iScanlineWordLength = numBytesInScanline / 4;
143 iMaxWordPos = iMinWordPos + (bmpsize.iHeight * iScanlineWordLength);
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;
153 /** Sets the current pixel position to the specified position and prepares
154 the bitmap for access to its pixel data.
156 This function is deprecated. Use the other overload, Begin(const TPoint&).
159 @param aPosition The position to which the current pixel position should be
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*/)
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.
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()
176 iFbsBitmap->EndDataAccess(!iWritten);
181 /** Gets the value of the pixel at the current pixel position.
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.
187 @return The value of the pixel at the current pixel position. */
188 EXPORT_C TUint32 TBitmapUtil::GetPixel() const
191 // 1,2,4,8,12,16,32-bit pixels
192 return((*iWordPos>>iBitShift)&iMask);
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)
202 Mem::Copy(&pixel, iPIXEL_ADDRESS, 3);
206 return (*( iPIXEL_ADDRESS )&0x00ffffff);
210 /** Sets the value of the pixel at the current pixel position.
212 To remove the overhead of constructing a TRgb, the function uses a TUint32
213 rather than a TRgb to hold an RGB value.
215 @param aValue The value to which the pixel at the current pixel position is
217 EXPORT_C void TBitmapUtil::SetPixel(TUint32 aValue)
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)
227 *iWordPos|= 0xff000000;
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);
240 *(iPIXEL_ADDRESS) &= ~0xffffff;
241 *(iPIXEL_ADDRESS) |= (aValue&0x00ffffff);
246 /** Sets the value of the pixel at the current pixel position to that returned
247 by aSource.GetPixel().
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)
253 SetPixel(aSource.GetPixel());
256 /** Sets a new current pixel position.
258 @param aPosition The new current pixel position. */
259 EXPORT_C void TBitmapUtil::SetPos(const TPoint& aPosition)
261 TSize bmpsize(iFbsBitmap->SizeInPixels());
262 TPoint correct(aPosition);
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;
269 iWordPos=iMinWordPos;
270 iWordPos+=iScanlineWordLength*correct.iY;
273 // 1,2,4,8,12,16,32-bit pixels
274 iWordPos+=correct.iX>>iPixelShift;
275 iBitShift=(correct.iX*iBpp)%32;
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
286 /** Decrements the x co-ordinate of the current pixel position. */
287 EXPORT_C void TBitmapUtil::DecXPos()
291 // 1,2,4,8,12,16,32-bit pixels
297 if(iWordPos<iMinWordPos) iWordPos=iMaxWordPos-1;
303 iPIXEL_BYTE_OFFSET -= 3;
305 // Scanline underflow?
306 if (iPIXEL_BYTE_OFFSET < 0)
308 iPIXEL_BYTE_OFFSET = (iScanlineWordLength*4)-iNUM_WASTE_BYTES-3;
311 if (iSTART_OF_SCAN_LINE == iMinWordPos)
312 iSTART_OF_SCAN_LINE = iMaxWordPos-iScanlineWordLength;
314 iSTART_OF_SCAN_LINE -= iScanlineWordLength;
319 /** Decrements the y co-ordinate of the current pixel position. */
320 EXPORT_C void TBitmapUtil::DecYPos()
322 iWordPos-=iScanlineWordLength;
323 if(iWordPos<iMinWordPos) iWordPos+=iMaxWordPos-iMinWordPos;
326 /** Increments the x co-ordinate of the current pixel position. */
327 EXPORT_C void TBitmapUtil::IncXPos()
331 // 1,2,4,8,12,16,32-bit pixels
337 if(iWordPos>=iMaxWordPos) iWordPos=iMinWordPos;
343 iPIXEL_BYTE_OFFSET += 3;
345 // Scanline overflow?
346 if (iPIXEL_BYTE_OFFSET >=
347 (iScanlineWordLength*4)-static_cast<TInt>(iNUM_WASTE_BYTES))
349 iPIXEL_BYTE_OFFSET = 0;
350 iSTART_OF_SCAN_LINE += iScanlineWordLength;
353 if (iSTART_OF_SCAN_LINE >= iMaxWordPos)
354 iSTART_OF_SCAN_LINE = iMinWordPos;
359 /** Increments the y co-ordinate of the current pixel position. */
360 EXPORT_C void TBitmapUtil::IncYPos()
362 iWordPos+=iScanlineWordLength;
363 if(iWordPos>=iMaxWordPos) iWordPos-=iMaxWordPos-iMinWordPos;
372 class TDitherColorError
375 inline TDitherColorError() {};
376 inline TDitherColorError(TInt aRed,TInt aGreen,TInt aBlue) : iRed(aRed), iGreen(aGreen), iBlue(aBlue) {}
383 NONSHARABLE_CLASS(CDitherColor256) : public CBase
386 void ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil = NULL);
388 void ConvertLine(TUint8* aDestination,TRgb* aSource);
391 const TColor256Util* iColorUtil;
393 TDitherColorError* iErrorBuffer;
394 TInt iErrorBufferLength;
397 CDitherColor256::~CDitherColor256()
399 delete[] iErrorBuffer;
402 void CDitherColor256::ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil)
404 if(iErrorBufferLength<=aLineWidth)
406 delete[] iErrorBuffer;
412 iErrorBuffer = new (ELeave) TDitherColorError[aLineWidth+1];
413 iErrorBufferLength = aLineWidth+1;
416 iLineWidth = aLineWidth;
418 aColorUtil = TColor256Util::Default();
419 iColorUtil = aColorUtil;
424 void CDitherColor256::Reset()
426 Mem::FillZ(iErrorBuffer,iErrorBufferLength*sizeof(iErrorBuffer[0]));
429 void CDitherColor256::ConvertLine(TUint8* aDestination,TRgb* aSource)
431 TUint8* dstLimit = aDestination+iLineWidth;
432 TDitherColorError* errorBuffer = iErrorBuffer;
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;
441 while(aDestination<dstLimit)
453 g += aSource->Green();
459 b += aSource->Blue();
467 value = iColorUtil->Color256(TRgb(value));
468 *(aDestination) = (TUint8)value;
469 value = iColorUtil->Color256(value).Value();
472 g -= (value>>8)&0xFF;
473 b -= (value>>16)&0xFF;
479 errorBuffer->iRed += r;
480 r += errorBuffer[1].iRed;
481 errorBuffer[1].iRed = x;
485 errorBuffer->iGreen += g;
486 g += errorBuffer[1].iGreen;
487 errorBuffer[1].iGreen = x;
491 errorBuffer->iBlue += b;
492 b += errorBuffer[1].iBlue;
493 errorBuffer[1].iBlue = x;
503 // CFbsColor256BitmapUtil
506 inline CFbsColor256BitmapUtil::CFbsColor256BitmapUtil()
509 /** Allocates and constructs a new 256 colour bitmap utility object, optionally
510 specifying a palette.
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
516 @return The newly constructed object. */
517 EXPORT_C CFbsColor256BitmapUtil* CFbsColor256BitmapUtil::NewL(const CPalette* aPalette)
519 CFbsColor256BitmapUtil* self = new (ELeave) CFbsColor256BitmapUtil;
520 CleanupStack::PushL(self);
523 self->iColor256Util = new (ELeave) TColor256Util;
524 self->iColor256Util->Construct(*aPalette);
526 // coverity[leave_without_push : FALSE]
527 // class member variables should not be pushed onto the cleanupstack
528 self->iDither = new (ELeave) CDitherColor256;
533 CFbsColor256BitmapUtil::~CFbsColor256BitmapUtil()
535 delete iColor256Util;
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
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,
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
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)
556 aSource->BeginDataAccess();
557 aColor256Destination->BeginDataAccess();
558 const TDisplayMode sourceMode = aSource->DisplayMode();
560 TSize size(aSource->SizeInPixels());
561 TInt width = size.iWidth;
562 TInt height = size.iHeight;
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);
568 if( sourceMode!=EColor256 && sourceMode!=EColor4K && sourceMode!=EColor64K &&
569 sourceMode!=EColor16M && sourceMode!=EColor16MU && sourceMode!=EColor16MA && sourceMode!=EColor16MAP)
571 aSource->EndDataAccess(ETrue);
572 aColor256Destination->EndDataAccess(ETrue);
573 return KErrNotSupported;
576 // get a TColor256Utils to use
577 const TColor256Util* colorUtil = iColor256Util;
579 colorUtil = TColor256Util::Default();
581 if(aDither==EFloydSteinberg)
583 TRAPD(err,iDither->ConstructL(width,colorUtil));
586 aSource->EndDataAccess(ETrue);
587 aColor256Destination->EndDataAccess(ETrue);
592 TRgb* pixelBuffer = new TRgb[width];
595 aSource->EndDataAccess(ETrue);
596 aColor256Destination->EndDataAccess(ETrue);
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);
611 for(i=0; i<width; i++)
612 pixelBuffer[i] = TRgb::Color256(((TUint8*)src)[i]);
615 for(i=0; i<width; i++)
616 pixelBuffer[i] = TRgb::_Color4K(((TUint16*)src)[i]);
619 for(i=0; i<width; i++)
620 pixelBuffer[i] = TRgb::_Color64K(((TUint16*)src)[i]);
625 TUint8* dataLimit = data+width*3;
627 while(data<dataLimit)
629 TUint32 value = *(data++)<<16;
630 value += *(data++)<<8;
632 pixelBuffer[i++] = TRgb(value);
638 TInt32* data = reinterpret_cast<TInt32*> (src);
639 TInt32* dataLimit = data+width;
641 while(data<dataLimit)
643 pixelBuffer[i++] = TRgb::_Color16MU(*data++);
649 TInt32* data = reinterpret_cast<TInt32*> (src);
650 TInt32* dataLimit = data+width;
652 while(data<dataLimit)
654 pixelBuffer[i++] = TRgb::_Color16MA(*data++);
660 // perform division of color channels by alpha.
661 TInt32* data = reinterpret_cast<TInt32*> (src);
662 TInt32* dataLimit = data+width;
663 while(data<dataLimit)
665 pixelBuffer[i++] = TRgb::_Color16MAP(*data++);
672 if(aDither==EFloydSteinberg)
673 iDither->ConvertLine(dst,pixelBuffer);
675 colorUtil->Color256(dst,pixelBuffer,width);
680 aSource->EndDataAccess(ETrue);
681 aColor256Destination->EndDataAccess(EFalse);
683 delete[] pixelBuffer;
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()
694 User::Panic(_L("Dummy Function"), 0);