00001 // PNGSCANLINEDECODER.CPP 00002 // 00003 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 00004 // All rights reserved. 00005 // This component and the accompanying materials are made available 00006 // under the terms of "Eclipse Public License v1.0" 00007 // which accompanies this distribution, and is available 00008 // at the URL "http://www.eclipse.org/legal/epl-v10.html". 00009 // 00010 // Initial Contributors: 00011 // Nokia Corporation - initial contribution. 00012 // 00013 // Contributors: 00014 // 00015 // Description: 00016 // 00017 // 00018 00019 #include "PNGCodec.h" 00020 00021 const TInt KPngScanlineFilterTypeLength = 1; 00022 00023 const TInt KColStart[KPngNumInterlacedPasses] = { 0, 4, 0, 2, 0, 1, 0, 0 }; 00024 const TInt KRowStart[KPngNumInterlacedPasses] = { 0, 0, 4, 0, 2, 0, 1, 0 }; 00025 const TInt KColIncrement[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 }; 00026 const TInt KRowIncrement[KPngNumInterlacedPasses] = { 8, 8, 8, 4, 4, 2, 2, 0 }; 00027 const TInt KBlockWidth[KPngNumInterlacedPasses] = { 8, 4, 4, 2, 2, 1, 1, 0 }; 00028 const TInt KBlockHeight[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 }; 00029 00030 // 00031 // These classes specialise the PNG reader to read 00032 // scanlines with different bitmap depths/colour types 00033 // 00034 00035 class CBitDepth1Decoder : public CPngReadSubCodec 00036 { 00037 private: 00038 virtual void DoConstructL(); 00039 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00040 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00041 }; 00042 00043 class CBitDepth2Decoder : public CPngReadSubCodec 00044 { 00045 private: 00046 virtual void DoConstructL(); 00047 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00048 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00049 }; 00050 00051 class CBitDepth4Decoder : public CPngReadSubCodec 00052 { 00053 private: 00054 virtual void DoConstructL(); 00055 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00056 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00057 }; 00058 00059 class CBitDepth8Decoder : public CPngReadSubCodec 00060 { 00061 private: 00062 virtual void DoConstructL(); 00063 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00064 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00065 }; 00066 00067 class CBitDepth8ColorType2Decoder : public CPngReadSubCodec 00068 { 00069 private: 00070 virtual void DoConstructL(); 00071 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00072 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00073 }; 00074 00075 class CBitDepth8ColorType4Decoder : public CPngReadSubCodec 00076 { 00077 private: 00078 virtual void DoConstructL(); 00079 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00080 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00081 }; 00082 00083 class CBitDepth8ColorType6Decoder : public CPngReadSubCodec 00084 { 00085 private: 00086 virtual void DoConstructL(); 00087 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00088 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00089 }; 00090 00091 class CBitDepth16ColorType0Decoder : public CPngReadSubCodec 00092 { 00093 private: 00094 virtual void DoConstructL(); 00095 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00096 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00097 }; 00098 00099 class CBitDepth16ColorType2Decoder : public CPngReadSubCodec 00100 { 00101 private: 00102 virtual void DoConstructL(); 00103 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00104 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00105 }; 00106 00107 class CBitDepth16ColorType4Decoder : public CPngReadSubCodec 00108 { 00109 private: 00110 virtual void DoConstructL(); 00111 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00112 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00113 }; 00114 00115 class CBitDepth16ColorType6Decoder : public CPngReadSubCodec 00116 { 00117 private: 00118 virtual void DoConstructL(); 00119 virtual TInt ScanlineBufferSize(TInt aPixelLength); 00120 virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit); 00121 }; 00122 00123 // 00124 // CPngReadSubCodec: base class for classes that read scanlines 00125 // 00126 00127 // Factory function 00128 CPngReadSubCodec* CPngReadSubCodec::NewL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo) 00129 { 00130 CPngReadSubCodec* self = NULL; 00131 00132 switch (aInfo.iBitDepth) 00133 { 00134 case 1: 00135 self = new(ELeave) CBitDepth1Decoder; 00136 break; 00137 case 2: 00138 self = new(ELeave) CBitDepth2Decoder; 00139 break; 00140 case 4: 00141 self = new(ELeave) CBitDepth4Decoder; 00142 break; 00143 case 8: 00144 switch (aInfo.iColorType) 00145 { 00146 case TPngImageInformation::EGrayscale: 00147 case TPngImageInformation::EIndexedColor: 00148 self = new(ELeave) CBitDepth8Decoder; 00149 break; 00150 case TPngImageInformation::EDirectColor: 00151 self = new(ELeave) CBitDepth8ColorType2Decoder; 00152 break; 00153 case TPngImageInformation::EAlphaGrayscale: 00154 self = new(ELeave) CBitDepth8ColorType4Decoder; 00155 break; 00156 case TPngImageInformation::EAlphaDirectColor: 00157 self = new(ELeave) CBitDepth8ColorType6Decoder; 00158 break; 00159 default: 00160 User::Leave(KErrNotSupported); 00161 break; 00162 } 00163 break; 00164 case 16: 00165 switch (aInfo.iColorType) 00166 { 00167 case TPngImageInformation::EGrayscale: 00168 self = new(ELeave) CBitDepth16ColorType0Decoder; 00169 break; 00170 case TPngImageInformation::EDirectColor: 00171 self = new(ELeave) CBitDepth16ColorType2Decoder; 00172 break; 00173 case TPngImageInformation::EAlphaGrayscale: 00174 self = new(ELeave) CBitDepth16ColorType4Decoder; 00175 break; 00176 case TPngImageInformation::EAlphaDirectColor: 00177 self = new(ELeave) CBitDepth16ColorType6Decoder; 00178 break; 00179 case TPngImageInformation::EIndexedColor: 00180 default: 00181 User::Leave(KErrNotSupported); 00182 break; 00183 } 00184 break; 00185 default: 00186 User::Leave(KErrNotSupported); 00187 break; 00188 } 00189 00190 CleanupStack::PushL(self); 00191 self->ConstructL(aImageProc,aMaskProc,aInfo); 00192 CleanupStack::Pop(); // self 00193 return self; 00194 } 00195 00196 CPngReadSubCodec::CPngReadSubCodec(): 00197 iScanlineDes1(NULL,0), 00198 iScanlineDes2(NULL,0) 00199 {} 00200 00201 CPngReadSubCodec::~CPngReadSubCodec() 00202 { 00203 delete iScanlineBuffer1; 00204 delete iScanlineBuffer2; 00205 } 00206 00207 void CPngReadSubCodec::ConstructL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo) 00208 { 00209 iImageProc = aImageProc; 00210 iMaskProc = aMaskProc; 00211 iInfo = aInfo; 00212 iScanlineBufferSize = ScanlineBufferSize(iInfo.iSize.iWidth); 00213 00214 DoConstructL(); 00215 00216 iScanlineBuffer1 = HBufC8::NewMaxL(iScanlineBufferSize); 00217 iScanlineBuffer2 = HBufC8::NewMaxL(iScanlineBufferSize); 00218 00219 if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace) 00220 { 00221 iInterlacedScanlineBufferSize[0] = ScanlineBufferSize((iInfo.iSize.iWidth + 7) >> 3); 00222 iInterlacedScanlineBufferSize[1] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 3); 00223 iInterlacedScanlineBufferSize[2] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 2); 00224 iInterlacedScanlineBufferSize[3] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 2); 00225 iInterlacedScanlineBufferSize[4] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 1); 00226 iInterlacedScanlineBufferSize[5] = ScanlineBufferSize(iInfo.iSize.iWidth >> 1); 00227 iInterlacedScanlineBufferSize[6] = iScanlineBufferSize; 00228 iInterlacedScanlineBufferSize[7] = 0; 00229 iPass = 0; 00230 00231 iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]); 00232 iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]); 00233 } 00234 else 00235 { 00236 iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iScanlineBufferSize,iScanlineBufferSize); 00237 iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iScanlineBufferSize,iScanlineBufferSize); 00238 } 00239 } 00240 00241 TDes8& CPngReadSubCodec::FirstBuffer() 00242 { 00243 iScanlineDes1.FillZ(); 00244 iCurrentScanlineBuffer = 2; 00245 return iScanlineDes2; 00246 } 00247 00248 TDes8& CPngReadSubCodec::DecodeL() 00249 { 00250 TUint8* dataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes1[1] : &iScanlineDes2[1]; 00251 const TUint8* dataPtrLimit = dataPtr + iScanlineDes1.Length() - 1; 00252 00253 FilterScanlineDataL(dataPtr,dataPtrLimit); 00254 DoDecode(dataPtr,dataPtrLimit); 00255 UpdatePos(); 00256 00257 if (iCurrentScanlineBuffer == 1) 00258 { 00259 iCurrentScanlineBuffer = 2; 00260 return iScanlineDes2; 00261 } 00262 else 00263 { 00264 iCurrentScanlineBuffer = 1; 00265 return iScanlineDes1; 00266 } 00267 } 00268 00269 void CPngReadSubCodec::FilterScanlineDataL(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00270 { 00271 TInt filterType = (iCurrentScanlineBuffer == 1) ? iScanlineDes1[0] : iScanlineDes2[0]; 00272 00273 switch (filterType) 00274 { 00275 case 0: // None 00276 break; 00277 case 1: // Sub 00278 { 00279 aDataPtr += iBytesPerPixel; 00280 00281 while (aDataPtr < aDataPtrLimit) 00282 { 00283 aDataPtr[0] = TUint8(aDataPtr[0] + aDataPtr[-iBytesPerPixel]); 00284 aDataPtr++; 00285 } 00286 } 00287 break; 00288 case 2: // Up 00289 { 00290 TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1]; 00291 00292 while (aDataPtr < aDataPtrLimit) 00293 *aDataPtr++ = TUint8(*aDataPtr + *altDataPtr++); 00294 } 00295 break; 00296 case 3: // Average 00297 { 00298 const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit); 00299 TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1]; 00300 00301 while (aDataPtr < tempDataPtrLimit) 00302 { 00303 aDataPtr[0] = TUint8(aDataPtr[0] + (altDataPtr[0] / 2)); 00304 aDataPtr++; 00305 altDataPtr++; 00306 } 00307 00308 while (aDataPtr < aDataPtrLimit) 00309 { 00310 aDataPtr[0] = TUint8(aDataPtr[0] + ((altDataPtr[0] + aDataPtr[-iBytesPerPixel]) / 2)); 00311 aDataPtr++; 00312 altDataPtr++; 00313 } 00314 } 00315 break; 00316 case 4: // Paeth 00317 { 00318 const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit); 00319 TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1]; 00320 00321 while (aDataPtr < tempDataPtrLimit) 00322 { 00323 aDataPtr[0] = TUint8(aDataPtr[0] + altDataPtr[0]); 00324 aDataPtr++; 00325 altDataPtr++; 00326 } 00327 00328 while (aDataPtr < aDataPtrLimit) 00329 { 00330 aDataPtr[0] = TUint8(aDataPtr[0] + PaethPredictor(aDataPtr[-iBytesPerPixel],altDataPtr[0],altDataPtr[-iBytesPerPixel])); 00331 aDataPtr++; 00332 altDataPtr++; 00333 } 00334 } 00335 break; 00336 default: // Error 00337 User::Leave(KErrCorrupt); 00338 break; 00339 } 00340 } 00341 00342 TInt CPngReadSubCodec::PaethPredictor(TInt aLeft,TInt aAbove,TInt aAboveLeft) 00343 { 00344 TInt p = aLeft + aAbove - aAboveLeft; 00345 TInt pa = Abs(p - aLeft); 00346 TInt pb = Abs(p - aAbove); 00347 TInt pc = Abs(p - aAboveLeft); 00348 00349 if (pa <= pb && pa <= pc) 00350 return aLeft; 00351 else if (pb <= pc) 00352 return aAbove; 00353 else 00354 return aAboveLeft; 00355 } 00356 00357 void CPngReadSubCodec::WritePixel(TRgb aPixelColor) 00358 { 00359 if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace) 00360 { 00361 const TInt width = Min(KBlockWidth[iPass],iInfo.iSize.iWidth - iPos.iX); 00362 const TInt endY = Min(iPos.iY + KBlockHeight[iPass],iInfo.iSize.iHeight); 00363 00364 TPoint pos(iPos); 00365 00366 while (pos.iY < endY) 00367 { 00368 iImageProc->SetPos(pos); 00369 00370 for (TInt col = 0; col < width; col++) 00371 iImageProc->SetPixel(aPixelColor); 00372 00373 pos.iY++; 00374 } 00375 00376 iPos.iX += KColIncrement[iPass]; 00377 } 00378 else 00379 iImageProc->SetPixel(aPixelColor); 00380 } 00381 00382 void CPngReadSubCodec::WritePixel(TRgb aPixelColor,TUint8 aAlphaValue) 00383 { 00384 ASSERT(iMaskProc); 00385 00386 TRgb maskColor(TRgb::Gray256(aAlphaValue)); 00387 00388 if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace) 00389 { 00390 iImageProc->SetPos(iPos); 00391 iMaskProc->SetPos(iPos); 00392 iImageProc->SetPixel(aPixelColor); 00393 iMaskProc->SetPixel(maskColor); 00394 00395 iPos.iX += KColIncrement[iPass]; 00396 } 00397 else 00398 { 00399 iImageProc->SetPixel(aPixelColor); 00400 iMaskProc->SetPixel(maskColor); 00401 } 00402 } 00403 00404 void CPngReadSubCodec::UpdatePos() 00405 { 00406 if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace) 00407 { 00408 ASSERT(iPass <= 7); 00409 00410 iPos.iX = KColStart[iPass]; 00411 iPos.iY += KRowIncrement[iPass]; 00412 00413 while (iPos.iX >= iInfo.iSize.iWidth || iPos.iY >= iInfo.iSize.iHeight) 00414 { 00415 iPass++; 00416 iPos.iX = KColStart[iPass]; 00417 iPos.iY = KRowStart[iPass]; 00418 iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]); 00419 iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]); 00420 iScanlineDes1.FillZ(); 00421 iScanlineDes2.FillZ(); 00422 } 00423 } 00424 } 00425 00426 // 00427 // CBitDepth1Decoder: specialised reader for 1bpp scanlines 00428 // 00429 void CBitDepth1Decoder::DoConstructL() 00430 { 00431 if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed)) 00432 { // Set up palette to be grayscale values 00433 iInfo.iPalette[0] = KRgbBlack; 00434 iInfo.iPalette[1] = KRgbWhite; 00435 00436 00437 if (iInfo.iTransparencyPresent) 00438 { 00439 if (iInfo.iTransparentGray <= 1) 00440 iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0; 00441 } 00442 } 00443 00444 // Replicate values to avoid shifts when decoding 00445 iInfo.iPalette[2] = iInfo.iPalette[1]; 00446 iInfo.iPalette[4] = iInfo.iPalette[1]; 00447 iInfo.iPalette[8] = iInfo.iPalette[1]; 00448 iInfo.iPalette[16] = iInfo.iPalette[1]; 00449 iInfo.iPalette[32] = iInfo.iPalette[1]; 00450 iInfo.iPalette[64] = iInfo.iPalette[1]; 00451 iInfo.iPalette[128] = iInfo.iPalette[1]; 00452 00453 if (iInfo.iTransparencyPresent && iInfo.iTransparencyValue[1] != 255) 00454 { 00455 iInfo.iTransparencyValue[2] = iInfo.iTransparencyValue[1]; 00456 iInfo.iTransparencyValue[4] = iInfo.iTransparencyValue[1]; 00457 iInfo.iTransparencyValue[8] = iInfo.iTransparencyValue[1]; 00458 iInfo.iTransparencyValue[16] = iInfo.iTransparencyValue[1]; 00459 iInfo.iTransparencyValue[32] = iInfo.iTransparencyValue[1]; 00460 iInfo.iTransparencyValue[64] = iInfo.iTransparencyValue[1]; 00461 iInfo.iTransparencyValue[128] = iInfo.iTransparencyValue[1]; 00462 } 00463 00464 iBytesPerPixel = 1; 00465 if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace) 00466 { 00467 TInt pixelPadding = ((iInfo.iSize.iWidth + 7) & ~7) - iInfo.iSize.iWidth; 00468 iImageProc->SetPixelPadding(pixelPadding); 00469 if (iMaskProc) 00470 iMaskProc->SetPixelPadding(pixelPadding); 00471 } 00472 } 00473 00474 TInt CBitDepth1Decoder::ScanlineBufferSize(TInt aPixelLength) 00475 { 00476 return ((aPixelLength + 7) / 8) + KPngScanlineFilterTypeLength; 00477 } 00478 00479 void CBitDepth1Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00480 { 00481 if (iMaskProc && iInfo.iTransparencyPresent) 00482 { 00483 while (aDataPtr < aDataPtrLimit) 00484 { 00485 TInt dataValue = *aDataPtr++; 00486 00487 for (TUint mask=0x80; mask!=0; mask>>=1) // iterate with 0x80, 0x40 .. 0x01 00488 WritePixel(iInfo.iPalette[dataValue & mask],iInfo.iTransparencyValue[dataValue & mask]); 00489 } 00490 } 00491 else 00492 { 00493 while (aDataPtr < aDataPtrLimit) 00494 { 00495 TInt dataValue = *aDataPtr++; 00496 00497 for (TUint mask=0x80; mask!=0; mask>>=1) // iterate with 0x80, 0x40 .. 0x01 00498 WritePixel(iInfo.iPalette[dataValue & mask]); 00499 } 00500 } 00501 } 00502 00503 00504 // 00505 // CBitDepth2Decoder: specialised reader for 2bpp scanlines 00506 // 00507 void CBitDepth2Decoder::DoConstructL() 00508 { 00509 if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed)) 00510 { // Set up palette to be grayscale values 00511 iInfo.iPalette[0] = KRgbBlack; 00512 iInfo.iPalette[1] = KRgbDarkGray; 00513 iInfo.iPalette[2] = KRgbGray; 00514 iInfo.iPalette[3] = KRgbWhite; 00515 00516 if (iInfo.iTransparencyPresent) 00517 { 00518 if (iInfo.iTransparentGray <= 3) 00519 iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0; 00520 } 00521 } 00522 00523 // Replicate values to avoid shifts when decoding 00524 iInfo.iPalette[4] = iInfo.iPalette[1]; 00525 iInfo.iPalette[8] = iInfo.iPalette[2]; 00526 iInfo.iPalette[12] = iInfo.iPalette[3]; 00527 00528 iInfo.iPalette[16] = iInfo.iPalette[1]; 00529 iInfo.iPalette[32] = iInfo.iPalette[2]; 00530 iInfo.iPalette[48] = iInfo.iPalette[3]; 00531 00532 iInfo.iPalette[64] = iInfo.iPalette[1]; 00533 iInfo.iPalette[128] = iInfo.iPalette[2]; 00534 iInfo.iPalette[192] = iInfo.iPalette[3]; 00535 00536 if (iInfo.iTransparencyPresent) 00537 { 00538 iInfo.iTransparencyValue[4] = iInfo.iTransparencyValue[1]; 00539 iInfo.iTransparencyValue[8] = iInfo.iTransparencyValue[2]; 00540 iInfo.iTransparencyValue[12] = iInfo.iTransparencyValue[3]; 00541 00542 iInfo.iTransparencyValue[16] = iInfo.iTransparencyValue[1]; 00543 iInfo.iTransparencyValue[32] = iInfo.iTransparencyValue[2]; 00544 iInfo.iTransparencyValue[48] = iInfo.iTransparencyValue[3]; 00545 00546 iInfo.iTransparencyValue[64] = iInfo.iTransparencyValue[1]; 00547 iInfo.iTransparencyValue[128] = iInfo.iTransparencyValue[2]; 00548 iInfo.iTransparencyValue[192] = iInfo.iTransparencyValue[3]; 00549 } 00550 00551 iBytesPerPixel = 1; 00552 if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace) 00553 { 00554 TInt pixelPadding = ((iInfo.iSize.iWidth + 3) & ~3) - iInfo.iSize.iWidth; 00555 iImageProc->SetPixelPadding(pixelPadding); 00556 if (iMaskProc) 00557 iMaskProc->SetPixelPadding(pixelPadding); 00558 } 00559 } 00560 00561 TInt CBitDepth2Decoder::ScanlineBufferSize(TInt aPixelLength) 00562 { 00563 return ((aPixelLength + 3) / 4) + KPngScanlineFilterTypeLength; 00564 } 00565 00566 void CBitDepth2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00567 { 00568 if (iMaskProc && iInfo.iTransparencyPresent) 00569 { 00570 while (aDataPtr < aDataPtrLimit) 00571 { 00572 TInt dataValue = *aDataPtr++; 00573 00574 for (TInt mask=0xc0; mask!=0; mask>>=2) // iterate through 0xc0, 0x30, 0x0c and 0x03 00575 WritePixel(iInfo.iPalette[dataValue & mask],iInfo.iTransparencyValue[dataValue & mask]); 00576 } 00577 } 00578 else 00579 { 00580 while (aDataPtr < aDataPtrLimit) 00581 { 00582 TInt dataValue = *aDataPtr++; 00583 00584 for (TInt mask=0xc0; mask!=0; mask>>=2) // iterate through 0xc0, 0x30, 0x0c and 0x03 00585 WritePixel(iInfo.iPalette[dataValue & mask]); 00586 } 00587 } 00588 } 00589 00590 00591 // 00592 // CBitDepth4Decoder: specialised reader for 4bpp scanlines 00593 // 00594 00595 void CBitDepth4Decoder::DoConstructL() 00596 { 00597 if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed)) 00598 { // Set up palette to be grayscale values 00599 for (TInt index = 0; index < 16; index++) 00600 iInfo.iPalette[index] = TRgb::Gray16(index); 00601 00602 if (iInfo.iTransparencyPresent) 00603 { 00604 if (iInfo.iTransparentGray <= 15) 00605 iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0; 00606 } 00607 } 00608 00609 iBytesPerPixel = 1; 00610 if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace) 00611 { 00612 TInt pixelPadding = ((iInfo.iSize.iWidth + 1) & ~1) - iInfo.iSize.iWidth; 00613 iImageProc->SetPixelPadding(pixelPadding); 00614 if (iMaskProc) 00615 iMaskProc->SetPixelPadding(pixelPadding); 00616 } 00617 } 00618 00619 TInt CBitDepth4Decoder::ScanlineBufferSize(TInt aPixelLength) 00620 { 00621 return ((aPixelLength + 1) / 2) + KPngScanlineFilterTypeLength; 00622 } 00623 00624 void CBitDepth4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00625 { 00626 if (iMaskProc && iInfo.iTransparencyPresent) 00627 { 00628 while (aDataPtr < aDataPtrLimit) 00629 { 00630 TInt dataValue = *aDataPtr++; 00631 00632 WritePixel(iInfo.iPalette[dataValue >> 4],iInfo.iTransparencyValue[dataValue >> 4]); 00633 WritePixel(iInfo.iPalette[dataValue & 0x0f],iInfo.iTransparencyValue[dataValue & 0x0f]); 00634 } 00635 } 00636 else 00637 { 00638 while (aDataPtr < aDataPtrLimit) 00639 { 00640 TInt dataValue = *aDataPtr++; 00641 00642 WritePixel(iInfo.iPalette[dataValue >> 4]); 00643 WritePixel(iInfo.iPalette[dataValue & 0x0f]); 00644 } 00645 } 00646 } 00647 00648 00649 // 00650 // CBitDepth8Decoder: specialised reader for 8bpp scanlines 00651 // 00652 00653 void CBitDepth8Decoder::DoConstructL() 00654 { 00655 if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed)) 00656 { // Set up palette to be grayscale values 00657 for (TInt index = 0; index < 256; index++) 00658 iInfo.iPalette[index] = TRgb::Gray256(index); 00659 00660 if (iInfo.iTransparencyPresent) 00661 { 00662 if (iInfo.iTransparentGray <= 255) 00663 iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0; 00664 } 00665 } 00666 00667 iBytesPerPixel = 1; 00668 } 00669 00670 TInt CBitDepth8Decoder::ScanlineBufferSize(TInt aPixelLength) 00671 { 00672 return aPixelLength + KPngScanlineFilterTypeLength; 00673 } 00674 00675 void CBitDepth8Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00676 { 00677 if (iMaskProc && iInfo.iTransparencyPresent) 00678 { 00679 while (aDataPtr < aDataPtrLimit) 00680 { 00681 WritePixel(iInfo.iPalette[aDataPtr[0]],iInfo.iTransparencyValue[aDataPtr[0]]); 00682 aDataPtr++; 00683 } 00684 } 00685 else 00686 { 00687 while (aDataPtr < aDataPtrLimit) 00688 WritePixel(iInfo.iPalette[*aDataPtr++]); 00689 } 00690 } 00691 00692 00693 // 00694 // CBitDepth8ColorType2Decoder: specialised reader for 8bpp scanlines, direct colour 00695 // 00696 00697 void CBitDepth8ColorType2Decoder::DoConstructL() 00698 { 00699 iBytesPerPixel = 3; 00700 } 00701 00702 TInt CBitDepth8ColorType2Decoder::ScanlineBufferSize(TInt aPixelLength) 00703 { 00704 return (aPixelLength * 3) + KPngScanlineFilterTypeLength; 00705 } 00706 00707 void CBitDepth8ColorType2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00708 { 00709 if (iMaskProc && iInfo.iTransparencyPresent) 00710 { 00711 while (aDataPtr < aDataPtrLimit) 00712 { 00713 TInt red = aDataPtr[0]; 00714 TInt green = aDataPtr[1]; 00715 TInt blue = aDataPtr[2]; 00716 TRgb pixelColor(red,green,blue); 00717 if (red == iInfo.iTransparentRed && green == iInfo.iTransparentGreen && blue == iInfo.iTransparentBlue) 00718 WritePixel(pixelColor,0); 00719 else 00720 WritePixel(pixelColor,255); 00721 aDataPtr += 3; 00722 } 00723 } 00724 else 00725 { 00726 while (aDataPtr < aDataPtrLimit) 00727 { 00728 WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2])); 00729 aDataPtr += 3; 00730 } 00731 } 00732 } 00733 00734 00735 // 00736 // CBitDepth8ColorType4Decoder: specialised reader for 8bpp scanlines, alpha greyscale 00737 // 00738 00739 void CBitDepth8ColorType4Decoder::DoConstructL() 00740 { 00741 iBytesPerPixel = 2; 00742 } 00743 00744 TInt CBitDepth8ColorType4Decoder::ScanlineBufferSize(TInt aPixelLength) 00745 { 00746 return (aPixelLength * 2) + KPngScanlineFilterTypeLength; 00747 } 00748 00749 void CBitDepth8ColorType4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00750 { 00751 if (iMaskProc) 00752 { 00753 while (aDataPtr < aDataPtrLimit) 00754 { 00755 WritePixel(TRgb::Gray256(aDataPtr[0]),aDataPtr[1]); 00756 aDataPtr += 2; 00757 } 00758 } 00759 else 00760 { 00761 while (aDataPtr < aDataPtrLimit) 00762 { 00763 WritePixel(TRgb::Gray256(aDataPtr[0])); 00764 aDataPtr += 2; 00765 } 00766 } 00767 } 00768 00769 00770 // 00771 // CBitDepth8ColorType4Decoder: specialised reader for 8bpp scanlines, alpha colour 00772 // 00773 00774 void CBitDepth8ColorType6Decoder::DoConstructL() 00775 { 00776 iBytesPerPixel = 4; 00777 } 00778 00779 TInt CBitDepth8ColorType6Decoder::ScanlineBufferSize(TInt aPixelLength) 00780 { 00781 return (aPixelLength * 4) + KPngScanlineFilterTypeLength; 00782 } 00783 00784 void CBitDepth8ColorType6Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00785 { 00786 if (iMaskProc) 00787 { 00788 while (aDataPtr < aDataPtrLimit) 00789 { 00790 WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2]),aDataPtr[3]); 00791 aDataPtr += 4; 00792 } 00793 } 00794 else 00795 { 00796 while (aDataPtr < aDataPtrLimit) 00797 { 00798 WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2])); 00799 aDataPtr += 4; 00800 } 00801 } 00802 } 00803 00804 00805 // 00806 // CBitDepth16ColorType0Decoder: specialised reader for 16bpp scanlines, greyscale 00807 // 00808 00809 void CBitDepth16ColorType0Decoder::DoConstructL() 00810 { 00811 iBytesPerPixel = 2; 00812 } 00813 00814 TInt CBitDepth16ColorType0Decoder::ScanlineBufferSize(TInt aPixelLength) 00815 { 00816 return (aPixelLength * 2) + KPngScanlineFilterTypeLength; 00817 } 00818 00819 void CBitDepth16ColorType0Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00820 { 00821 if (iMaskProc && iInfo.iTransparencyPresent) 00822 { 00823 while (aDataPtr < aDataPtrLimit) 00824 { 00825 TInt gray = (aDataPtr[0] << 8) | aDataPtr[1]; 00826 TRgb pixelColor(TRgb::Gray256(aDataPtr[0])); 00827 if (gray == iInfo.iTransparentGray) 00828 WritePixel(pixelColor,0); 00829 else 00830 WritePixel(pixelColor,255); 00831 aDataPtr += 2; 00832 } 00833 } 00834 else 00835 { 00836 while (aDataPtr < aDataPtrLimit) 00837 { 00838 WritePixel(TRgb::Gray256(aDataPtr[0])); 00839 aDataPtr += 2; 00840 } 00841 } 00842 } 00843 00844 00845 // 00846 // CBitDepth16ColorType2Decoder: specialised reader for 16bpp scanlines, RGB colour 00847 // 00848 00849 void CBitDepth16ColorType2Decoder::DoConstructL() 00850 { 00851 iBytesPerPixel = 6; 00852 } 00853 00854 TInt CBitDepth16ColorType2Decoder::ScanlineBufferSize(TInt aPixelLength) 00855 { 00856 return (aPixelLength * 6) + KPngScanlineFilterTypeLength; 00857 } 00858 00859 void CBitDepth16ColorType2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00860 { 00861 if (iMaskProc && iInfo.iTransparencyPresent) 00862 { 00863 while (aDataPtr < aDataPtrLimit) 00864 { 00865 TInt red = (aDataPtr[0] << 8) | aDataPtr[1]; 00866 TInt green = (aDataPtr[2] << 8) | aDataPtr[3]; 00867 TInt blue = (aDataPtr[4] << 8) | aDataPtr[5]; 00868 TRgb pixelColor(aDataPtr[0],aDataPtr[2],aDataPtr[4]); 00869 if (red == iInfo.iTransparentRed && green == iInfo.iTransparentGreen && blue == iInfo.iTransparentBlue) 00870 WritePixel(pixelColor,0); 00871 else 00872 WritePixel(pixelColor,255); 00873 aDataPtr += 6; 00874 } 00875 } 00876 else 00877 { 00878 while (aDataPtr < aDataPtrLimit) 00879 { 00880 WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4])); 00881 aDataPtr += 6; 00882 } 00883 } 00884 } 00885 00886 00887 // 00888 // CBitDepth16ColorType4Decoder: specialised reader for 16bpp scanlines, alpha greyscale 00889 // 00890 00891 void CBitDepth16ColorType4Decoder::DoConstructL() 00892 { 00893 iBytesPerPixel = 4; 00894 } 00895 00896 TInt CBitDepth16ColorType4Decoder::ScanlineBufferSize(TInt aPixelLength) 00897 { 00898 return (aPixelLength * 4) + KPngScanlineFilterTypeLength; 00899 } 00900 00901 void CBitDepth16ColorType4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00902 { 00903 if (iMaskProc) 00904 { 00905 while (aDataPtr < aDataPtrLimit) 00906 { 00907 WritePixel(TRgb::Gray256(aDataPtr[0]),aDataPtr[2]); 00908 aDataPtr += 4; 00909 } 00910 } 00911 else 00912 { 00913 while (aDataPtr < aDataPtrLimit) 00914 { 00915 WritePixel(TRgb::Gray256(aDataPtr[0])); 00916 aDataPtr += 4; 00917 } 00918 } 00919 } 00920 00921 00922 // 00923 // CBitDepth16ColorType6Decoder: specialised reader for 16bpp scanlines, alpha colour 00924 // 00925 00926 void CBitDepth16ColorType6Decoder::DoConstructL() 00927 { 00928 iBytesPerPixel = 8; 00929 } 00930 00931 TInt CBitDepth16ColorType6Decoder::ScanlineBufferSize(TInt aPixelLength) 00932 { 00933 return (aPixelLength * 8) + KPngScanlineFilterTypeLength; 00934 } 00935 00936 void CBitDepth16ColorType6Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit) 00937 { 00938 if (iMaskProc) 00939 { 00940 while (aDataPtr < aDataPtrLimit) 00941 { 00942 WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4]),aDataPtr[6]); 00943 aDataPtr += 8; 00944 } 00945 } 00946 else 00947 { 00948 while (aDataPtr < aDataPtrLimit) 00949 { 00950 WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4])); 00951 aDataPtr += 8; 00952 } 00953 } 00954 } 00955
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.