00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "PngScanlineEncoder.h"
00033
00034
00035
00036
00037
00038
00039 CPngWriteSubCodec* CPngWriteSubCodec::NewL(const TPngImageInformation& aInfo, const CFbsBitmap* aSource)
00040 {
00041 CPngWriteSubCodec* self = NULL;
00042
00043 switch (aInfo.iBitDepth)
00044 {
00045 case 1:
00046 self = new(ELeave) CBitDepth1Encoder;
00047 break;
00048 case 2:
00049 self = new(ELeave) CBitDepth2Encoder;
00050 break;
00051 case 4:
00052 self = new(ELeave) CBitDepth4Encoder;
00053 break;
00054 case 8:
00055 switch (aInfo.iColorType)
00056 {
00057 case TPngImageInformation::EGrayscale:
00058 case TPngImageInformation::EIndexedColor:
00059 self = new(ELeave) CBitDepth8Encoder;
00060 break;
00061 case TPngImageInformation::EDirectColor:
00062 self = new(ELeave) CBitDepth8ColorType2Encoder;
00063 break;
00064 default:
00065 User::Leave(KErrNotSupported);
00066 break;
00067 }
00068 break;
00069 default:
00070 User::Leave(KErrNotSupported);
00071 break;
00072 }
00073 ASSERT(self);
00074 CleanupStack::PushL(self);
00075 self->ConstructL(aInfo, aSource);
00076 CleanupStack::Pop(self);
00077 return self;
00078 }
00079
00080 CPngWriteSubCodec::CPngWriteSubCodec()
00081 : iScanlineDes(NULL, 0)
00082 {
00083 }
00084
00085 CPngWriteSubCodec::~CPngWriteSubCodec()
00086 {
00087 delete iScanlineBuffer;
00088 delete iPalette;
00089 }
00090
00091 void CPngWriteSubCodec::ConstructL(const TPngImageInformation& aInfo, const CFbsBitmap* aSource)
00092 {
00093 iInfo = aInfo;
00094 iSource = aSource;
00095 iScanlineBufferSize = ScanlineBufferSize(iInfo.iSize.iWidth);
00096 iScanlineBuffer = HBufC8::NewMaxL(iScanlineBufferSize);
00097 iScanlineDes.Set(&(iScanlineBuffer->Des())[0], iScanlineBufferSize, iScanlineBufferSize);
00098
00099
00100 DoConstructL();
00101 }
00102
00103 void CPngWriteSubCodec::DoConstructL()
00104 {
00105 }
00106
00107 TDes8& CPngWriteSubCodec::Buffer()
00108 {
00109 iScanlineDes.FillZ();
00110 return iScanlineDes;
00111 }
00112
00113 TDes8& CPngWriteSubCodec::EncodeL(const TInt aScanline)
00114 {
00115 if (aScanline < iInfo.iSize.iHeight)
00116 {
00117 TUint8* dataPtr = const_cast<TUint8*>(iScanlineDes.Ptr());
00118 const TUint8* dataPtrLimit = dataPtr + iScanlineBufferSize;
00119
00120 DoEncode(iSource, aScanline, dataPtr, dataPtrLimit);
00121 }
00122 else
00123 {
00124 iScanlineDes.Set(NULL, 0, 0);
00125 }
00126 return iScanlineDes;
00127 }
00128
00129 TUint8 CPngWriteSubCodec::ReverseBits(const TUint8 aValue) const
00130 {
00131 TUint value = aValue;
00132 TUint reverseVal = 0;
00133 for (TInt i = 0; i < 8; i++)
00134 {
00135 reverseVal <<= 1;
00136 reverseVal |= value & 1;
00137 value >>= 1;
00138 }
00139 return TUint8(reverseVal);
00140 }
00141
00142 void CPngWriteSubCodec::EncodePalettedScanline(TUint8* aDataPtr, const CFbsBitmap* aSource, const TInt aScanline,
00143 const TInt aPixelsPerByte, const TInt aShiftValue)
00144 {
00145
00146 ASSERT(iInfo.iPalettePresent);
00147 TPoint pos(0, aScanline);
00148 const TInt scanLength = iInfo.iSize.iWidth;
00149 for (TInt i=0; i < scanLength; i += aPixelsPerByte)
00150 {
00151
00152 TUint8 pixels = 0;
00153 for (TInt j=0; j < aPixelsPerByte; j++)
00154 {
00155 pixels <<= aShiftValue;
00156 TRgb rgb;
00157 aSource->GetPixel(rgb, pos);
00158 pixels |= TUint8(iPalette->NearestIndex(rgb));
00159 pos.iX++;
00160 }
00161 *aDataPtr = pixels;
00162 aDataPtr++;
00163 }
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 void CBitDepth1Encoder::DoConstructL()
00176 {
00177 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00178 {
00179
00180 iPalette = CPalette::NewL(2);
00181 iPalette->SetEntry(0, KRgbBlack);
00182 iPalette->SetEntry(1, KRgbWhite);
00183 iInfo.iPalettePresent = ETrue;
00184 }
00185 }
00186
00187 TInt CBitDepth1Encoder::ScanlineBufferSize(TInt aPixelLength)
00188 {
00189
00190 return ((aPixelLength + KPngDepth1RoundUpValue) / KPngDepth1PixelsPerByte) + KPngScanlineFilterTypeLength;
00191 }
00192
00193 void CBitDepth1Encoder::DoEncode(const CFbsBitmap* aSource, const TInt aScanline,
00194 TUint8* aDataPtr, const TUint8* aDataPtrLimit)
00195 {
00196
00197 PtrWriteUtil::WriteInt8(aDataPtr, iInfo.iFilterMethod);
00198 aDataPtr++;
00199
00200
00201 const TInt scanLength = iInfo.iSize.iWidth;
00202 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00203 {
00204
00205 EncodePalettedScanline(aDataPtr, aSource, aScanline, KPngDepth1PixelsPerByte, KPngDepth1ShiftValue);
00206 }
00207 else
00208 {
00209
00210 TInt dataLength = (scanLength + KPngDepth1RoundUpValue) / KPngDepth1PixelsPerByte;
00211 TPtr8 dataPtr(aDataPtr, dataLength, dataLength);
00212
00213 aSource->GetScanLine(dataPtr, TPoint(0, aScanline), scanLength, EGray2);
00214
00215
00216 while (aDataPtr < aDataPtrLimit)
00217 {
00218 aDataPtr[0] = ReverseBits(aDataPtr[0]);
00219 aDataPtr++;
00220 }
00221 }
00222 }
00223
00224
00225
00226
00227
00228 void CBitDepth2Encoder::DoConstructL()
00229 {
00230 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00231 {
00232
00233 iPalette = CPalette::NewL(4);
00234 iPalette->SetEntry(0, KRgbBlack);
00235 iPalette->SetEntry(1, KRgbDarkGray);
00236 iPalette->SetEntry(2, KRgbGray);
00237 iPalette->SetEntry(3, KRgbWhite);
00238 iInfo.iPalettePresent = ETrue;
00239 }
00240 }
00241
00242 TInt CBitDepth2Encoder::ScanlineBufferSize(TInt aPixelLength)
00243 {
00244 return ((aPixelLength + KPngDepth2RoundUpValue) / KPngDepth2PixelsPerByte) + KPngScanlineFilterTypeLength;
00245 }
00246
00247 void CBitDepth2Encoder::DoEncode(const CFbsBitmap* aSource, const TInt aScanline,
00248 TUint8* aDataPtr, const TUint8* aDataPtrLimit)
00249 {
00250
00251 PtrWriteUtil::WriteInt8(aDataPtr, iInfo.iFilterMethod);
00252 aDataPtr++;
00253
00254
00255 const TInt scanLength = iInfo.iSize.iWidth;
00256 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00257 {
00258
00259 EncodePalettedScanline(aDataPtr, aSource, aScanline, KPngDepth2PixelsPerByte, KPngDepth2ShiftValue);
00260 }
00261 else
00262 {
00263
00264 TPtr8 dataPtr(aDataPtr, (scanLength + KPngDepth2RoundUpValue) / KPngDepth2PixelsPerByte);
00265 aSource->GetScanLine(dataPtr, TPoint(0, aScanline), scanLength, EGray4);
00266
00267
00268 while (aDataPtr < aDataPtrLimit)
00269 {
00270 TUint8 value = aDataPtr[0];
00271 TUint8 reverse = 0;
00272 for (TInt i=0; i < KPngDepth2PixelsPerByte; i++)
00273 {
00274 reverse <<= 2;
00275 reverse |= value & 0x3;
00276 value >>= 2;
00277 }
00278 aDataPtr[0] = reverse;
00279 aDataPtr++;
00280 }
00281 }
00282 }
00283
00284
00285
00286
00287
00288 void CBitDepth4Encoder::DoConstructL()
00289 {
00290 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00291 {
00292
00293 iPalette = CPalette::NewDefaultL(EColor16);
00294 iInfo.iPalettePresent = ETrue;
00295 }
00296 }
00297
00298 TInt CBitDepth4Encoder::ScanlineBufferSize(TInt aPixelLength)
00299 {
00300 return ((aPixelLength + KPngDepth4RoundUpValue) / KPngDepth4PixelsPerByte) + KPngScanlineFilterTypeLength;
00301 }
00302
00303 void CBitDepth4Encoder::DoEncode(const CFbsBitmap* aSource, const TInt aScanline,
00304 TUint8* aDataPtr, const TUint8* aDataPtrLimit)
00305 {
00306
00307 PtrWriteUtil::WriteInt8(aDataPtr, iInfo.iFilterMethod);
00308 aDataPtr++;
00309
00310
00311 const TInt scanLength = iInfo.iSize.iWidth;
00312 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00313 {
00314
00315 EncodePalettedScanline(aDataPtr, aSource, aScanline, KPngDepth4PixelsPerByte, KPngDepth4ShiftValue);
00316 }
00317 else
00318 {
00319 TPtr8 dataPtr(aDataPtr, (scanLength + KPngDepth4RoundUpValue) / KPngDepth4PixelsPerByte);
00320 aSource->GetScanLine(dataPtr, TPoint(0, aScanline), scanLength,
00321 (iInfo.iColorType == TPngImageInformation::EDirectColor) ? EColor16 : EGray16);
00322
00323
00324 while (aDataPtr < aDataPtrLimit)
00325 {
00326 TUint value = aDataPtr[0];
00327 TUint low = value << KPngDepth4ShiftValue;
00328 TUint high = value >> KPngDepth4ShiftValue;
00329 aDataPtr[0] = TUint8(low | high);
00330 aDataPtr++;
00331 }
00332 }
00333 }
00334
00335
00336
00337
00338
00339 TInt CBitDepth8ColorType2Encoder::ScanlineBufferSize(TInt aPixelLength)
00340 {
00341 return (aPixelLength * KPngDepth8RgbBytesPerPixel) + KPngScanlineFilterTypeLength;
00342 }
00343
00344 void CBitDepth8ColorType2Encoder::DoEncode(const CFbsBitmap* aSource, const TInt aScanline,
00345 TUint8* aDataPtr, const TUint8* aDataPtrLimit)
00346 {
00347
00348 PtrWriteUtil::WriteInt8(aDataPtr, iInfo.iFilterMethod);
00349 aDataPtr++;
00350
00351
00352 TPtr8 dataPtr(aDataPtr, iInfo.iSize.iWidth * KPngDepth8RgbBytesPerPixel);
00353 aSource->GetScanLine(dataPtr, TPoint(0, aScanline), iInfo.iSize.iWidth, EColor16M);
00354
00355 while (aDataPtr < aDataPtrLimit)
00356 {
00357
00358 TUint8 temp = aDataPtr[0];
00359 aDataPtr[0] = aDataPtr[2];
00360 aDataPtr[2] = temp;
00361 aDataPtr += KPngDepth8RgbBytesPerPixel;
00362 }
00363 }
00364
00365
00366
00367
00368
00369 void CBitDepth8Encoder::DoConstructL()
00370 {
00371 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00372 {
00373
00374 iPalette = CPalette::NewDefaultL(EColor256);
00375 iInfo.iPalettePresent = ETrue;
00376 }
00377 }
00378
00379 TInt CBitDepth8Encoder::ScanlineBufferSize(TInt aPixelLength)
00380 {
00381 return aPixelLength + KPngScanlineFilterTypeLength;
00382 }
00383
00384 void CBitDepth8Encoder::DoEncode(const CFbsBitmap* aSource, const TInt aScanline,
00385 TUint8* aDataPtr, const TUint8* )
00386 {
00387
00388 PtrWriteUtil::WriteInt8(aDataPtr, iInfo.iFilterMethod);
00389 aDataPtr++;
00390
00391 const TInt scanLength = iInfo.iSize.iWidth;
00392 if (iInfo.iColorType == TPngImageInformation::EIndexedColor)
00393 {
00394
00395 EncodePalettedScanline(aDataPtr, aSource, aScanline, KPngDepth8PixelsPerByte, KPngDepth8ShiftValue);
00396 }
00397 else
00398 {
00399
00400 TPtr8 dataPtr(aDataPtr, scanLength);
00401 aSource->GetScanLine(dataPtr, TPoint(0, aScanline), scanLength, EGray256);
00402 }
00403 }