mmplugins/imagingplugins/codecs/TIFFCodec/TIFFCodec.cpp
changeset 0 40261b775718
child 12 b74061f7f3d2
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     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