?? tififd.cpp
字號:
// TifIFD.cpp: implementation of the CTifIFD class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Huffman.h"
#include "TifIFD.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define DECODE_BUF_EXTEND_LEN 90000 // Old value is 6000
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTifIFD::CTifIFD()
{
//Initial class members
m_pEntry = NULL;
m_image.lpImage = NULL;
m_outImage.lpImage = NULL;
m_outImage.lnCount = 0;
m_lOldVRes = 0;
m_lOldHRes = 0;
m_lnRow = 0;
}
CTifIFD::~CTifIFD()
{
FreeMem();
}
// ---------------------------------------------------------------------------
// Load one tiff page from file
//
BOOL CTifIFD::LoadIFD(HANDLE hFile, WORD wByteOrderFlag)
{
register WORD i;
WORD wEntryCount;
DWORD dwNumOfByteRead;
WORD wLastTag;
//Initial values
WORD wIfdError=0;
short nCompression=1;
long int lnPhotometricInterpretation=-1;
long int lnHres=0;
long int lnVres=0;
long int lnRes[2];
short int nOures=1;
//free memory first.
FreeMem();
//Get EntryCount form file;
if(ReadFile(hFile,&wEntryCount,sizeof(WORD),
&dwNumOfByteRead,NULL)==0)
return FALSE;
//alloc memory for entry
m_pEntry = new TIFFMARK[wEntryCount];
if(m_pEntry == 0)
return FALSE;
wLastTag=0; // init last tag
//Initialize some value , add by zsxl
m_image.wBitOrder = 1;
m_image.wOptions = 4; // what's the meaing of 4
//end initialize
//Read and process entries.
for(i=0;i<wEntryCount;i++)
{
if(ReadFile(hFile,&m_pEntry[i],sizeof(TIFFMARK),
&dwNumOfByteRead,NULL)==0)
return FALSE;
if(wByteOrderFlag!=0) // "MM"
{
reverse(&m_pEntry[i].wTag,2);
reverse(&m_pEntry[i].wType,2);
reverse(&m_pEntry[i].dwCount,4);
if (m_pEntry[i].wType==IFD_SHORT)
reverse(&m_pEntry[i].dwValue,2) ;
if ((m_pEntry[i].wType==IFD_LONG)||
(m_pEntry[i].wType==IFD_RATIONAL))
reverse(&m_pEntry[i].dwValue,4) ;
}
if (m_pEntry[i].wTag <= wLastTag)
{
wIfdError=1 ;
break ;
}
wLastTag=m_pEntry[i].wTag;
if (m_pEntry[i].dwCount==1)
{
//if (cpu_order=='M')
if(wByteOrderFlag!=0) // "MM"
{
if (m_pEntry[i].wType==IFD_BYTE)
m_pEntry[i].dwValue>>=24 ;
else if (m_pEntry[i].wType==IFD_SHORT)
m_pEntry[i].dwValue>>=16 ;
}
}
switch (m_pEntry[i].wTag)
{
case ImageWidth_tag: // ImageWidth must be 864, there is no default
m_image.wWidth=(unsigned short int)m_pEntry[i].dwValue;
break;
case ImageLength_tag: // ImageLength must be strip size, there is no default
m_image.wLength=(unsigned short int)m_pEntry[i].dwValue;
break;
case BitsPerSample_tag: // BitsPerSample must be 1, default is ok
if ((unsigned short int)m_pEntry[i].dwValue!=1)
wIfdError=1 ;
break;
case Compression_tag: // Compression must be 3 or 4 ,the default is no good
nCompression = (short int)m_pEntry[i].dwValue;
break;
case PhotometricInterpretation_tag: /* PhotometricInterpretation must be 0 */
/* there is no default */
lnPhotometricInterpretation=(unsigned short int)m_pEntry[i].dwValue;
break;
case FillOrder_tag: // FillOrder can be 1 or 2 , take what comes
m_image.wBitOrder=(unsigned short)m_pEntry[i].dwValue;
break;
case StripOffsets_tag: /* StripOffsets we need to know */
/* there is no default */
m_image.dwOffset=m_pEntry[i].dwValue;
break;
case SamplesPerPixel_tag: /* SamplesPerPixel must be 1 */
/* default is ok */
if((unsigned short int)m_pEntry[i].dwValue!=1)
wIfdError=1 ;
break ;
case RowsPerStrip_tag: /* RowsPerStrip must be single strip */
/* default is ok */
if (m_image.wLength<m_pEntry[i].dwValue)
wIfdError=1 ;
break ;
case StripByteCounts_tag: /* Positive StripByteCounts we do need */
if (m_pEntry[i].dwValue==0)
wIfdError=1;
m_image.dwByteCount=m_pEntry[i].dwValue;
break ;
case XResolution_tag: /* Xresolution pointer to rational */
lnHres = m_pEntry[i].dwValue;
break ;
case YResolution_tag: /* Yresolution pointer to rational */
lnVres = m_pEntry[i].dwValue;
break ;
case T4Options_tag: /* T4Options OK */
/* default is ok */
m_image.wOptions= (unsigned short)m_pEntry[i].dwValue&1;
break ;
case PageNumber_tag: /* PageNumber [0] */
/* optional field */
m_image.wPage= (unsigned short int)m_pEntry[i].dwValue;
break ;
default: /* we don't care about any other tags */
break ;
}
}
m_lImgWidth = m_image.wWidth;
m_lImgHeight = m_image.wLength;
if ((ReadFile(hFile,&m_image.dwIfd,sizeof(DWORD),&dwNumOfByteRead,NULL))==0)
return FALSE;
if(wByteOrderFlag!=0) // "MM"
reverse(&m_image.dwIfd,4);
if ((nCompression!=3)&&(nCompression!=4)) // not the fax 3 & 5 format
{ // 1: uncompressed format, 2: huffman format, 3: & 4: fax tiff format
wIfdError=1;
}
if (nCompression==4)
m_image.wOptions=2;
if (lnHres==0)
{
wIfdError=1;
}
else
{
if(SetFilePointer(hFile,lnHres,NULL,FILE_BEGIN)==
0xFFFFFFFF)
return FALSE;
if((ReadFile(hFile,lnRes,4*2,&dwNumOfByteRead,NULL))==0)
return FALSE;
if(wByteOrderFlag!=0) // "MM"
{
reverse(&lnRes[0],4) ;
reverse(&lnRes[1],4) ;
}
if(lnRes[1] == 0) // This is not a good method, just for error .tiff file
lnHres = 200;
else
lnHres=(lnRes[0]/lnRes[1]);
m_lHRes = lnHres;
}
if (lnVres==0)
{
wIfdError=1 ;
}
else
{
if(SetFilePointer(hFile,lnVres,NULL,FILE_BEGIN)==
0xFFFFFFFF)
return FALSE;
if ((ReadFile(hFile,lnRes,4*2,&dwNumOfByteRead,NULL))==0)
return FALSE;
if(wByteOrderFlag!=0) // "MM"
{
reverse(&lnRes[0],4) ;
reverse(&lnRes[1],4) ;
}
if(lnRes[1] == 0) // This is not a good method, just for error .tiff file
lnVres = 200;
else
lnVres=(lnRes[0]/lnRes[1]);
m_lVRes = lnVres;
}
// check the error flag and set the image offset to 0 if we haven't
// an acceptable class F IFD
if(wIfdError)
{
m_image.dwOffset=0;
return FALSE;
}
else
{
if(lnVres == 0)
lnVres = 200;
nOures = (short)(((float)lnHres/(float)lnVres)+0.5);
if(nOures<2)
m_image.wOptions |= 0x80 ;
}
if (SetFilePointer(hFile,m_image.dwOffset,
NULL,FILE_BEGIN)==0xFFFFFFFF)
{
m_image.dwByteCount=0;
return FALSE;
}
else
{
m_image.lpImage = new BYTE[m_image.dwByteCount];
if(m_image.lpImage==0)
return FALSE;
if((ReadFile(hFile,m_image.lpImage,m_image.dwByteCount,
&dwNumOfByteRead,NULL))==0)
return FALSE;
}
if(m_image.dwIfd != 0)
{
if(SetFilePointer(hFile,m_image.dwIfd,
NULL,FILE_BEGIN)==0xFFFFFFFF)
return FALSE;
}
// used for reserve the old value
m_lOldHRes = m_lHRes;
m_lOldVRes = m_lVRes;
return TRUE;
}
// ---------------------------------------------------------------------------
//
//
void CTifIFD::FreeMem()
{
if(m_pEntry!=NULL)
{
delete[] m_pEntry;
m_pEntry = NULL;
}
if(m_image.lpImage != NULL)
{
delete m_image.lpImage;
m_image.lpImage = NULL;
}
FreeOutImageMem();
}
// ----------------------------------------------------------------------------
// Free output image memory
//
void CTifIFD::FreeOutImageMem()
{
if(m_outImage.lpImage != NULL)
{
delete m_outImage.lpImage;
m_outImage.lpImage = NULL;
m_outImage.wWidth=0;
m_outImage.wLength=0;
m_outImage.lnCount=0;
}
}
// ----------------------------------------------------------------------------
// Unpack a tiff page image, then make into a dib memory block
//
HDIB CTifIFD::UnpackAsDib()
{
register int i,j;
int lnDots_left = m_lImgWidth; // fax width
int lnCode = 0;
int lnResync, lnA0, lnB1, lnB2, lnHorz_runs;
BYTE bOctet, bRef_color, bThis_bit, bCoding_scheme=1;
DEVPARMS device;
NODE *tree= (NODE *)&gWTree;
char* cpTwolines;
char *cpRef_line ;
char *cpTmp_line ;
LPBYTE lpSrcBuf;
DWORD dwByteCount;
/* Preliminaries for the whole file - check for a valid fax image in
file, initialize various components of our DEVPARMS structure.
Initialize our Output device with a get_device call, and initialize
our Output logic with a ProcessLine INIT call. The we can begin the main
loop for each image in the file */
if(m_image.lpImage==NULL)
{
return NULL;
}
// restore the old value first
m_lHRes = m_lOldHRes;
m_lVRes = m_lOldVRes;
m_image.wWidth = (WORD)m_lImgWidth;
m_image.wLength = (WORD)m_lImgHeight;
device.hFile = NULL;
device.id = DEVICE_MEMORY;
device.color = WHITE ;
device.res = 1+(m_image.wOptions>>7) ;
device.source_width = m_lImgWidth; // fax width & length
device.source_height = m_lImgHeight;
device.total_lines = 1;
device.dest_width = m_lImgWidth; // fax width
device.dest_height = m_lImgHeight; // fax length
if (! ProcessLine(&device,INIT))
return NULL;
// init decoding first
if(! InitDecoding())
return NULL;
/* Preliminaries for each image in the file - fseek to the start of
the image. (If we can't we give it a zero length and ignore). If a
2-D or a T.6 image, set up pointers to the reference line and the
current line. If a T.6 image (which has no initial EOL) set up our
key variables to the right initial state. If a T.4 image just set
our resync flag, which forces us to ignore everything until the next
EOL code */
cpTwolines = new char[((m_lImgWidth+7)/8)*2]; // used for some condition
if(m_image.wOptions&3)
{
memset (cpTwolines,0x00,((m_lImgWidth+7)/8)*2);
cpRef_line= &cpTwolines[0] ;
device.cur_line= &cpTwolines[(m_lImgWidth+7)/8] ;
}
else
{
device.cur_line= NULL ;
}
// will not be used again
delete cpTwolines;
if(m_image.wOptions&2)
{
bCoding_scheme= 2 ;
lnResync= 0 ;
device.color= WHITE ;
lnDots_left= m_lImgWidth;/*FAXWIDTH*/ ;
tree= (NODE *)&gTwoTree ;
lnHorz_runs= lnCode= 0 ;
lnA0= (-1) ;
}
else
{
lnResync= 1 ;
}
/* This is the main loop for processing an image - we have a double
loop, with the outer executing for each byte (octet) in the image,
and the inner executing 8 times for each octet and processing each
bit in turn. The only exits before a completed image are on
physical end of file, on error if writing Output file, or on EOFB
in a T.6 file. */
lpSrcBuf=m_image.lpImage;
dwByteCount=m_image.dwByteCount;
for (;dwByteCount;dwByteCount--)
{
if ((device.id== U_TIFF)&&(device.hFile== NULL))
break;
bOctet=*lpSrcBuf++; // get the source data
if (m_image.wBitOrder==2)
bOctet=gBackward[bOctet];
for(i=0; i<8;i++,bOctet<<= 1) // decode each bit
{
/* We have three checks for every bit in the file. First we
check for EOL in T.6 mode - there is no EOL marker, but we
should have exactly the right number of dots decoded.
There should be none left in the line. If we pass the
test we Output the line and reset our key variables */
if((m_image.wOptions&2)&&(lnHorz_runs==0)&&(lnDots_left==0))
{
if(! ProcessLine(&device, OUREOL))
return NULL;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -