|
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 <fbs.h> |
|
17 #include "ImageUtils.h" |
|
18 |
|
19 #include "BMPCodec.h" |
|
20 |
|
21 /** |
|
22 @file |
|
23 @internalComponent |
|
24 */ |
|
25 |
|
26 // CBmpReadCodec |
|
27 CBmpReadCodec::CBmpReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
28 iOriginalSize(aBmpSize), |
|
29 iPalette(aPalette) |
|
30 {} |
|
31 |
|
32 CBmpReadCodec::~CBmpReadCodec() |
|
33 { |
|
34 } |
|
35 |
|
36 |
|
37 |
|
38 TFrameState CBmpReadCodec::ProcessFrameL(TBufPtr8& aSrc) |
|
39 { |
|
40 const TUint8* srcStart = aSrc.Ptr(); |
|
41 iDataPtr = srcStart; |
|
42 iDataPtrLimit = srcStart + aSrc.Length(); |
|
43 |
|
44 DoProcessL(); |
|
45 |
|
46 TInt bytesUsed = iDataPtr - srcStart; |
|
47 aSrc.Shift(bytesUsed); |
|
48 iBytesProcessed += bytesUsed; |
|
49 if (iBytesProcessed >= iBytesExpected) |
|
50 { |
|
51 ImageProcessor()->FlushPixels(); |
|
52 return EFrameComplete; |
|
53 } |
|
54 |
|
55 return EFrameIncomplete; |
|
56 } |
|
57 |
|
58 void CBmpReadCodec::InitFrameL(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameImageData*/, TBool aDisableErrorDiffusion, CFbsBitmap& aDestination, CFbsBitmap* /*aDestinationMask*/) |
|
59 { |
|
60 iFrameSize = aFrameInfo.iFrameCoordsInPixels.Size(); |
|
61 Pos().iY = iOriginalSize.iHeight - 1; |
|
62 |
|
63 const TSize destinationSize(aDestination.SizeInPixels()); |
|
64 TInt reductionFactor = ReductionFactor(iOriginalSize, destinationSize); |
|
65 |
|
66 CImageProcessor* imageProc = ImageProcessorUtility::NewImageProcessorL(aDestination, reductionFactor, ERgb, aDisableErrorDiffusion); |
|
67 |
|
68 SetImageProcessor(imageProc); |
|
69 |
|
70 imageProc->PrepareL(aDestination, iOriginalSize); |
|
71 imageProc->SetPos(TPoint(0,iOriginalSize.iHeight - 1)); |
|
72 imageProc->SetYPosIncrement(-1); |
|
73 iBytesProcessed = 0; |
|
74 DoNewFrameL(); |
|
75 |
|
76 ClearBitmapL(aDestination, KRgbWhite); |
|
77 // clear full bitmap, in case of streaming partial decode |
|
78 } |
|
79 |
|
80 void CBmpReadCodec::InitFrameHeader(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameData*/) |
|
81 { |
|
82 ASSERT(aFrameInfo.CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised); |
|
83 iFrameInfo = &aFrameInfo; |
|
84 aFrameInfo.SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrameHeader); |
|
85 } |
|
86 |
|
87 TFrameState CBmpReadCodec::ProcessFrameHeaderL(TBufPtr8&/* aData*/) |
|
88 { |
|
89 ASSERT(iFrameInfo); |
|
90 iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete); |
|
91 return EFrameComplete; |
|
92 } |
|
93 |
|
94 void CBmpReadCodec::DoNewFrameL() |
|
95 {} |
|
96 |
|
97 |
|
98 // CBmp1BppReadCodec |
|
99 CBmp1BppReadCodec::CBmp1BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
100 CBmpReadCodec(aBmpSize, aPalette) |
|
101 { |
|
102 ASSERT(iPalette); |
|
103 } |
|
104 |
|
105 |
|
106 CBmp1BppReadCodec* CBmp1BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette) |
|
107 { |
|
108 CBmp1BppReadCodec* self = new(ELeave) CBmp1BppReadCodec(aBmpSize, aPalette); |
|
109 CleanupStack::PushL(self); |
|
110 self->ConstructL(); |
|
111 CleanupStack::Pop(self); // self |
|
112 return self; |
|
113 } |
|
114 |
|
115 void CBmp1BppReadCodec::DoProcessL() |
|
116 { |
|
117 CImageProcessor *const imageProc = ImageProcessor(); |
|
118 while (iDataPtr < iDataPtrLimit) |
|
119 { |
|
120 TUint8 value = *iDataPtr++; |
|
121 |
|
122 for(TUint8 pixelMask = 0x80; pixelMask!=0 ;pixelMask >>= 1) |
|
123 imageProc->SetPixel((value & pixelMask) ? iEntry1 : iEntry0); |
|
124 } |
|
125 } |
|
126 |
|
127 void CBmp1BppReadCodec::DoNewFrameL() |
|
128 { |
|
129 iEntry0 = iPalette[0]; |
|
130 iEntry1 = iPalette[1]; |
|
131 |
|
132 TInt actualWidth = (iOriginalSize.iWidth + 31) & ~31; |
|
133 ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth); |
|
134 iBytesExpected = (actualWidth >> 3) * iOriginalSize.iHeight; |
|
135 } |
|
136 |
|
137 |
|
138 // CBmpNoComp4BppReadCodec |
|
139 CBmpNoComp4BppReadCodec* CBmpNoComp4BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette) |
|
140 { |
|
141 CBmpNoComp4BppReadCodec* self = new(ELeave) CBmpNoComp4BppReadCodec(aBmpSize, aPalette); |
|
142 CleanupStack::PushL(self); |
|
143 self->ConstructL(); |
|
144 CleanupStack::Pop(self); |
|
145 return self; |
|
146 } |
|
147 |
|
148 CBmpNoComp4BppReadCodec::CBmpNoComp4BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
149 CBmpReadCodec(aBmpSize, aPalette) |
|
150 { |
|
151 ASSERT(iPalette); |
|
152 } |
|
153 |
|
154 void CBmpNoComp4BppReadCodec::DoNewFrameL() |
|
155 { |
|
156 TInt actualWidth = (iOriginalSize.iWidth + 7) & ~7; |
|
157 ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth); |
|
158 iBytesExpected = (actualWidth >> 1) * iOriginalSize.iHeight; |
|
159 } |
|
160 |
|
161 void CBmpNoComp4BppReadCodec::DoProcessL() |
|
162 { |
|
163 CImageProcessor *const imageProc = ImageProcessor(); |
|
164 while (iDataPtr < iDataPtrLimit) |
|
165 { |
|
166 TUint8 value = *iDataPtr++; |
|
167 imageProc->SetPixel(iPalette[value >> 4]); |
|
168 imageProc->SetPixel(iPalette[value & 0x0f]); |
|
169 } |
|
170 } |
|
171 |
|
172 |
|
173 // CBmpRLE4ReadCodec |
|
174 CBmpRLE4ReadCodec* CBmpRLE4ReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette) |
|
175 { |
|
176 CBmpRLE4ReadCodec* self = new(ELeave) CBmpRLE4ReadCodec(aBmpSize, aPalette); |
|
177 CleanupStack::PushL(self); |
|
178 self->ConstructL(); |
|
179 CleanupStack::Pop(self); |
|
180 return self; |
|
181 } |
|
182 |
|
183 CBmpRLE4ReadCodec::CBmpRLE4ReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
184 CBmpReadCodec(aBmpSize, aPalette) |
|
185 { |
|
186 ASSERT(iPalette); |
|
187 } |
|
188 |
|
189 void CBmpRLE4ReadCodec::DoNewFrameL() |
|
190 { |
|
191 iBytesExpected = KMaxTInt; |
|
192 } |
|
193 |
|
194 void CBmpRLE4ReadCodec::DoProcessL() |
|
195 { |
|
196 const TUint8* srcSafeLimit = iDataPtrLimit - 1; |
|
197 |
|
198 TPoint& pos = Pos(); |
|
199 CImageProcessor*const imageProc = ImageProcessor(); |
|
200 |
|
201 while (iDataPtr < srcSafeLimit || pos.iY < 0) |
|
202 { |
|
203 TUint8 index = *iDataPtr++; |
|
204 if (index > 0) // Encoded mode |
|
205 WriteRun(*iDataPtr++,index); |
|
206 else |
|
207 { |
|
208 index = *iDataPtr++; |
|
209 if (index > 2) // Absolute mode |
|
210 { |
|
211 TInt byteCount = (index + ((index & 1) ? 1 : 0)) >> 1; |
|
212 TInt padding = (byteCount & 1) ? 1 : 0; |
|
213 if ((iDataPtr + (byteCount + padding)) > iDataPtrLimit) |
|
214 { |
|
215 iDataPtr -= 2; |
|
216 break; |
|
217 } |
|
218 WriteData(index); |
|
219 if (padding) |
|
220 iDataPtr++; |
|
221 } |
|
222 else if (index == 0) // End of line |
|
223 { |
|
224 pos.iX = 0; |
|
225 pos.iY--; |
|
226 if (!imageProc->SetPos(pos)) |
|
227 { |
|
228 iBytesExpected = 0; |
|
229 break; |
|
230 } |
|
231 } |
|
232 else if (index == 1) // End of bitmap |
|
233 { |
|
234 iBytesExpected = 0; |
|
235 Pos().iY = -1; |
|
236 break; |
|
237 } |
|
238 else // Delta |
|
239 { |
|
240 if ((iDataPtr + 2) > iDataPtrLimit) |
|
241 { |
|
242 iDataPtr -= 2; |
|
243 break; |
|
244 } |
|
245 imageProc->FlushPixels(); |
|
246 pos.iX += *iDataPtr++; |
|
247 pos.iY -= *iDataPtr++; |
|
248 if (!imageProc->SetPos(pos)) |
|
249 break; |
|
250 } |
|
251 } |
|
252 } |
|
253 if (pos.iY < 0) |
|
254 { |
|
255 // that may mean a dodgy image, so flag decoding immediately complete |
|
256 iBytesExpected = 0; |
|
257 } |
|
258 } |
|
259 |
|
260 void CBmpRLE4ReadCodec::WriteRun(TUint8 aValue, TInt aNumPixels) |
|
261 { |
|
262 CImageProcessor*const imageProc = ImageProcessor(); |
|
263 Pos().iX += aNumPixels; |
|
264 TRgb highValue = iPalette[aValue >> 4]; |
|
265 TRgb lowValue = iPalette[aValue & 0x0f]; |
|
266 TInt numPixels; |
|
267 for (numPixels = aNumPixels; numPixels > 1; numPixels -= 2) |
|
268 { |
|
269 imageProc->SetPixel(highValue); |
|
270 imageProc->SetPixel(lowValue); |
|
271 } |
|
272 if (numPixels & 1) |
|
273 imageProc->SetPixel(highValue); |
|
274 } |
|
275 |
|
276 void CBmpRLE4ReadCodec::WriteData(TInt aNumPixels) |
|
277 { |
|
278 CImageProcessor*const imageProc = ImageProcessor(); |
|
279 const TUint8* dataPtrLimit = iDataPtr + (aNumPixels >> 1); |
|
280 while (iDataPtr < dataPtrLimit) |
|
281 { |
|
282 TUint8 value = *iDataPtr++; |
|
283 imageProc->SetPixel(iPalette[value >> 4]); |
|
284 imageProc->SetPixel(iPalette[value & 0x0f]); |
|
285 } |
|
286 if (aNumPixels & 1) |
|
287 { |
|
288 TUint8 value = *iDataPtr++; |
|
289 imageProc->SetPixel(iPalette[value >> 4]); |
|
290 } |
|
291 Pos().iX += aNumPixels; |
|
292 } |
|
293 |
|
294 |
|
295 // CBmpNoComp8BppReadCodec |
|
296 CBmpNoComp8BppReadCodec* CBmpNoComp8BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette) |
|
297 { |
|
298 CBmpNoComp8BppReadCodec* self = new(ELeave) CBmpNoComp8BppReadCodec(aBmpSize, aPalette); |
|
299 CleanupStack::PushL(self); |
|
300 self->ConstructL(); |
|
301 CleanupStack::Pop(self); |
|
302 return self; |
|
303 } |
|
304 |
|
305 CBmpNoComp8BppReadCodec::CBmpNoComp8BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
306 CBmpReadCodec(aBmpSize, aPalette) |
|
307 { |
|
308 ASSERT(iPalette); |
|
309 } |
|
310 |
|
311 void CBmpNoComp8BppReadCodec::DoNewFrameL() |
|
312 { |
|
313 TInt actualWidth = (iOriginalSize.iWidth + 3) & ~3; |
|
314 ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth); |
|
315 iBytesExpected = actualWidth * iOriginalSize.iHeight; |
|
316 } |
|
317 |
|
318 void CBmpNoComp8BppReadCodec::DoProcessL() |
|
319 { |
|
320 CImageProcessor*const imageProc = ImageProcessor(); |
|
321 while (iDataPtr < iDataPtrLimit) |
|
322 imageProc->SetPixel(iPalette[*iDataPtr++]); |
|
323 } |
|
324 |
|
325 |
|
326 // CBmpRLE8ReadCodec |
|
327 CBmpRLE8ReadCodec* CBmpRLE8ReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette) |
|
328 { |
|
329 CBmpRLE8ReadCodec* self = new(ELeave) CBmpRLE8ReadCodec(aBmpSize, aPalette); |
|
330 CleanupStack::PushL(self); |
|
331 self->ConstructL(); |
|
332 CleanupStack::Pop(self); |
|
333 return self; |
|
334 } |
|
335 |
|
336 CBmpRLE8ReadCodec::CBmpRLE8ReadCodec(const TSize& aBmpSize, const TRgb* aPalette): |
|
337 CBmpReadCodec(aBmpSize, aPalette) |
|
338 { |
|
339 ASSERT(iPalette); |
|
340 } |
|
341 |
|
342 void CBmpRLE8ReadCodec::DoNewFrameL() |
|
343 { |
|
344 iBytesExpected = KMaxTInt; |
|
345 } |
|
346 |
|
347 void CBmpRLE8ReadCodec::DoProcessL() |
|
348 { |
|
349 const TUint8* srcSafeLimit = iDataPtrLimit - 1; |
|
350 |
|
351 TPoint& pos = Pos(); |
|
352 CImageProcessor*const imageProc = ImageProcessor(); |
|
353 |
|
354 while (iDataPtr < srcSafeLimit || pos.iY < 0) |
|
355 { |
|
356 TUint8 index = *iDataPtr++; |
|
357 if (index > 0) // Encoded mode |
|
358 WriteRun(*iDataPtr++,index); |
|
359 else |
|
360 { |
|
361 index = *iDataPtr++; |
|
362 if (index > 2) // Absolute mode |
|
363 { |
|
364 TInt padding = (index & 1) ? 1 : 0; |
|
365 if ((iDataPtr + (index + padding)) > iDataPtrLimit) |
|
366 { |
|
367 iDataPtr -= 2; |
|
368 break; |
|
369 } |
|
370 WriteData(index); |
|
371 if (padding) |
|
372 iDataPtr++; |
|
373 } |
|
374 else if (index == 0) // End of line |
|
375 { |
|
376 pos.iX = 0; |
|
377 pos.iY--; |
|
378 if (!imageProc->SetPos(pos)) |
|
379 { |
|
380 iBytesExpected = 0; |
|
381 break; |
|
382 } |
|
383 } |
|
384 else if (index == 1) // End of bitmap |
|
385 { |
|
386 iBytesExpected = 0; |
|
387 Pos().iY = -1; |
|
388 break; |
|
389 } |
|
390 else // Delta |
|
391 { |
|
392 if ((iDataPtr + 2) > iDataPtrLimit) |
|
393 { |
|
394 iDataPtr -= 2; |
|
395 break; |
|
396 } |
|
397 imageProc->FlushPixels(); |
|
398 pos.iX += *iDataPtr++; |
|
399 pos.iY -= *iDataPtr++; |
|
400 if (!imageProc->SetPos(pos)) |
|
401 break; |
|
402 } |
|
403 } |
|
404 } |
|
405 |
|
406 if (pos.iY < 0) |
|
407 { |
|
408 // that may indicate a dodgy image, so flag decoding complete |
|
409 iBytesExpected = 0; |
|
410 } |
|
411 } |
|
412 |
|
413 void CBmpRLE8ReadCodec::WriteRun(TUint8 aValue, TInt aNumPixels) |
|
414 { |
|
415 CImageProcessor*const imageProc = ImageProcessor(); |
|
416 Pos().iX += aNumPixels; |
|
417 TRgb value = iPalette[aValue]; |
|
418 for (; aNumPixels > 0; aNumPixels--) |
|
419 imageProc->SetPixel(value); |
|
420 } |
|
421 |
|
422 void CBmpRLE8ReadCodec::WriteData(TInt aNumPixels) |
|
423 { |
|
424 CImageProcessor*const imageProc = ImageProcessor(); |
|
425 Pos().iX += aNumPixels; |
|
426 const TUint8* dataPtrLimit = iDataPtr + aNumPixels; |
|
427 while (iDataPtr < dataPtrLimit) |
|
428 imageProc->SetPixel(iPalette[*iDataPtr++]); |
|
429 } |
|
430 |
|
431 /*static*/ |
|
432 CBmpBiRgbReadCodec* CBmpBiRgbReadCodec::NewL(const TSize& aBmpSize, TInt aPixelSize, const TRgb* aPalette) |
|
433 { |
|
434 CBmpBiRgbReadCodec* self = new(ELeave) CBmpBiRgbReadCodec(aBmpSize, aPixelSize, aPalette); |
|
435 CleanupStack::PushL(self); |
|
436 self->ConstructL(); |
|
437 CleanupStack::Pop(self); |
|
438 return self; |
|
439 } |
|
440 |
|
441 CBmpBiRgbReadCodec::CBmpBiRgbReadCodec(const TSize& aBmpSize, TInt aPixelSize, const TRgb* aPalette): |
|
442 CBmpReadCodec(aBmpSize, aPalette), |
|
443 iPixelSize(aPixelSize) |
|
444 { |
|
445 } |
|
446 /** |
|
447 calculate: |
|
448 1. mask used to extract channel value |
|
449 2. right shift value used to place channel value into "low" byte |
|
450 3. left shift value used to scale up channel if it has got less than 8 bits |
|
451 */ |
|
452 void CBmpBiRgbReadCodec::ConstructL() |
|
453 { |
|
454 // 16 Bpp 5-5-5 bitmaps do not have masks defined |
|
455 // as they are "standard", so use predefined ones |
|
456 static const TUint32 KDefault555Masks[]= |
|
457 { |
|
458 0x7C00u, //red |
|
459 0x03E0u, //green |
|
460 0x001Fu //blue |
|
461 }; |
|
462 |
|
463 CBmpReadCodec::ConstructL(); |
|
464 |
|
465 const TRgb* const masks= iPalette ? iPalette : reinterpret_cast<const TRgb*>(KDefault555Masks); |
|
466 |
|
467 for (TInt comp=0; comp<=KBlueCompIdx; comp++) |
|
468 { |
|
469 iCompInfo[comp].iMask = 0x00FFFFFF & masks[comp].Internal(); // ignore the alpha channel |
|
470 TInt shiftVal=0; |
|
471 const TUint maskValue=iCompInfo[comp].iMask; |
|
472 while (shiftVal < sizeof(TUint32) * 8 && ((maskValue >> shiftVal) &1 )==0) |
|
473 { |
|
474 ++shiftVal; |
|
475 } |
|
476 iCompInfo[comp].iRightShiftValue = shiftVal; |
|
477 while (shiftVal < sizeof(TUint32) * 8 && ((maskValue >> shiftVal) &1) !=0 ) |
|
478 { |
|
479 ++shiftVal; |
|
480 } |
|
481 iCompInfo[comp].iLeftShiftValue = 8 - (shiftVal - iCompInfo[comp].iRightShiftValue); |
|
482 if (iCompInfo[comp].iLeftShiftValue < 0) |
|
483 { |
|
484 // We've got image with bad mask |
|
485 User::Leave(KErrCorrupt); |
|
486 } |
|
487 } |
|
488 } |
|
489 |
|
490 void CBmpBiRgbReadCodec::DoProcessL() |
|
491 { |
|
492 TInt bytesRemaining = iDataPtrLimit - iDataPtr; |
|
493 CImageProcessor* const imageProc = ImageProcessor(); |
|
494 while (bytesRemaining >= iPixelSize) |
|
495 { |
|
496 TInt bytesToWrite = iPixelByteWidth - iBytePos; |
|
497 if (bytesToWrite > 0) |
|
498 { |
|
499 TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / iPixelSize; |
|
500 const TInt bytesWritten = pixelsToWrite * iPixelSize; |
|
501 const TUint8* const tempDataPtrLimit = iDataPtr + bytesWritten; |
|
502 bytesRemaining -= bytesWritten; |
|
503 iBytePos += bytesWritten; |
|
504 while (iDataPtr < tempDataPtrLimit) |
|
505 { |
|
506 TUint pixelValue; |
|
507 switch (iPixelSize) |
|
508 { |
|
509 case sizeof(TUint16): |
|
510 pixelValue=PtrReadUtil::ReadUint16(iDataPtr); |
|
511 break; |
|
512 |
|
513 case sizeof(TUint16) + sizeof(TUint8): |
|
514 pixelValue=PtrReadUtil::ReadUint16(iDataPtr) | (iDataPtr[2] << 16); |
|
515 break; |
|
516 |
|
517 case sizeof(TUint32): |
|
518 pixelValue=PtrReadUtil::ReadUint32(iDataPtr); |
|
519 break; |
|
520 |
|
521 default: |
|
522 ASSERT(EFalse); |
|
523 pixelValue = 0; |
|
524 } |
|
525 TInt red=((pixelValue & iCompInfo[KRedCompIdx].iMask) >> iCompInfo[KRedCompIdx].iRightShiftValue) << iCompInfo[KRedCompIdx].iLeftShiftValue; |
|
526 red |=red >> (8 - iCompInfo[KRedCompIdx].iLeftShiftValue); |
|
527 |
|
528 TInt green = ((pixelValue & iCompInfo[KGreenCompIdx].iMask) >> iCompInfo[KGreenCompIdx].iRightShiftValue) << iCompInfo[KGreenCompIdx].iLeftShiftValue; |
|
529 green |= green >> (8 - iCompInfo[KGreenCompIdx].iLeftShiftValue); |
|
530 |
|
531 TInt blue = ((pixelValue & iCompInfo[KBlueCompIdx].iMask) >> iCompInfo[KBlueCompIdx].iRightShiftValue) << iCompInfo[KBlueCompIdx].iLeftShiftValue; |
|
532 blue |= blue >> (8 - iCompInfo[KBlueCompIdx].iLeftShiftValue); |
|
533 |
|
534 imageProc->SetPixel( TRgb(red, green, blue) ); |
|
535 iDataPtr += iPixelSize; |
|
536 } |
|
537 } |
|
538 |
|
539 if (iBytePos >= iPixelByteWidth) |
|
540 { |
|
541 const TInt KBytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos); |
|
542 bytesRemaining -= KBytesToSkip; |
|
543 iBytePos += KBytesToSkip; |
|
544 iDataPtr += KBytesToSkip; |
|
545 } |
|
546 |
|
547 if (iBytePos >= iTotalByteWidth) |
|
548 { |
|
549 iBytePos = 0; |
|
550 } |
|
551 } |
|
552 } |
|
553 |
|
554 void CBmpBiRgbReadCodec::DoNewFrameL() |
|
555 { |
|
556 if (iPixelSize < 4) |
|
557 { |
|
558 iTotalByteWidth = ((iOriginalSize.iWidth * iPixelSize) + iPixelSize) & ~iPixelSize; |
|
559 } |
|
560 else |
|
561 { |
|
562 iTotalByteWidth = (iOriginalSize.iWidth * iPixelSize); |
|
563 } |
|
564 |
|
565 iPixelByteWidth = (iOriginalSize.iWidth * iPixelSize); |
|
566 iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth; |
|
567 iBytePos = 0; |
|
568 iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight; |
|
569 } |
|
570 |
|
571 // CBmp24BppReadCodec |
|
572 CBmp24BppReadCodec* CBmp24BppReadCodec::NewL(const TSize& aBmpSize) |
|
573 { |
|
574 CBmp24BppReadCodec* self = new(ELeave) CBmp24BppReadCodec(aBmpSize); |
|
575 CleanupStack::PushL(self); |
|
576 self->ConstructL(); |
|
577 CleanupStack::Pop(self); |
|
578 return self; |
|
579 } |
|
580 |
|
581 CBmp24BppReadCodec::CBmp24BppReadCodec(const TSize& aBmpSize) |
|
582 : CBmpReadCodec(aBmpSize, NULL) |
|
583 {} |
|
584 |
|
585 void CBmp24BppReadCodec::DoProcessL() |
|
586 { |
|
587 TInt bytesRemaining = iDataPtrLimit - iDataPtr; |
|
588 CImageProcessor*const imageProc = ImageProcessor(); |
|
589 while (bytesRemaining > 2) |
|
590 { |
|
591 TInt bytesToWrite = iPixelByteWidth - iBytePos; |
|
592 if (bytesToWrite > 0) |
|
593 { |
|
594 TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / 3; |
|
595 TInt bytesWritten = pixelsToWrite * 3; |
|
596 const TUint8* tempDataPtrLimit = iDataPtr + bytesWritten; |
|
597 bytesRemaining -= bytesWritten; |
|
598 iBytePos += bytesWritten; |
|
599 while (iDataPtr < tempDataPtrLimit) |
|
600 { |
|
601 imageProc->SetPixel(TRgb(iDataPtr[2], iDataPtr[1], iDataPtr[0])); |
|
602 iDataPtr += 3; |
|
603 } |
|
604 } |
|
605 |
|
606 if (iBytePos >= iPixelByteWidth) |
|
607 { |
|
608 TInt bytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos); |
|
609 bytesRemaining -= bytesToSkip; |
|
610 iBytePos += bytesToSkip; |
|
611 iDataPtr += bytesToSkip; |
|
612 } |
|
613 |
|
614 if (iBytePos >= iTotalByteWidth) |
|
615 iBytePos = 0; |
|
616 } |
|
617 } |
|
618 |
|
619 void CBmp24BppReadCodec::DoNewFrameL() |
|
620 { |
|
621 iTotalByteWidth = ((iOriginalSize.iWidth * 3) + 3) & ~3; |
|
622 iPixelByteWidth = (iOriginalSize.iWidth * 3); |
|
623 iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth; |
|
624 iBytePos = 0; |
|
625 iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight; |
|
626 } |
|
627 |
|
628 // CBmp32BppReadCodec |
|
629 CBmp32BppReadCodec* CBmp32BppReadCodec::NewL(const TSize& aBmpSize) |
|
630 { |
|
631 CBmp32BppReadCodec* self = new(ELeave) CBmp32BppReadCodec(aBmpSize); |
|
632 CleanupStack::PushL(self); |
|
633 self->ConstructL(); |
|
634 CleanupStack::Pop(self); |
|
635 return self; |
|
636 } |
|
637 |
|
638 CBmp32BppReadCodec::CBmp32BppReadCodec(const TSize& aBmpSize) |
|
639 : CBmpReadCodec(aBmpSize, NULL) |
|
640 {} |
|
641 |
|
642 void CBmp32BppReadCodec::DoProcessL() |
|
643 { |
|
644 TInt bytesRemaining = iDataPtrLimit - iDataPtr; |
|
645 CImageProcessor*const imageProc = ImageProcessor(); |
|
646 while (bytesRemaining > 3) |
|
647 { |
|
648 TInt bytesToWrite = iPixelByteWidth - iBytePos; |
|
649 if (bytesToWrite > 0) |
|
650 { |
|
651 TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / 4; |
|
652 TInt bytesWritten = pixelsToWrite * 4; |
|
653 const TUint8* tempDataPtrLimit = iDataPtr + bytesWritten; |
|
654 bytesRemaining -= bytesWritten; |
|
655 iBytePos += bytesWritten; |
|
656 while (iDataPtr < tempDataPtrLimit) |
|
657 { |
|
658 imageProc->SetPixel(TRgb(iDataPtr[2], iDataPtr[1], iDataPtr[0])); |
|
659 iDataPtr += 4; |
|
660 } |
|
661 } |
|
662 |
|
663 if (iBytePos >= iPixelByteWidth) |
|
664 { |
|
665 TInt bytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos); |
|
666 bytesRemaining -= bytesToSkip; |
|
667 iBytePos += bytesToSkip; |
|
668 iDataPtr += bytesToSkip; |
|
669 } |
|
670 |
|
671 if (iBytePos >= iTotalByteWidth) |
|
672 iBytePos = 0; |
|
673 } |
|
674 } |
|
675 |
|
676 void CBmp32BppReadCodec::DoNewFrameL() |
|
677 { |
|
678 iTotalByteWidth = iOriginalSize.iWidth * 4; |
|
679 iPixelByteWidth = iTotalByteWidth; |
|
680 iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth; |
|
681 iBytePos = 0; |
|
682 iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight; |
|
683 } |
|
684 |
|
685 // CBmpWriteCodec |
|
686 void CBmpWriteCodec::InitFrameL(TBufPtr8& aDst, const CFbsBitmap& aSource) |
|
687 { |
|
688 SetSource(&aSource); |
|
689 iSourceRect = TRect(aSource.SizeInPixels()); |
|
690 iPos.SetXY(0,0); |
|
691 iPos.iY = iSourceRect.iBr.iY - 1; |
|
692 iPaddingBytes = PaddingBytes(); |
|
693 iBytesToWrite = 0; |
|
694 aDst.SetLength(0); //No frame header |
|
695 } |
|
696 |
|
697 TFrameState CBmpWriteCodec::ProcessFrameL(TBufPtr8& aDst) |
|
698 { |
|
699 //Setup buffer to use all available space |
|
700 TUint8* destStartPtr = CONST_CAST(TUint8*,aDst.Ptr()); |
|
701 iDestPtr = destStartPtr; |
|
702 iDestPtrLimit = iDestPtr + aDst.MaxLength(); |
|
703 |
|
704 DoProcessL(*Source()); |
|
705 |
|
706 aDst.SetLength(iDestPtr - destStartPtr); |
|
707 |
|
708 // If processed all pixels |
|
709 if (iPos.iY < iSourceRect.iTl.iY) |
|
710 return EFrameComplete; |
|
711 |
|
712 return EFrameIncomplete; |
|
713 } |
|
714 |
|
715 |
|
716 // CBmp1BppWriteCodec |
|
717 CBmp1BppWriteCodec* CBmp1BppWriteCodec::NewL(void) |
|
718 { |
|
719 CBmp1BppWriteCodec* self = new(ELeave) CBmp1BppWriteCodec(); |
|
720 CleanupStack::PushL(self); |
|
721 self->ConstructL(); |
|
722 CleanupStack::Pop(self); |
|
723 return self; |
|
724 } |
|
725 |
|
726 TInt CBmp1BppWriteCodec::PaddingBytes() |
|
727 { |
|
728 TInt byteWidth = (iSourceRect.Size().iWidth + 7) / 8; |
|
729 return ((byteWidth + 3) & ~3) - byteWidth; |
|
730 } |
|
731 |
|
732 void CBmp1BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame) |
|
733 { |
|
734 while (iDestPtr < iDestPtrLimit) |
|
735 { |
|
736 for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--) |
|
737 *iDestPtr++ = 0; |
|
738 |
|
739 if (iPos.iY < 0) |
|
740 break; |
|
741 |
|
742 TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) * 8); |
|
743 TInt dstLength = (scanLength + 7) / 8; |
|
744 TPtr8 dstBuf(iDestPtr,dstLength,dstLength); |
|
745 |
|
746 aFrame.GetScanLine(dstBuf, iPos, scanLength, EGray2); |
|
747 |
|
748 iPos.iX += scanLength; |
|
749 TUint8* tempDestPtrLimit = iDestPtr + dstLength; |
|
750 while (iDestPtr < tempDestPtrLimit) |
|
751 { |
|
752 TUint8 tempVal = iDestPtr[0]; |
|
753 TUint reverseVal = 0; |
|
754 TUint origValCopy = tempVal; |
|
755 for(TInt countBit = 0; countBit<8; countBit++) |
|
756 { |
|
757 reverseVal<<=1; |
|
758 reverseVal |= origValCopy & 1; |
|
759 origValCopy>>=1; |
|
760 } |
|
761 iDestPtr[0] = TUint8(reverseVal); |
|
762 iDestPtr++; |
|
763 } |
|
764 |
|
765 if (iPos.iX == iSourceRect.iBr.iX) |
|
766 { |
|
767 iPos.iX = iSourceRect.iTl.iX; |
|
768 iPos.iY--; |
|
769 iBytesToWrite = iPaddingBytes; |
|
770 } |
|
771 } |
|
772 } |
|
773 |
|
774 |
|
775 // CBmp4BppWriteCodec |
|
776 CBmp4BppWriteCodec* CBmp4BppWriteCodec::NewL(void) |
|
777 { |
|
778 CBmp4BppWriteCodec* self = new(ELeave) CBmp4BppWriteCodec(); |
|
779 CleanupStack::PushL(self); |
|
780 self->ConstructL(); |
|
781 CleanupStack::Pop(self); |
|
782 return self; |
|
783 } |
|
784 |
|
785 TInt CBmp4BppWriteCodec::PaddingBytes() |
|
786 { |
|
787 TInt byteWidth = (iSourceRect.Size().iWidth + 1) / 2; |
|
788 return ((byteWidth + 3) & ~3) - byteWidth; |
|
789 } |
|
790 |
|
791 void CBmp4BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame) |
|
792 { |
|
793 while (iDestPtr < iDestPtrLimit) |
|
794 { |
|
795 for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--) |
|
796 *iDestPtr++ = 0; |
|
797 |
|
798 if (iPos.iY < 0) |
|
799 break; |
|
800 |
|
801 TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) * 2); |
|
802 TInt dstLength = (scanLength + 1) / 2; |
|
803 TPtr8 dstBuf(iDestPtr,dstLength,dstLength); |
|
804 |
|
805 aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor16); |
|
806 |
|
807 iPos.iX += scanLength; |
|
808 TUint8* tempDestPtrLimit = iDestPtr + dstLength; |
|
809 while (iDestPtr < tempDestPtrLimit) |
|
810 { |
|
811 TInt tempVal = iDestPtr[0]; |
|
812 TInt lowNibble = tempVal << 4; |
|
813 TInt highNibble = tempVal >> 4; |
|
814 iDestPtr[0] = TUint8(lowNibble | highNibble); |
|
815 iDestPtr++; |
|
816 } |
|
817 |
|
818 if (iPos.iX == iSourceRect.iBr.iX) |
|
819 { |
|
820 iPos.iX = iSourceRect.iTl.iX; |
|
821 iPos.iY--; |
|
822 iBytesToWrite = iPaddingBytes; |
|
823 } |
|
824 } |
|
825 } |
|
826 |
|
827 |
|
828 // CBmp8BppWriteCodec |
|
829 CBmp8BppWriteCodec* CBmp8BppWriteCodec::NewL(void) |
|
830 { |
|
831 CBmp8BppWriteCodec* self = new(ELeave) CBmp8BppWriteCodec(); |
|
832 CleanupStack::PushL(self); |
|
833 self->ConstructL(); |
|
834 CleanupStack::Pop(self); |
|
835 return self; |
|
836 } |
|
837 |
|
838 TInt CBmp8BppWriteCodec::PaddingBytes() |
|
839 { |
|
840 TInt byteWidth = iSourceRect.Size().iWidth; |
|
841 return ((byteWidth + 3) & ~3) - byteWidth; |
|
842 } |
|
843 |
|
844 void CBmp8BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame) |
|
845 { |
|
846 while (iDestPtr < iDestPtrLimit) |
|
847 { |
|
848 for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--) |
|
849 *iDestPtr++ = 0; |
|
850 |
|
851 if (iPos.iY < 0) |
|
852 break; |
|
853 |
|
854 TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, iDestPtrLimit - iDestPtr); |
|
855 TPtr8 dstBuf(iDestPtr, scanLength, scanLength); |
|
856 |
|
857 aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor256); |
|
858 |
|
859 iPos.iX += scanLength; |
|
860 iDestPtr += scanLength; |
|
861 |
|
862 if (iPos.iX == iSourceRect.iBr.iX) |
|
863 { |
|
864 iPos.iX = iSourceRect.iTl.iX; |
|
865 iPos.iY--; |
|
866 iBytesToWrite = iPaddingBytes; |
|
867 } |
|
868 } |
|
869 } |
|
870 |
|
871 |
|
872 // CBmp24BppWriteCodec |
|
873 CBmp24BppWriteCodec* CBmp24BppWriteCodec::NewL(void) |
|
874 { |
|
875 CBmp24BppWriteCodec* self = new(ELeave) CBmp24BppWriteCodec(); |
|
876 CleanupStack::PushL(self); |
|
877 self->ConstructL(); |
|
878 CleanupStack::Pop(self); |
|
879 return self; |
|
880 } |
|
881 |
|
882 TInt CBmp24BppWriteCodec::PaddingBytes() |
|
883 { |
|
884 TInt byteWidth = iSourceRect.Size().iWidth * 3; |
|
885 return ((byteWidth + 3) & ~3) - byteWidth; |
|
886 } |
|
887 |
|
888 void CBmp24BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame) |
|
889 { |
|
890 TUint8* safeDestPtrLimit = iDestPtrLimit - 2; |
|
891 |
|
892 while (iDestPtr < safeDestPtrLimit) |
|
893 { |
|
894 for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--) |
|
895 *iDestPtr++ = 0; |
|
896 |
|
897 if (iPos.iY < 0) |
|
898 break; |
|
899 |
|
900 TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) / 3); |
|
901 TInt dstLength = scanLength * 3; |
|
902 TPtr8 dstBuf(iDestPtr, dstLength, dstLength); |
|
903 |
|
904 aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor16M); |
|
905 |
|
906 iPos.iX += scanLength; |
|
907 iDestPtr += dstLength; |
|
908 |
|
909 if (iPos.iX == iSourceRect.iBr.iX) |
|
910 { |
|
911 iPos.iX = iSourceRect.iTl.iX; |
|
912 iPos.iY--; |
|
913 iBytesToWrite = iPaddingBytes; |
|
914 } |
|
915 } |
|
916 } |
|
917 |