|
1 // Copyright (c) 1999-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 <fbs.h> |
|
17 #include "ImageClientMain.h" |
|
18 #include "TIFFCodec.h" |
|
19 #include "TIFFFax.h" |
|
20 #include "ImageUtils.h" |
|
21 |
|
22 // CTiffReadCodec. |
|
23 CTiffReadCodec::CTiffReadCodec(TTiffFormatInfo aFormatInfo, CTiffDecoder& aPlugin) |
|
24 : iFormatInfo(aFormatInfo), |
|
25 iValueReader(aFormatInfo.iEndianness), |
|
26 iPlugin(aPlugin) |
|
27 {} |
|
28 |
|
29 CTiffReadCodec::~CTiffReadCodec() |
|
30 { |
|
31 if (iFrameImageData && iFrameImageData->iStripInfo) |
|
32 delete iFrameImageData->iStripInfo; |
|
33 |
|
34 delete iFrameImageData; |
|
35 delete iIfdBuffer; |
|
36 delete iLongValuesBuffer; |
|
37 delete iDecoder; |
|
38 delete iRecordTable; |
|
39 } |
|
40 |
|
41 CTiffReadCodec* CTiffReadCodec::NewL(TTiffFormatInfo aFormatInfo, CTiffDecoder& aPlugin) |
|
42 { |
|
43 CTiffReadCodec* self = new(ELeave) CTiffReadCodec(aFormatInfo, aPlugin); |
|
44 CleanupStack::PushL(self); |
|
45 self->ConstructL(); |
|
46 CleanupStack::Pop(self); |
|
47 return self; |
|
48 } |
|
49 |
|
50 void CTiffReadCodec::InitFrameHeader(TFrameInfo& aFrameSettings, CFrameImageData& aFrameImageData) |
|
51 { |
|
52 iImageInfo = &aFrameSettings; |
|
53 iImageData = &aFrameImageData; |
|
54 |
|
55 if (iRecordTable && (iProcessHeaderState == EReadIfd)) |
|
56 { |
|
57 iRecordTable->Reset(); |
|
58 } |
|
59 } |
|
60 |
|
61 TFrameState CTiffReadCodec::ProcessFrameHeaderL(TBufPtr8& aData) |
|
62 { |
|
63 const TUint8* ptr = aData.Ptr(); |
|
64 const TUint8* const ptrStart = ptr; |
|
65 const TUint8* const ptrLimit = ptr + aData.Length(); |
|
66 |
|
67 if (iImageInfo->CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised) |
|
68 { |
|
69 iImageInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrameHeader); |
|
70 |
|
71 if (ptrStart + 4 > ptrLimit) |
|
72 User::Leave(KErrUnderflow); |
|
73 |
|
74 TUint32 signature = PtrReadUtil::ReadUint32(ptr); |
|
75 |
|
76 if (iFormatInfo.iSignature == signature) |
|
77 return EFrameComplete; |
|
78 |
|
79 iProcessHeaderState = EReadIfd; |
|
80 iNumIfdEntries = 0; |
|
81 iLongValuesStartOffset = KMaxTInt; |
|
82 iLongValuesEndOffset = 0; |
|
83 iLoadedLongValuesSize = 0; |
|
84 |
|
85 if (iFrameImageData && iFrameImageData->iStripInfo) |
|
86 delete iFrameImageData->iStripInfo; |
|
87 |
|
88 delete iFrameImageData; |
|
89 iFrameImageData = NULL; |
|
90 |
|
91 iFrameImageData = new(ELeave) TTiffImageData; |
|
92 iFrameImageData->iNewSubfileType = 0; |
|
93 iFrameImageData->iSizeInPixels = TSize(0, 0); |
|
94 iFrameImageData->iBitsPerSample = 0; |
|
95 iFrameImageData->iSamplesPerPixel = 0; |
|
96 iFrameImageData->iCompression = 0; |
|
97 iFrameImageData->iT4Options = 0; |
|
98 iFrameImageData->iT6Options = 0; |
|
99 iFrameImageData->iPhotometricInterpretation = 0; |
|
100 iFrameImageData->iFillOrder = 0; |
|
101 iFrameImageData->iWidthInTwips = 0.0; |
|
102 iFrameImageData->iHeightInTwips = 0.0; |
|
103 iFrameImageData->iRowsPerStrip = 0; |
|
104 iFrameImageData->iNumStrips = 0; |
|
105 iFrameImageData->iStripInfo = NULL; |
|
106 } |
|
107 |
|
108 TInt err = KErrNone; |
|
109 |
|
110 FOREVER |
|
111 { |
|
112 switch(iProcessHeaderState) |
|
113 { |
|
114 case EReadIfd: |
|
115 if (!iRecordTable) |
|
116 { |
|
117 iRecordTable = CRecordTable::NewL(); |
|
118 } |
|
119 |
|
120 iIfdSize = 0; |
|
121 iIfdOffset = iPlugin.CurrentFilePosition(); |
|
122 err = ReadIfdL(ptr, ptrLimit, iIfdSize); |
|
123 |
|
124 if (err != KErrNone) |
|
125 { |
|
126 return EFrameIncomplete; |
|
127 } |
|
128 |
|
129 if (iLongValuesSize) |
|
130 { |
|
131 iProcessHeaderState = EReadLongValues; |
|
132 aData.Shift(aData.Length()); |
|
133 iNewPosition = iLongValuesStartOffset; |
|
134 return EFrameIncompleteRepositionRequest; |
|
135 } |
|
136 |
|
137 iProcessHeaderState = EProcessIfd; |
|
138 break; |
|
139 |
|
140 case EReadLongValues: |
|
141 |
|
142 err = ReadLongValuesL(ptr, ptrLimit); |
|
143 aData.Shift(ptr-ptrStart); |
|
144 if (err != KErrNone) |
|
145 return EFrameIncomplete; |
|
146 |
|
147 iProcessHeaderState = EProcessIfd; |
|
148 break; |
|
149 |
|
150 case EProcessIfd: |
|
151 |
|
152 ProcessIfdL(); |
|
153 aData.Shift(aData.Length()); |
|
154 |
|
155 iProcessHeaderState = EFinish; |
|
156 break; |
|
157 |
|
158 case EFinish: |
|
159 { |
|
160 err = iRecordTable->InsertRecordL(iIfdOffset, iIfdSize); |
|
161 if (err != KErrNone) |
|
162 { |
|
163 User::Leave(KErrCorrupt); |
|
164 } |
|
165 |
|
166 iIfdOffset = 0; |
|
167 iIfdSize = 0; |
|
168 |
|
169 // Check that we got strip info. |
|
170 if (iFrameImageData->iStripInfo == NULL) |
|
171 User::Leave(KErrCorrupt); |
|
172 |
|
173 err = iImageData->AppendImageBuffer(iFrameImageData->iStripInfo); |
|
174 if (err != KErrNone) |
|
175 { |
|
176 delete iFrameImageData->iStripInfo; |
|
177 delete iFrameImageData; |
|
178 iFrameImageData = NULL; |
|
179 |
|
180 User::Leave(err); |
|
181 } |
|
182 |
|
183 err = iImageData->AppendFrameData(iFrameImageData); |
|
184 if(err != KErrNone) |
|
185 { |
|
186 delete iFrameImageData; |
|
187 iFrameImageData = NULL; |
|
188 |
|
189 User::Leave(err); |
|
190 } |
|
191 |
|
192 iImageInfo->iFrameCoordsInPixels = iFrameImageData->iSizeInPixels; |
|
193 iImageInfo->iOverallSizeInPixels = iFrameImageData->iSizeInPixels; |
|
194 iImageInfo->iFrameSizeInTwips.SetSize(STATIC_CAST(TInt, iFrameImageData->iWidthInTwips), STATIC_CAST(TInt, iFrameImageData->iHeightInTwips)); |
|
195 iImageInfo->iBitsPerPixel = 1; |
|
196 iImageInfo->iFrameDisplayMode = EGray2; |
|
197 iImageInfo->iDelay = 0; |
|
198 iImageInfo->iFlags = TFrameInfo::EPartialDecodeInvalid; |
|
199 // in all of the test files we've seen, the frame info follows the frame data |
|
200 // so it has not been possible to check to see if it would work |
|
201 // If this has changed, visit commented out ClearBitmap above |
|
202 iImageInfo->SetFrameDataOffset(iStripInfo[0].iOffset - iFormatInfo.iFirstIfd); |
|
203 |
|
204 iFrameImageData = NULL; |
|
205 iImageInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete); |
|
206 if (iNextIfdOffset == 0) |
|
207 { |
|
208 delete iRecordTable; |
|
209 iRecordTable = NULL; |
|
210 return EFrameComplete; |
|
211 } |
|
212 else |
|
213 { |
|
214 iNewPosition = iNextIfdOffset; |
|
215 return EFrameIncompleteRepositionRequest; |
|
216 } |
|
217 } |
|
218 |
|
219 default: |
|
220 Panic(EUnknownHeaderState); |
|
221 } |
|
222 } |
|
223 } |
|
224 |
|
225 TInt CTiffReadCodec::ReadIfdL(const TUint8*& aPtr, const TUint8* aPtrLimit, TInt& aIfdSizeInBytes) |
|
226 { |
|
227 const TUint8* ptr = aPtr; |
|
228 |
|
229 if (ptr + 4 > aPtrLimit) |
|
230 return(KErrUnderflow); |
|
231 |
|
232 iNumIfdEntries = iValueReader.ReadUint16(ptr); |
|
233 |
|
234 ptr += 2; |
|
235 |
|
236 if (ptr + iNumIfdEntries * KTiffIfdEntryLength + 4 > aPtrLimit) |
|
237 return(KErrUnderflow); |
|
238 |
|
239 aIfdSizeInBytes = iNumIfdEntries * sizeof(TTiffIfdEntry); |
|
240 |
|
241 if (iIfdBuffer) |
|
242 { |
|
243 if (iIfdBuffer->Length() < aIfdSizeInBytes) |
|
244 { |
|
245 delete iIfdBuffer; |
|
246 iIfdBuffer = NULL; |
|
247 } |
|
248 } |
|
249 |
|
250 if (!iIfdBuffer) |
|
251 iIfdBuffer = HBufC8::NewMaxL(aIfdSizeInBytes); |
|
252 |
|
253 TTiffIfdEntry* entry = REINTERPRET_CAST(TTiffIfdEntry*, CONST_CAST(TUint8*, iIfdBuffer->Des().Ptr())); |
|
254 iIfdEntries = entry; |
|
255 |
|
256 for (TInt i = 0; i < iNumIfdEntries; i++) |
|
257 { |
|
258 ReadIfdEntryL(*entry, ptr); |
|
259 entry++; |
|
260 ptr += KTiffIfdEntryLength; |
|
261 } |
|
262 |
|
263 iNextIfdOffset = iValueReader.ReadUint32(ptr); |
|
264 aPtr = ptr + 4; |
|
265 |
|
266 if (iLongValuesStartOffset < iLongValuesEndOffset) |
|
267 iLongValuesSize = iLongValuesEndOffset - iLongValuesStartOffset; |
|
268 else |
|
269 iLongValuesSize = 0; |
|
270 |
|
271 return(KErrNone); |
|
272 } |
|
273 |
|
274 void CTiffReadCodec::ReadIfdEntryL(TTiffIfdEntry& aEntry, const TUint8*const aPtr) |
|
275 { |
|
276 aEntry.iId = STATIC_CAST(TTiffIfdEntry::TId, iValueReader.ReadUint16(aPtr + KTiffIfdEntryTagOffset)); |
|
277 aEntry.iType = STATIC_CAST(TTiffIfdEntry::TType, iValueReader.ReadUint16(aPtr + KTiffIfdEntryTypeOffset)); |
|
278 aEntry.iCount = iValueReader.ReadUint32(aPtr + KTiffIfdEntryCountOffset); |
|
279 |
|
280 const TInt valueSize = aEntry.TypeSize()*aEntry.iCount; |
|
281 |
|
282 if (valueSize <= 4) |
|
283 { |
|
284 // read as if TUint32* - equiv to Mem::Copy(&aEntry.iValue, aPtr+KTiffIfdEntryValueOffset, 4); |
|
285 aEntry.iValue = PtrReadUtil::ReadUint32(aPtr+KTiffIfdEntryValueOffset); |
|
286 |
|
287 aEntry.iValuePtr = REINTERPRET_CAST(TUint8*, &aEntry.iValue); |
|
288 } |
|
289 else |
|
290 { |
|
291 TInt valueOffset = iValueReader.ReadUint32(aPtr + KTiffIfdEntryValueOffset); |
|
292 aEntry.iValue = valueOffset; |
|
293 |
|
294 aEntry.iValuePtr = NULL; |
|
295 |
|
296 if (valueOffset < iLongValuesStartOffset) |
|
297 iLongValuesStartOffset = valueOffset; |
|
298 if (valueOffset + valueSize > iLongValuesEndOffset) |
|
299 iLongValuesEndOffset = valueOffset + valueSize; |
|
300 } |
|
301 } |
|
302 |
|
303 TInt CTiffReadCodec::ReadLongValuesL(const TUint8*& aPtr, const TUint8*const aPtrLimit) |
|
304 { |
|
305 if(!iLoadedLongValuesSize) |
|
306 { |
|
307 if (iLongValuesSize<0) |
|
308 User::Leave(KErrCorrupt); |
|
309 |
|
310 if (iLongValuesSize>=(KMaxTInt/2)) // User alloc limit. |
|
311 User::Leave(KErrNoMemory); |
|
312 |
|
313 if (iLongValuesBuffer) |
|
314 { |
|
315 if (iLongValuesBuffer->Length() < iLongValuesSize) |
|
316 { |
|
317 delete iLongValuesBuffer; |
|
318 iLongValuesBuffer = NULL; |
|
319 } |
|
320 } |
|
321 |
|
322 if (!iLongValuesBuffer) |
|
323 iLongValuesBuffer = HBufC8::NewMaxL(iLongValuesSize); |
|
324 |
|
325 iLongValues = CONST_CAST(TUint8*, iLongValuesBuffer->Des().Ptr()); |
|
326 } |
|
327 |
|
328 TInt size = iLongValuesSize - iLoadedLongValuesSize; |
|
329 |
|
330 if (aPtr+size>aPtrLimit) |
|
331 size = aPtrLimit-aPtr; |
|
332 |
|
333 Mem::Copy(iLongValues + iLoadedLongValuesSize, aPtr, size); |
|
334 aPtr += size; |
|
335 |
|
336 iLoadedLongValuesSize += size; |
|
337 |
|
338 if (iLoadedLongValuesSize!=iLongValuesSize) |
|
339 return(KErrUnderflow); |
|
340 |
|
341 TTiffIfdEntry* entry = iIfdEntries; |
|
342 for(TInt i = 0 ; i < iNumIfdEntries; i+=1) |
|
343 { |
|
344 if (!entry->iValuePtr) |
|
345 { |
|
346 TInt entryPos = entry->iValue-iLongValuesStartOffset; |
|
347 if ((entryPos<0) || (entryPos>=iLongValuesSize)) |
|
348 User::Leave(KErrCorrupt); |
|
349 |
|
350 TInt valueSize = entry->TypeSize()*entry->iCount; |
|
351 if ((entryPos+valueSize)>iLongValuesSize) |
|
352 User::Leave(KErrCorrupt); |
|
353 |
|
354 entry->iValuePtr = iLongValues+entryPos; |
|
355 } |
|
356 |
|
357 entry++; |
|
358 } |
|
359 |
|
360 return(KErrNone); |
|
361 } |
|
362 |
|
363 void CTiffReadCodec::ProcessIfdL() |
|
364 { |
|
365 TTiffIfdEntry* entry = iIfdEntries; |
|
366 |
|
367 for (TInt i = 0; i < iNumIfdEntries; i+=1) |
|
368 { |
|
369 ProcessIfdEntryL(*entry); |
|
370 entry++; |
|
371 } |
|
372 } |
|
373 |
|
374 void CTiffReadCodec::ProcessIfdEntryL(const TTiffIfdEntry& aEntry) |
|
375 { |
|
376 switch(aEntry.iId) |
|
377 { |
|
378 case TTiffIfdEntry::ENewSubfileType: |
|
379 |
|
380 iFrameImageData->iNewSubfileType = IntegerIfdEntryValueL(aEntry); |
|
381 break; |
|
382 |
|
383 case TTiffIfdEntry::ESubfileType: |
|
384 { |
|
385 TUint32 type = IntegerIfdEntryValueL(aEntry) - 1; //Convert SubfileType to NewSubfileType |
|
386 if (type < 3) |
|
387 iFrameImageData->iNewSubfileType = type; |
|
388 } |
|
389 break; |
|
390 |
|
391 case TTiffIfdEntry::EImageWidth: |
|
392 |
|
393 iFrameImageData->iSizeInPixels.iWidth = IntegerIfdEntryValueL(aEntry); |
|
394 if (iFrameImageData->iSizeInPixels.iWidth<0) |
|
395 User::Leave(KErrCorrupt); |
|
396 break; |
|
397 |
|
398 case TTiffIfdEntry::EImageLength: |
|
399 |
|
400 iFrameImageData->iSizeInPixels.iHeight = IntegerIfdEntryValueL(aEntry); |
|
401 if (iFrameImageData->iSizeInPixels.iHeight<0) |
|
402 User::Leave(KErrCorrupt); |
|
403 break; |
|
404 |
|
405 case TTiffIfdEntry::EBitsPerSample: |
|
406 |
|
407 iFrameImageData->iBitsPerSample = IntegerIfdEntryValueL(aEntry); |
|
408 break; |
|
409 |
|
410 case TTiffIfdEntry::ECompression: |
|
411 |
|
412 iFrameImageData->iCompression = IntegerIfdEntryValueL(aEntry); |
|
413 break; |
|
414 |
|
415 case TTiffIfdEntry::EPhotometricInterpretation: |
|
416 |
|
417 iFrameImageData->iPhotometricInterpretation = IntegerIfdEntryValueL(aEntry); |
|
418 break; |
|
419 |
|
420 case TTiffIfdEntry::EFillOrder: |
|
421 |
|
422 iFrameImageData->iFillOrder = IntegerIfdEntryValueL(aEntry); |
|
423 break; |
|
424 |
|
425 case TTiffIfdEntry::EStripOffsets: |
|
426 { |
|
427 if (aEntry.iCount<=0) |
|
428 User::Leave(KErrCorrupt); |
|
429 iFrameImageData->iNumStrips = aEntry.iCount; |
|
430 |
|
431 TInt stripBytes = iFrameImageData->iNumStrips * sizeof(TTiffImageStrip); |
|
432 if ((stripBytes<0) || (stripBytes>=(KMaxTInt/2))) // User alloc limit. |
|
433 User::Leave(KErrNoMemory); |
|
434 |
|
435 ASSERT(iFrameImageData->iStripInfo==NULL); |
|
436 iFrameImageData->iStripInfo = HBufC8::NewMaxL(stripBytes); |
|
437 |
|
438 TInt i; |
|
439 TPtr8 stripInfoPtr(iFrameImageData->iStripInfo->Des()); |
|
440 iStripInfo = REINTERPRET_CAST(TTiffImageStrip*, CONST_CAST(TUint8*, stripInfoPtr.Ptr())); |
|
441 for(i = 0; i < iFrameImageData->iNumStrips; i++) |
|
442 iStripInfo[i].iOffset = IntegerIfdEntryValueL(aEntry,i); |
|
443 } |
|
444 break; |
|
445 |
|
446 case TTiffIfdEntry::ESamplesPerPixel: |
|
447 |
|
448 iFrameImageData->iSamplesPerPixel = IntegerIfdEntryValueL(aEntry); |
|
449 break; |
|
450 |
|
451 case TTiffIfdEntry::ERowsPerStrip: |
|
452 |
|
453 iFrameImageData->iRowsPerStrip = IntegerIfdEntryValueL(aEntry); |
|
454 break; |
|
455 |
|
456 case TTiffIfdEntry::EStripByteCounts: |
|
457 { |
|
458 TInt i; |
|
459 for(i = 0; i < iFrameImageData->iNumStrips; i++) |
|
460 iStripInfo[i].iLength = IntegerIfdEntryValueL(aEntry, i); |
|
461 } |
|
462 break; |
|
463 |
|
464 case TTiffIfdEntry::EXResolution: |
|
465 { |
|
466 TReal resolution = RationalIfdEntryValueL(aEntry); |
|
467 if (resolution != 0) |
|
468 iFrameImageData->iWidthInTwips = STATIC_CAST(TReal, iFrameImageData->iSizeInPixels.iWidth) * STATIC_CAST(TReal, KTwipsPerInch) / resolution; |
|
469 } |
|
470 break; |
|
471 |
|
472 case TTiffIfdEntry::EYResolution: |
|
473 { |
|
474 TReal resolution = RationalIfdEntryValueL(aEntry); |
|
475 if (resolution != 0) |
|
476 iFrameImageData->iHeightInTwips = STATIC_CAST(TReal, iFrameImageData->iSizeInPixels.iHeight) * STATIC_CAST(TReal, KTwipsPerInch) / resolution; |
|
477 } |
|
478 break; |
|
479 |
|
480 case TTiffIfdEntry::ET4Options: |
|
481 |
|
482 iFrameImageData->iT4Options = IntegerIfdEntryValueL(aEntry); |
|
483 break; |
|
484 |
|
485 case TTiffIfdEntry::ET6Options: |
|
486 |
|
487 iFrameImageData->iT6Options = IntegerIfdEntryValueL(aEntry); |
|
488 break; |
|
489 |
|
490 case TTiffIfdEntry::EResolutionUnit: |
|
491 |
|
492 if (IntegerIfdEntryValueL(aEntry) == 3) // Resolution units are centimeters rather than inches |
|
493 { |
|
494 const TReal KInchesPerCentimeter = 1.0 / 2.54; |
|
495 iFrameImageData->iWidthInTwips *= KInchesPerCentimeter; |
|
496 iFrameImageData->iHeightInTwips *= KInchesPerCentimeter; |
|
497 } |
|
498 break; |
|
499 |
|
500 default: |
|
501 break; |
|
502 } |
|
503 } |
|
504 |
|
505 TInt CTiffReadCodec::IntegerIfdEntryValueL(const TTiffIfdEntry& aEntry, TInt aIndex) const |
|
506 { |
|
507 if (aIndex >= aEntry.iCount) |
|
508 User::Leave(KErrCorrupt); |
|
509 |
|
510 TUint8* ptr = aEntry.iValuePtr; |
|
511 |
|
512 switch(aEntry.iType) |
|
513 { |
|
514 case TTiffIfdEntry::EByte: |
|
515 return(ptr[aIndex]); |
|
516 |
|
517 case TTiffIfdEntry::ESbyte: |
|
518 return(STATIC_CAST(TInt8, ptr[aIndex])); |
|
519 |
|
520 case TTiffIfdEntry::EShort: |
|
521 return(iValueReader.ReadUint16(ptr + aIndex * 2)); |
|
522 |
|
523 case TTiffIfdEntry::ESshort: |
|
524 return(iValueReader.ReadInt16(ptr + aIndex * 2)); |
|
525 |
|
526 case TTiffIfdEntry::ELong: |
|
527 return(iValueReader.ReadUint32(ptr + aIndex * 4)); |
|
528 |
|
529 case TTiffIfdEntry::ESlong: |
|
530 return(iValueReader.ReadInt32(ptr + aIndex * 4)); |
|
531 |
|
532 default: |
|
533 User::Leave(KErrCorrupt); |
|
534 return(0); |
|
535 } |
|
536 } |
|
537 |
|
538 TInt CTiffReadCodec::IntegerIfdEntryValueL(const TTiffIfdEntry& aEntry) const |
|
539 { |
|
540 if (aEntry.iCount != 1) |
|
541 User::Leave(KErrCorrupt); |
|
542 |
|
543 return(IntegerIfdEntryValueL(aEntry, 0)); |
|
544 } |
|
545 |
|
546 TReal CTiffReadCodec::RationalIfdEntryValueL(const TTiffIfdEntry& aEntry) const |
|
547 { |
|
548 if (aEntry.iCount != 1) |
|
549 User::Leave(KErrCorrupt); |
|
550 |
|
551 TUint8* ptr = aEntry.iValuePtr; |
|
552 |
|
553 switch(aEntry.iType) |
|
554 { |
|
555 |
|
556 case TTiffIfdEntry::ERational: |
|
557 { |
|
558 TInt numerator = iValueReader.ReadUint32(ptr); |
|
559 TInt denominator = iValueReader.ReadUint32(ptr + 4); |
|
560 if (!denominator) |
|
561 User::Leave(KErrCorrupt); |
|
562 return(STATIC_CAST(TReal, numerator) / STATIC_CAST(TReal, denominator)); |
|
563 } |
|
564 |
|
565 default: |
|
566 User::Leave(KErrCorrupt); |
|
567 return(0); |
|
568 |
|
569 } |
|
570 |
|
571 } |
|
572 void CTiffReadCodec::InitFrameL(TFrameInfo& aFrameInfo, CFrameImageData& aFrameImageData, TBool aDisableErrorDiffusion, CFbsBitmap& aBitmap, CFbsBitmap* /*aDestinationMask*/) |
|
573 { |
|
574 iImageInfo = &aFrameInfo; |
|
575 iImageData = &aFrameImageData; |
|
576 iTiffImageData = STATIC_CAST(TTiffImageData*, iImageData->GetFrameData(0)); |
|
577 |
|
578 TPtr8 stripInfoPtr(iTiffImageData->iStripInfo->Des()); |
|
579 iStripInfo = REINTERPRET_CAST(TTiffImageStrip*, CONST_CAST(TUint8*, stripInfoPtr.Ptr())); |
|
580 |
|
581 delete iDecoder; |
|
582 iDecoder = NULL; |
|
583 |
|
584 switch(iTiffImageData->iCompression) |
|
585 { |
|
586 case TTiffIfdEntry::EGroup3FaxCompression: |
|
587 |
|
588 if (iTiffImageData->iT4Options & TTiffIfdEntry::ET4TwoDimentionalCoding) |
|
589 iDecoder = CTiffGroup3Fax2dDecoder::NewL(*iTiffImageData); |
|
590 else |
|
591 iDecoder = CTiffGroup3Fax1dDecoder::NewL(*iTiffImageData); |
|
592 break; |
|
593 |
|
594 case TTiffIfdEntry::EGroup4FaxCompression: |
|
595 |
|
596 iDecoder = CTiffGroup4FaxDecoder::NewL(*iTiffImageData); |
|
597 break; |
|
598 |
|
599 default: |
|
600 User::Leave(KErrNotSupported); |
|
601 break; |
|
602 } |
|
603 |
|
604 const TSize destinationSize(aBitmap.SizeInPixels()); |
|
605 TInt reductionFactor = ReductionFactor(iImageInfo->iOverallSizeInPixels, destinationSize); |
|
606 iDecoder->DoNewFrameL(aBitmap, aDisableErrorDiffusion, reductionFactor); |
|
607 |
|
608 // ClearBitmapL(aBitmap, KRgbWhite); |
|
609 // No need to do something sensible when we do partial decodes on streaming |
|
610 // as tiff cannot return a partial image |
|
611 |
|
612 iCurrentStrip = 0; |
|
613 iNewStrip = ETrue; |
|
614 } |
|
615 |
|
616 void CTiffReadCodec::NewStripL() |
|
617 { |
|
618 iNewStrip = EFalse; |
|
619 iDecoder->NewStripL(iStripInfo[iCurrentStrip].iLength); |
|
620 } |
|
621 |
|
622 TFrameState CTiffReadCodec::ProcessFrameL(TBufPtr8& aSrc) |
|
623 { |
|
624 if (iNewStrip) |
|
625 NewStripL(); |
|
626 |
|
627 if (!iDecoder->ProcessStripL(&aSrc)) |
|
628 return(EFrameIncomplete); |
|
629 |
|
630 iCurrentStrip++; |
|
631 if (iCurrentStrip >= iTiffImageData->iNumStrips) |
|
632 return (EFrameComplete); |
|
633 |
|
634 iNewStrip = ETrue; |
|
635 iNewPosition = iStripInfo[iCurrentStrip].iOffset; |
|
636 |
|
637 return(EFrameIncompleteRepositionRequest); |
|
638 } |
|
639 |
|
640 void CTiffReadCodec::GetNewDataPosition(TInt& aPosition, TInt& /* aLength */ ) |
|
641 { |
|
642 aPosition = iNewPosition; |
|
643 } |
|
644 |
|
645 |
|
646 // TTiffIfdEntry. |
|
647 TInt TTiffIfdEntry::TypeSize() const |
|
648 { |
|
649 switch(iType) |
|
650 { |
|
651 case EByte: |
|
652 case ESbyte: |
|
653 case EAscii: |
|
654 case EUndefined: |
|
655 return(1); |
|
656 case EShort: |
|
657 case ESshort: |
|
658 return(2); |
|
659 case ELong: |
|
660 case ESlong: |
|
661 case EFloat: |
|
662 return(4); |
|
663 case ERational: |
|
664 case ESrational: |
|
665 case EDouble: |
|
666 return(8); |
|
667 default: |
|
668 return(0); |
|
669 } |
|
670 } |
|
671 |