|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <ecom/ecom.h> |
|
17 #include "PNGCodec.h" |
|
18 |
|
19 #include "PngDecoderFactory.h" |
|
20 |
|
21 |
|
22 |
|
23 /*static*/ |
|
24 MImageStreamDecoderFactory* CPngImageStreamDecoderFactory::NewL() |
|
25 { |
|
26 return static_cast<MImageStreamDecoderFactory*>(new (ELeave) CPngImageStreamDecoderFactory()); |
|
27 } |
|
28 |
|
29 |
|
30 CPngImageStreamDecoderFactory::CPngImageStreamDecoderFactory() |
|
31 { |
|
32 } |
|
33 |
|
34 CPngImageStreamDecoderFactory::~CPngImageStreamDecoderFactory() |
|
35 { |
|
36 REComSession::DestroyedImplementation(iDtorKey); |
|
37 } |
|
38 |
|
39 // MImageStreamDecoderFactory // |
|
40 void CPngImageStreamDecoderFactory::SetDtorKey(TUid aUid) |
|
41 { |
|
42 iDtorKey = aUid; |
|
43 } |
|
44 |
|
45 void CPngImageStreamDecoderFactory::Release() |
|
46 { |
|
47 ASSERT(iDtorKey.iUid); |
|
48 delete this; |
|
49 } |
|
50 |
|
51 class CPngImage: protected CPngReadCodec, protected MPngDecoder, public MImageStreamDecoder |
|
52 { |
|
53 public: |
|
54 static CPngImage* NewL(); |
|
55 |
|
56 // from the MImageStreamDecoder // |
|
57 virtual void InitL(CImageProcessor& aImageProcessor, CImageProcessor* aMaskProcessor, CFbsBitmap* aDestination, |
|
58 const TPtrC8& aData, MUniqueChunkDataProvider& aProvider); |
|
59 virtual void DecodeL(); |
|
60 virtual void ResetL(); |
|
61 virtual void Release(); |
|
62 virtual const TSize& ImageSize(); |
|
63 |
|
64 protected: |
|
65 CPngImage(); |
|
66 |
|
67 virtual void DoProcessPLTEL(const TUint8* aDataPtr,TInt aChunkLength); |
|
68 virtual void DoProcesstRNSL(const TUint8* aDataPtr,TInt aChunkLength); |
|
69 virtual void DoProcessbKGDL(const TUint8* aDataPtr,TInt aChunkLength); |
|
70 virtual void DoProcesspHYsL(const TUint8* aDataPtr,TInt aChunkLength); |
|
71 |
|
72 void InitFrameL(); |
|
73 // from the MPngDecoder // |
|
74 void GoToProcessDataState(); |
|
75 |
|
76 protected: |
|
77 CPngImage(const TBufPtr8& aData); |
|
78 TFrameInfo iFrameInfo; |
|
79 TBufPtr8 iCurrentData; |
|
80 TBufPtr8 iData; |
|
81 MUniqueChunkDataProvider* iChunkProvider; |
|
82 TBool iDataProcessing; |
|
83 TBool ibKGDChunkFound; |
|
84 TBool ipHYsChunkFound; |
|
85 TBool itRNSChunkFound; |
|
86 CFbsBitmap* iCurrentFrame; //destination bitmap; not owned. |
|
87 }; |
|
88 |
|
89 /*static*/ |
|
90 CPngImage* CPngImage::NewL() |
|
91 { |
|
92 return new (ELeave) CPngImage(); |
|
93 } |
|
94 |
|
95 CPngImage::CPngImage():CPngReadCodec(static_cast<MPngDecoder&>(*this)) |
|
96 { |
|
97 } |
|
98 |
|
99 void CPngImage::Release() |
|
100 { |
|
101 delete this; |
|
102 } |
|
103 |
|
104 void CPngImage::GoToProcessDataState() |
|
105 { |
|
106 iDataProcessing = ETrue; |
|
107 } |
|
108 |
|
109 void CPngImage::InitL(CImageProcessor& aImageProcessor, CImageProcessor* aMaskProcessor, CFbsBitmap* aDestination, |
|
110 const TPtrC8& aData, MUniqueChunkDataProvider& aProvider) |
|
111 { |
|
112 CPngReadCodec::ConstructL(); |
|
113 iCurrentFrame = aDestination; |
|
114 SetImageProcessor(&aImageProcessor, EFalse); |
|
115 if (NULL != aMaskProcessor) |
|
116 { |
|
117 SetMaskProcessor(aMaskProcessor, EFalse); |
|
118 } |
|
119 iCurrentData.Set(aData); |
|
120 iData.Set(aData); |
|
121 iChunkProvider = &aProvider; |
|
122 |
|
123 TFrameInfo inf; |
|
124 inf.SetCurrentFrameState(TFrameInfo::EFrameInfoUninitialised); |
|
125 CFrameImageData* DummyData=NULL; |
|
126 InitFrameHeader(inf, *DummyData ); |
|
127 ProcessFrameHeaderL( iCurrentData ); |
|
128 if (!ibKGDChunkFound) |
|
129 { |
|
130 const TUint8* Ptr; |
|
131 TInt ChunkLength; |
|
132 if (KErrNone == iChunkProvider->GetChunkData(KPngbKGDChunkId().Ptr(), Ptr, ChunkLength)) |
|
133 { |
|
134 DoProcessbKGDL(Ptr, ChunkLength); |
|
135 } |
|
136 } |
|
137 if (!ipHYsChunkFound) |
|
138 { |
|
139 const TUint8* Ptr; |
|
140 TInt ChunkLength; |
|
141 if (KErrNone == iChunkProvider->GetChunkData(KPngpHYsChunkId().Ptr(), Ptr, ChunkLength)) |
|
142 { |
|
143 DoProcesspHYsL(Ptr, ChunkLength); |
|
144 } |
|
145 } |
|
146 InitFrameL(); |
|
147 } |
|
148 |
|
149 void CPngImage::ResetL() |
|
150 { |
|
151 iCurrentData.Set(iData); |
|
152 iDataProcessing = EFalse; |
|
153 ibKGDChunkFound = EFalse; |
|
154 ipHYsChunkFound = EFalse; |
|
155 itRNSChunkFound = EFalse; |
|
156 InitFrameL(); |
|
157 } |
|
158 |
|
159 const TSize& CPngImage::ImageSize() |
|
160 { |
|
161 return iImageInfo.iSize; |
|
162 } |
|
163 |
|
164 void CPngImage::DoProcessPLTEL(const TUint8* aDataPtr,TInt aChunkLength) |
|
165 { |
|
166 if (0 == aChunkLength) |
|
167 { |
|
168 const TUint8* Plte; |
|
169 if (KErrNone == iChunkProvider->GetChunkData(KPngPLTEChunkId().Ptr(), Plte, aChunkLength)) |
|
170 { |
|
171 // try to get inherited tRNS as well... |
|
172 const TUint8* Trns; |
|
173 TInt TrnsLen=0; |
|
174 if (!itRNSChunkFound && KErrNone == iChunkProvider->GetChunkData(KPngtRNSChunkId().Ptr(), Trns, TrnsLen)) |
|
175 { |
|
176 CPngReadCodec::DoProcesstRNSL(Trns, TrnsLen); |
|
177 } |
|
178 aDataPtr = Plte; |
|
179 } |
|
180 } |
|
181 CPngReadCodec::DoProcessPLTEL(aDataPtr, aChunkLength); |
|
182 } |
|
183 |
|
184 void CPngImage::DoProcesstRNSL(const TUint8* aDataPtr,TInt aChunkLength) |
|
185 { |
|
186 if (0 == aChunkLength) |
|
187 { |
|
188 const TUint8* Trns; |
|
189 if (KErrNone == iChunkProvider->GetChunkData(KPngtRNSChunkId().Ptr(), Trns, aChunkLength)) |
|
190 { |
|
191 aDataPtr = Trns; |
|
192 } |
|
193 } |
|
194 itRNSChunkFound = (0 != aChunkLength); |
|
195 CPngReadCodec::DoProcesstRNSL(aDataPtr,aChunkLength); |
|
196 } |
|
197 |
|
198 void CPngImage::DoProcessbKGDL(const TUint8* aDataPtr,TInt aChunkLength) |
|
199 { |
|
200 if (0 == aChunkLength || ibKGDChunkFound) |
|
201 { |
|
202 User::Leave(KErrCorrupt); |
|
203 } |
|
204 ibKGDChunkFound = ETrue; |
|
205 CPngReadCodec::DoProcessbKGDL(aDataPtr,aChunkLength); |
|
206 } |
|
207 |
|
208 void CPngImage::DoProcesspHYsL(const TUint8* aDataPtr,TInt aChunkLength) |
|
209 { |
|
210 if (0 == aChunkLength || ipHYsChunkFound) |
|
211 { |
|
212 User::Leave(KErrCorrupt); |
|
213 } |
|
214 ipHYsChunkFound = ETrue; |
|
215 CPngReadCodec::DoProcessbKGDL(aDataPtr,aChunkLength); |
|
216 } |
|
217 |
|
218 void CPngImage::InitFrameL() |
|
219 { |
|
220 iChunkBytesRemaining = 0; |
|
221 iChunkId = KNullDesC8; |
|
222 |
|
223 |
|
224 if (iDecoder == NULL) |
|
225 { |
|
226 TBool fastProcessorMode = EFalse; |
|
227 CFastProcessor* fastProc = NULL; |
|
228 SetFastProcessor(NULL); |
|
229 |
|
230 /*Check if Image processor is to be ignored. |
|
231 Ignore Image processor only when decoding 24 or 32 bpp images. |
|
232 In case of non interlaced images and if destination and source height/width differ then don't skip Image processor. |
|
233 */ |
|
234 if (((iImageInfo.iBitDepth == 8) && (iImageInfo.iColorType == TPngImageInformation::EDirectColor || iImageInfo.iColorType == TPngImageInformation::EAlphaDirectColor)) && (iImageInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace) && (iImageInfo.iTransparencyPresent == EFalse )) |
|
235 { |
|
236 |
|
237 CFbsBitmap* destBitmap=NULL; |
|
238 |
|
239 fastProc = CFastProcessor::NewL(iImageInfo, destBitmap, NULL, ETrue); |
|
240 SetFastProcessor(fastProc); |
|
241 fastProcessorMode = ETrue; |
|
242 } |
|
243 |
|
244 iDecoder = CPngReadSubCodec::NewL(ImageProcessor(), MaskProcessor(), iImageInfo , FastProcessor(), fastProcessorMode); |
|
245 iDecoder->SetRgbaMode(ETrue); |
|
246 } |
|
247 |
|
248 if (iDecompressor == NULL) |
|
249 { |
|
250 iDecompressor = CEZDecompressor::NewL(*this); |
|
251 } |
|
252 |
|
253 } |
|
254 |
|
255 void CPngImage::DecodeL() |
|
256 { |
|
257 const TPoint ZeroPoint(0,0); |
|
258 const TRect ImageRect(ZeroPoint, ImageSize().AsPoint()); |
|
259 |
|
260 if ((iImageInfo.iTransparencyPresent || (iImageInfo.iColorType & TPngImageInformation::EAlphaChannelUsed)) |
|
261 && MaskProcessor() ) |
|
262 { |
|
263 |
|
264 MaskProcessor()->PrepareL(*iCurrentFrame, ImageRect); |
|
265 MaskProcessor()->SetPos(ZeroPoint); |
|
266 } |
|
267 |
|
268 ImageProcessor()->PrepareL(*iCurrentFrame, ImageRect); |
|
269 ImageProcessor()->SetPos(ZeroPoint); |
|
270 |
|
271 while (EFrameIncomplete == ProcessFrameL( iCurrentData )) |
|
272 { |
|
273 if (iDataProcessing) |
|
274 { |
|
275 while ( ! DoProcessDataL() ) |
|
276 { |
|
277 (void)0; |
|
278 } |
|
279 } |
|
280 iDataProcessing = EFalse; |
|
281 } |
|
282 delete iDecompressor; |
|
283 iDecompressor=NULL; |
|
284 iDecoder->ResetL(); |
|
285 } |
|
286 |
|
287 // MImageStreamDecoderFactory // |
|
288 void CPngImageStreamDecoderFactory::CreatePngDecoderL(MImageStreamDecoder*& aPtr) |
|
289 { |
|
290 aPtr = NULL; |
|
291 aPtr = static_cast<MImageStreamDecoder*>( CPngImage::NewL() ); |
|
292 } |
|
293 |