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