⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tififd.cpp

📁 < 精通Visual C++图象处理编程>>(第3版)第八章配套源码,希望对学过此书的同学或开发人员有帮助
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -