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