examples/Multimedia/ICL/ICLCodec/PngScanlineDecoder.cpp

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

Generated by  doxygen 1.6.2