examples/Multimedia/ICL/ICLCodec/PngScanlineDecoder.cpp

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 

Generated by  doxygen 1.6.2