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