diff -r 735348f59235 -r 948c7f65f6d4 mmplugins/imagingplugins/codecs/TIFFCodec/TIFFFax.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmplugins/imagingplugins/codecs/TIFFCodec/TIFFFax.cpp Wed Sep 01 12:38:50 2010 +0100 @@ -0,0 +1,1198 @@ +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "TIFFFax.h" + +const TInt KMaxHuffmanCodeLength = 13; +LOCAL_C inline TUint32 GetMostSignificantBits(TUint32 aBits,TInt aNumBits) + { + return(aBits>>(32-aNumBits)); + } + + +// CTiffFax1dDecoder. +CTiffFax1dDecoder::~CTiffFax1dDecoder() + { + delete []iRunData; + delete iImageProcessor; + } + +void CTiffFax1dDecoder::ConstructL(const TTiffImageData& aImageData) + { + iImageData = &aImageData; + + if((iImageData->iBitsPerSample>1) || (iImageData->iSamplesPerPixel>1)) + User::Leave(KErrNotSupported); + + if(iImageData->iFillOrder==2) + iReverseBitsInByte = ETrue; + + // note officially should check for iImageData->iPhotometricInterpretation==EBlackIsZero + // and reverse black, white interpretation, but some TIFF writers break this rule and other + // readers ignore it + iBlack = KRgbBlack; + iWhite = KRgbWhite; + + iRowWidth = iImageData->iSizeInPixels.iWidth; + iRowNumber = 0; + iRunData = new (ELeave) TInt[iRowWidth+2]; + } + +void CTiffFax1dDecoder::DoNewFrameL(CFbsBitmap& aBitmap, TBool aDisableErrorDiffusion, TInt aReductionFactor) + { + delete iImageProcessor; + iImageProcessor = NULL; + + iImageProcessor = ImageProcessorUtility::NewImageProcessorL(aBitmap, aReductionFactor, EGray2, aDisableErrorDiffusion); + iImageProcessor->PrepareL(aBitmap,iImageData->iSizeInPixels); + } + +void CTiffFax1dDecoder::NewStripL(TInt aNumBytes) + { + if(!aNumBytes) + aNumBytes = KMaxTInt; + + iRowsRemaining = iImageData->iRowsPerStrip; + + TInt maxRows = iImageData->iSizeInPixels.iHeight-iRowNumber; + if( (iRowsRemaining>maxRows) || (iRowsRemaining<=0) ) + iRowsRemaining = maxRows; + + iPixelsStoredInRow = 0; + + iBitCache = 0; + iBitCacheLength = 0; + + iCodeType = ETiffFaxWhiteRun; + + CTiffFax1dDecoder::NewRow(); + } + +void CTiffFax1dDecoder::NewRow() + { + iColor = ETiffFaxWhiteRun; + iRunDataIndex = 0; + iRunData[0] = 0; + } + +TBool CTiffFax1dDecoder::ProcessStripL(TBufPtr8* aSrc) + { + const TUint8* sourceBuffer = aSrc->Ptr(); + iSourcePtr = sourceBuffer; + iSourcePtrLimit = iSourcePtr+aSrc->Length(); + + UseBits(0); + + FOREVER + { + switch(ProcessNextCode()) + { + case ETiffFaxUnderflow: + aSrc->Shift(iSourcePtr-sourceBuffer); + return(EFalse); + + case ETiffFaxInvalid: + User::Leave(KErrCorrupt); + + case ETiffFaxEndOfLine: + if(iPixelsStoredInRow==0) + continue; + + if(iPixelsStoredInRow!=iRowWidth) + User::Leave(KErrCorrupt); + + NewRow(); + + iPixelsStoredInRow = 0; + iRowNumber++; + iRowsRemaining--; + continue; + + case ETiffFaxPixelRun: + if(!iCodeCount) + continue; + + { + TInt n = iPixelsStoredInRow+iCodeCount; + + if(n>iRowWidth) + User::Leave(KErrCorrupt); + + if(iCodeType==ETiffFaxBlackRun) + { + iImageProcessor->SetMonoPixelRun(0,iCodeCount); + + if(!(iRunDataIndex&1)) + iRunDataIndex++; + } + else + { + iImageProcessor->SetMonoPixelRun(255,iCodeCount); + + if(iRunDataIndex&1) + iRunDataIndex++; + } + + iPixelsStoredInRow = n; + iRunData[iRunDataIndex] = n; + + if((n!=iRowWidth) || (iRowsRemaining!=1)) // Continue if not last pixel of image + continue; + } + + // else drop through.... + + case ETiffFaxEndOfFax: + iImageProcessor->FlushPixels(); + return(ETrue); + } + } + } + +LOCAL_D const TUint8 KByteFlip[256] = + { + 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, + 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, + 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, + 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, + 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, + 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, + 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, + 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, + 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, + 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, + 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, + 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, + 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, + 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, + 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, + 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff + }; + +void CTiffFax1dDecoder::UseBits(TInt aNumBits) + { + ASSERT(aNumBits<=iBitCacheLength); + + TInt validBits = iBitCacheLength-aNumBits; + TUint32 bits = iBitCache<=KMaxHuffmanCodeLength) + { + iBitCache = bits; + iBitCacheLength = validBits; + return; + } + + TInt shift = 32-validBits; + const TUint8* ptr = iSourcePtr; + + TInt numBytes = shift>>3; + TInt maxBytes = iSourcePtrLimit-ptr; + if(numBytes>maxBytes) + numBytes = maxBytes; + + iBitCacheLength = validBits+numBytes*8; + + const TUint8* ptrLimit = ptr+numBytes; + + if(iReverseBitsInByte) + { + while(ptr=0x02000000) + { + const THuffmanTable* table = &WhiteTables[GetMostSignificantBits(bits,4)]; + bits &= ~0xf0000000; // zero the 4 most significant bits + code = table->iCodes[GetMostSignificantBits(bits,4+table->iIndexBits)]; + } + else if(bits>=0x01000000) + { + bits &= ~0xff000000; // zero the 8 most significant bits + code = Common0000_0001[GetMostSignificantBits(bits,8+4)]; + } + else + return(ETiffFaxInvalid); + + TInt numBits = code&15; + + if(numBits>iBitCacheLength) + return(ETiffFaxUnderflow); + + UseBits(numBits); + + iCodeType = ETiffFaxWhiteRun; + iCodeCount = code>>4; + + if(iCodeCount<64) + iColor = ETiffFaxBlackRun; + + return(ETiffFaxPixelRun); + } + +TTiffFaxState CTiffFax1dDecoder::DecodeBlack() + { + TUint32 bits = iBitCache; + TUint16 code; + + if(bits&0xf0000000) + { + const THuffmanTable* table = &BlackTables[GetMostSignificantBits(bits,4)]; + bits &= ~0xf0000000; // zero the 4 most significant bits + code = table->iCodes[GetMostSignificantBits(bits,4+table->iIndexBits)]; + } + else if(bits&0xff000000) + { + const THuffmanTable* table = &BlackTables0000[GetMostSignificantBits(bits,8)]; + bits &= ~0xff000000; // zero the 8 most significant bits + code = table->iCodes[GetMostSignificantBits(bits,8+table->iIndexBits)]; + } + else + return(ETiffFaxInvalid); + + TInt numBits = code&15; + + if(numBits>iBitCacheLength) + return(ETiffFaxUnderflow); + + UseBits(numBits); + + iCodeType = ETiffFaxBlackRun; + iCodeCount = code>>4; + + if(iCodeCount<64) + iColor = ETiffFaxWhiteRun; + + return(ETiffFaxPixelRun); + } + +TTiffFaxState CTiffFax1dDecoder::DecodeEndOfLine() + { + if(iBitCache>=0x00200000) + return(ETiffFaxInvalid); + + FOREVER + { + if(iBitCacheLength<12) + return(ETiffFaxUnderflow); + if(iBitCache&0x00100000) + break; + UseBits(1); + } + + UseBits(12); + + iColor = ETiffFaxWhiteRun; + + iCodeCount = 1; + + if(iCodeType==ETiffFaxEndOfLineCode) + return(ETiffFaxEndOfFax); + + iCodeType = ETiffFaxEndOfLineCode; + return(ETiffFaxEndOfLine); + } + + +// CTiffFax2dDecoder. +CTiffFax2dDecoder::~CTiffFax2dDecoder() + { + delete []iReferenceRunData; + } + +void CTiffFax2dDecoder::ConstructL(const TTiffImageData& aImageData) + { + CTiffFax1dDecoder::ConstructL(aImageData); + iReferenceRunData = new (ELeave) TInt[iRowWidth+2]; + } + +void CTiffFax2dDecoder::NewStripL(TInt aNumBytes) + { + CTiffFax1dDecoder::NewStripL(aNumBytes); + CTiffFax2dDecoder::NewRow(); + } + +void CTiffFax2dDecoder::NewRow() + { + if(iRunDataIndex&1) + iRunDataIndex++; + iRunData[iRunDataIndex] = iRowWidth; + iRunData[iRunDataIndex+1] = iRowWidth; + + TInt* temp = iReferenceRunData; + iReferenceRunData = iRunData; + iRunData = temp; + + iReferenceRunDataIndex = 0; + iHorizontalCodeCount = 0; + iA0 = 0; + + CTiffFax1dDecoder::NewRow(); + } + +TTiffFaxState CTiffFax2dDecoder::Decode2d() + { + if(iHorizontalCodeCount) + return(DecodeHorizontal()); + + TUint32 bits = iBitCache; + TInt validBits; + TInt verticalOffset; + + switch(GetMostSignificantBits(bits,3)) + { + case 0: + + switch(GetMostSignificantBits(bits,7)) + { + case 0: + case 1: + return(DecodeEndOfLine()); + case 2: + verticalOffset = -3; + validBits = 7; + break; + case 3: + verticalOffset = 3; + validBits = 7; + break; + case 4: + case 5: + verticalOffset = -2; + validBits = 6; + break; + case 6: + case 7: + verticalOffset = 2; + validBits = 6; + break; + default: + if(iBitCacheLength<4) + return(ETiffFaxUnderflow); + UseBits(4); + return(DecodePass()); + } + + break; + + case 1: + if(iBitCacheLength<3) + return(ETiffFaxUnderflow); + UseBits(3); + iHorizontalCodeCount = 2; + return(DecodeHorizontal()); + + case 2: + + verticalOffset = -1; + validBits = 3; + break; + + case 3: + + verticalOffset = 1; + validBits = 3; + break; + + default: + + verticalOffset = 0; + validBits = 1; + break; + } + + if(validBits>iBitCacheLength) + return(ETiffFaxUnderflow); + + UseBits(validBits); + + return(DecodeVertical(verticalOffset)); + } + +TTiffFaxState CTiffFax2dDecoder::DecodeHorizontal() + { + TTiffFaxState returnValue; + + returnValue = Decode1d(); + if(returnValue!=ETiffFaxPixelRun) + return(returnValue); + + iA0 += iCodeCount; + + if(iCodeCount<64) + iHorizontalCodeCount--; + + if(iHorizontalCodeCount) + return(ETiffFaxPixelRun); + + TInt n = iA0; + if(n>=iRowWidth) + n = iRowWidth-1; + + TInt i = iReferenceRunDataIndex; + + while(iReferenceRunData[i]<=n) + i++; + + if(iColor==ETiffFaxBlackRun) + { + if(!(i&1)) + i++; + } + else + { + if(i&1) + i++; + } + + iReferenceRunDataIndex = i; + + return(ETiffFaxPixelRun); + } + +TTiffFaxState CTiffFax2dDecoder::DecodeVertical(TInt aDifference) + { + iA0 = iReferenceRunData[iReferenceRunDataIndex]+aDifference; + + iCodeCount = iA0-iPixelsStoredInRow; + iCodeType = iColor; + + if(iColor==ETiffFaxWhiteRun) + iColor = ETiffFaxBlackRun; + else + iColor = ETiffFaxWhiteRun; + + TInt n = iA0; + if(n>=iRowWidth) + n = iRowWidth-1; + + TInt i = iReferenceRunDataIndex; + + if(i) + i--; + else + i++; + + while(iReferenceRunData[i]<=n) + i += 2; + + iReferenceRunDataIndex = i; + + return(ETiffFaxPixelRun); + } + +TTiffFaxState CTiffFax2dDecoder::DecodePass() + { + iA0 = iReferenceRunData[iReferenceRunDataIndex+1]; + iReferenceRunDataIndex += 2; + + iCodeCount = iA0-iPixelsStoredInRow; + iCodeType = iColor; + + return(ETiffFaxPixelRun); + } + + +// CTiffGroup3Fax1dDecoder. +CTiffGroup3Fax1dDecoder* CTiffGroup3Fax1dDecoder::NewL(const TTiffImageData& aImageData) + { + if(aImageData.iT4Options & ~TTiffIfdEntry::ET4ContainsPaddedEols) + User::Leave(KErrNotSupported); + + CTiffGroup3Fax1dDecoder* decoder = new (ELeave) CTiffGroup3Fax1dDecoder; + + CleanupStack::PushL(decoder); + decoder->ConstructL(aImageData); + CleanupStack::Pop(); + + return(decoder); + } + +TTiffFaxState CTiffGroup3Fax1dDecoder::ProcessNextCode() + { + return(Decode1d()); + } + + +// CTiffGroup3Fax2dDecoder. +CTiffGroup3Fax2dDecoder* CTiffGroup3Fax2dDecoder::NewL(const TTiffImageData& aImageData) + { + if( (aImageData.iT4Options&~TTiffIfdEntry::ET4ContainsPaddedEols) != TTiffIfdEntry::ET4TwoDimentionalCoding ) + User::Leave(KErrNotSupported); + + CTiffGroup3Fax2dDecoder* decoder = new (ELeave) CTiffGroup3Fax2dDecoder; + + CleanupStack::PushL(decoder); + decoder->ConstructL(aImageData); + CleanupStack::Pop(); + + return(decoder); + } + +void CTiffGroup3Fax2dDecoder::NewStripL(TInt aNumBytes) + { + CTiffFax2dDecoder::NewStripL(aNumBytes); + iState = E1d; + } + +TTiffFaxState CTiffGroup3Fax2dDecoder::ProcessNextCode() + { + if(iState!=ESelect1d2d) + { + TTiffFaxState returnValue; + + if(iState==E1d) + returnValue = Decode1d(); + else + returnValue = Decode2d(); + + if(returnValue!=ETiffFaxEndOfLine) + return(returnValue); + + iState = ESelect1d2d; + } + + if(!iBitCacheLength) + return(ETiffFaxUnderflow); + + if(iBitCache&((TUint32)1<<31)) + iState = E1d; + else + iState = E2d; + + UseBits(1); + + return(ETiffFaxEndOfLine); + } + +void CTiffGroup3Fax2dDecoder::NewRow() + { + if(iState==E1d) + CTiffFax1dDecoder::NewRow(); + else + CTiffFax2dDecoder::NewRow(); + } + + +// CTiffGroup4FaxDecoder. +CTiffGroup4FaxDecoder* CTiffGroup4FaxDecoder::NewL(const TTiffImageData& aImageData) + { + if(aImageData.iT6Options!=0) + User::Leave(KErrNotSupported); + + CTiffGroup4FaxDecoder* decoder = new (ELeave) CTiffGroup4FaxDecoder; + + CleanupStack::PushL(decoder); + decoder->ConstructL(aImageData); + CleanupStack::Pop(); + + return(decoder); + } + +TTiffFaxState CTiffGroup4FaxDecoder::ProcessNextCode() + { + if((iA0==iRowWidth) && (iHorizontalCodeCount==0)) + return(ETiffFaxEndOfLine); + + return(Decode2d()); + } +