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

📄 tififd.cpp

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

	At the end of each scan line things start to get complicated.

	We always call vscale and see how many lines we have to Output.

	1) If we have no lines to Output we reset our indices (leaving our
	data intact for ORIng in with later lines) and return with indices,
	color and horizontal scaling reset.

	2) If we have multiple lines to Output, we start a loop for each
	Output line. The number of lines we Output at a time (as set in the
	DEVPARMS member total_lines) could be 1 (for raster devices such as
	screen and HP type lasers) or a multiple of 8 (for 24-pin dot-matrix
	and bubblejet printers that go in slices - note that as 9-pin dot
	matrix printer have a lower resolution than a fax they never have
	more than one line to Output and therefore don't get handled just
	yet). We have to handle these cases in different ways.

	i) For multislice printers which Output multiple lines in different
		bit positions we need to cater for two further cases.

		One is where we really do Output, which is only if we reach the
		last line of the slice (when DEVPARMS this_line decrements to 1) ;
		In this case, we call the Output function and then set the Output
		buffer to white space before looping.

		The other multislice case is where the slice isn't complete so we
		cannot call Output just yet.  What we do is to duplicate the bit
		of the slice we have reached into the next bit. This involves
		first finding out the bit we have reached from m_lnSliceBytes and
		this_line (which is stored in the m_lnLastSaveByte of bBit) and then ORing
		that back in at the next bit position (which might be in the
		following byte).

		For all multislice cases we then go on to the next m_lnRow and the
		next bit in the slice (increment m_lnRow and decrement DEVPARMS
		this_line) before carrying on with the loop.

	ii) For single-slice printers or screens we simply Output, increment
		m_lnRow, and loop again.  9-pin dot matric printers also come to here.

		We then have a special check to see if we really printed on a 8-slice
		printer (9-pin dot matrix) and if we did, we reset m_lnLastSaveByte to 0 and reset
		the Output buffer to white space.

	Finally, we reset indices to zero, reset bits unused to 8,
	reinitialize hor scaling, reinitialize colour to white, and go back.

	**************************************************************************/

	if (iRunlength==OUREOL)
	{
		m_ln2DIndex=0 ;
		m_ln2DBit=8 ;
		lnTemp = 1;//VerticalScale(device,(long int)m_lnRow) ;
		if (lnTemp==0)
		{
			m_lnIndex=0 ;
			m_lnThisbit=8 ;
			HorizScale(device,(long int)m_lnIndex) ;
			device->color=WHITE ;
			return 1;
		}
		for (; lnTemp>0 ; lnTemp--)
		{
			if (device->total_lines>8)
			{
				if (device->this_line==1)
				{
					if(!Output(device,m_lpFaxline,m_lnRow,m_lnLastSaveByte))
						return 0;
					m_lnRow++ ;
					for (m_lnIndex=0 ; m_lnIndex<m_lnLastSaveByte;
						m_lnIndex+=m_lnSliceBytes)
					{
						if (lnTemp==1) 
							m_lpFaxline[m_lnIndex]=0 ;
						else 
							m_lpFaxline[m_lnIndex]=
								(m_lpFaxline[m_lnIndex+(m_lnSliceBytes-1)]<<7) ;
						for (m_lnThisbit=1 ; m_lnThisbit<m_lnSliceBytes; 
							m_lnThisbit++) 
							m_lpFaxline[m_lnIndex+m_lnThisbit]=0 ;
					}
				}
				else
				{
					for (m_lnIndex=0 ; m_lnIndex<m_lnLastSaveByte ; 
						m_lnIndex+=m_lnSliceBytes)
					{
						if (lnTemp!=1)
						{
							m_lnThisbit=m_lnSliceBytes-
								(device->this_line/8) ;
							bBit=m_lpFaxline[m_lnIndex+m_lnThisbit] ;
							m_lnThisbit=device->this_line%8 ;
							if (m_lnThisbit==0) 
								m_lnThisbit=8 ;
							m_lnThisbit = 1 << (m_lnThisbit-1) ;
							bBit=(bBit&m_lnThisbit) ;
							if (bBit!=0) 
								bBit=1 ;
							m_lnThisbit=(device->this_line-1)%8 ;
							if (m_lnThisbit==0) 
								m_lnThisbit=8 ;
							if (m_lnThisbit>1) 
								bBit <<= (m_lnThisbit-1) ;
							m_lnThisbit=m_lnSliceBytes-
								((device->this_line-1)/8) ;
							m_lpFaxline[m_lnIndex+m_lnThisbit]=
								m_lpFaxline[m_lnIndex+m_lnThisbit]|bBit ;
						}
					}
					m_lnRow++ ;
					--device->this_line ;
				}
			}
			else
			{
				if(!Output(device,m_lpFaxline,m_lnRow,m_lnLastSaveByte))
					return 0;
				m_lnRow++ ;
			}
		}
		if ((device->this_line==device->total_lines)
			&&(device->total_lines<=8))
		{
			m_lnLastSaveByte=0 ;
			for (m_lnIndex=0;m_lnIndex<m_lnFaxBytes;m_lnIndex++)
				m_lpFaxline[m_lnIndex]=0 ;
		}
		m_lnIndex=0 ;
		m_lnThisbit=8 ;
		HorizScale(device,(long int)m_lnIndex) ;
		device->color=WHITE ;
		return 1;
	}

	/**************************************************************************

	Our final case is going to be normal run length.  We understabably
	ignore a run length of 0 (though it's a valid terminating run
	length).

	If we are decoding a 2-D file (we see that the cur_line current line
	buffer is in use) we must preserve a copy of the current scan line
	being decoded for use as the reference line when decoding the next
	scan line.  We keep this copy in the buffer pointed at by cur_line.
	We take a copy of the run length as it gets destroyed.  Then for
	white runs, we just skip the correct number of bits as cur_line
	buffer is always initialized to white space.  For black runs, we OR a
	series of 1s into the cur_line buffer until the run is exhausted -
	where we can we do this in octets, but where we cannot we OR single
	bits.  Then we carry on as normal with the original run-length.

	The run length is scaled horizontally - we ignore cases where it is
	scaled down to zero.

	We treat multislice printers (which Output more than one scan line at
	a time with different line occupying different bit positions)
	differently to raster devices like screens and lasers.

	Raster devices simply require setting the same number of consecutive
	bits as the run length in the Output buffer.  If the run is white,
	presetting the buffer to white space enables us to simply skip. If
	the run is black, we OR bit in till the run is used up. We also set
	the m_lnLastSaveByte marker to the final black position if it is greater than the
	last m_lnLastSaveByte value.

	Multislice printer require setting the identical bit in the same
	number of consecutive slices as the run length in the Output buffer.
	Again, if the run is white, presetting the buffer to white space
	enables us to skip, but we skip slices rather than bits.  If the run
	is black, we first set m_lnLastSaveByte and then OR a bit in the right position
	(we calculate the relative bit and slice position from this_line
	knowing that we have 8 lines to a byte) till the run is used up.


	**************************************************************************/

	if (!iRunlength) 
		return 1;

	if (device->cur_line!=NULL)
	{	
		lnCopyRun=iRunlength ;
		if (device->color==WHITE)
		{
			m_ln2DBit-=(lnCopyRun%8) ;
			m_ln2DIndex+=(lnCopyRun/8) ;
			if (m_ln2DBit<0)
			{
				m_ln2DBit+=8 ;
				m_ln2DIndex++ ;
			}
		}
		else for (;;)
		{
			while (m_ln2DBit>0)
			{
				device->cur_line[m_ln2DIndex]|=(1<<(m_ln2DBit-1)) ;
				m_ln2DBit-- ;
				if (!(--lnCopyRun)) 
					break;
			}
			if(lnCopyRun==0) 
				break ;
			m_ln2DIndex++;
			for (; lnCopyRun>8 ; lnCopyRun-=8) 
				device->cur_line[m_ln2DIndex++]=(char)0xff ;
			if (lnCopyRun==0) 
				break;
			m_ln2DBit=8;
		}
	}

	iRunlength=HorizScale(device,(long int)iRunlength) ;
	if (!iRunlength) 
		return 1;

	if (device->total_lines>1)
	{
		if (device->color==WHITE)
		{
			m_lnIndex+=(m_lnSliceBytes*iRunlength) ;
			if (m_lnIndex>m_lnFaxBytes) 
				m_lnIndex=m_lnFaxBytes ;
			return 1;
		}
		bBit = 1 ;
		m_lnThisbit=device->this_line%8 ;
		if (m_lnThisbit==0) 
			m_lnThisbit=8 ;
		if (m_lnThisbit>1) 
			bBit <<= (m_lnThisbit-1) ;
		m_lnThisbit=m_lnSliceBytes-(device->this_line/8) ;
		for (;;)
		{	
			if (m_lnLastSaveByte<=m_lnIndex) 
				m_lnLastSaveByte=(m_lnIndex+1) ;
			m_lpFaxline[m_lnIndex+m_lnThisbit]|=bBit ;
			if (m_lnIndex<m_lnFaxBytes) 
				m_lnIndex+=m_lnSliceBytes ;
			if (!(--iRunlength)) 
				return 1;
		}
	}
	if (device->color==WHITE)
	{
		m_lnThisbit-=(iRunlength%8) ;
		m_lnIndex+=(iRunlength/8) ;
		if (m_lnThisbit<0)
		{
			m_lnThisbit+=8 ;
			m_lnIndex++ ;
		}
		return 1;
	}
	for (;;)
	{
		if (m_lnLastSaveByte<=m_lnIndex) 
			m_lnLastSaveByte=(m_lnIndex+1) ;
		while (m_lnThisbit>0)
		{
			m_lpFaxline[m_lnIndex]|=(1<<(m_lnThisbit-1)) ;
			m_lnThisbit-- ;
			if (!(--iRunlength)) 
				return 1;
		}
		if (iRunlength==0) 
			return 1;
		m_lnIndex++ ;
		for (; iRunlength>8 ; iRunlength-=8) 
			m_lpFaxline[m_lnIndex++]=0xff ;
		if (iRunlength==0) 
			return 1;
		m_lnThisbit=8 ;
	}
}

/**************************************************************************/
// ----------------------------------------------------------------------------
// init the decoding buffer
//
BOOL CTifIFD::InitDecoding()
{
	// ALLOCATE OUTPUT MEMORY
	FreeOutImageMem();
	m_outImage.wWidth = (WORD)m_lImgWidth; 
	m_outImage.wLength = (WORD)m_lImgHeight; 

	long lnBufLen = ((m_outImage.wWidth+31)/32*32)/8*
		((long)(m_outImage.wLength+400))+ DECODE_BUF_EXTEND_LEN;
	
	m_outImage.lnBufLen = lnBufLen*4;
	m_outImage.lpImage = (LPBYTE) new BYTE[m_outImage.lnBufLen]; 	// why add 6000???

	if(m_outImage.lpImage == 0)
		return FALSE;

	memset(m_outImage.lpImage,0,m_outImage.lnBufLen);

	return TRUE;
}

int CTifIFD::HorizScale(DEVPARMS * device, long int run)
{
	static long int remainder ;
	static char borrow ;

	if (!run)
	{
		remainder=0 ;
		borrow=0 ;
		return(0) ;
	}

	run=(run*(long int)device->dest_width);
	run=run+remainder ;
	remainder=run%device->source_width ;
	run=run/device->source_width ;

	if ((!run)&&(!borrow))
	{
		run++ ;
		borrow++ ;
	}

	if ((run>1)&&(borrow!=0))
	{
		run-- ;
		borrow-- ;
	}

	return (int)(run) ;
}

int CTifIFD::VerticalScale(DEVPARMS * device, long int count)
{
	static long int remainder ;

	if (count<0)
	{
		remainder=0 ;
		return(0) ;
	}

	count=remainder+device->dest_height ;
	remainder=count%(device->source_height*device->res) ;
	count=count/(device->source_height*device->res) ;
	return (int)(count) ;
}

BOOL CTifIFD::Output(DEVPARMS * device, unsigned char * our_line, int our_row, int lsb)
{
	DWORD newWidth = (m_lImgWidth+31)/32*32/8;
	switch (device->id)
	{
	case DEVICE_MEMORY:
		{
			int nLen = ((m_outImage.wWidth+31)/32*32)/8*((long)(m_outImage.wLength+400)) 
				+ 4000 -m_lImgWidth/8;	// why add 4000
			
			if(m_outImage.lnCount >= m_outImage.lnBufLen)
			{
#if 0
				return FALSE;
#endif
			}			
			if(our_line == NULL)
			{
				return FALSE;
			}
			ASSERT((WORD)(m_outImage.lnCount + newWidth) < m_outImage.lnBufLen);

			memcpy(m_outImage.lpImage+m_outImage.lnCount,
				our_line,newWidth);

			m_outImage.lnCount += newWidth;
			break;
		}
   /* for uncompressed TIFF files, we simply fwrite the exact number
      of bytes to the output file and increment the count of lines in
      the image */
#if 0
   case U_TIFF :
		if ((fwrite (our_line,1,((m_lImgWidth+7)/*FAXWIDTH*//8),device->tiffile))==0)
		{
			fclose (device->tiffile);
			device->tiffile=NULL; 
		}
		device->ifd->ImageLength.value++;
		break;
#endif
	default:
	   break;
	}
	return TRUE;
}

BOOL CTifIFD::VertFlipBuf(BYTE* inbuf, UINT widthBytes, UINT height)
{   
	BYTE  *tb1;
	BYTE  *tb2;

	if (inbuf==NULL)
		return FALSE;

	UINT bufsize;

	bufsize=widthBytes;

	tb1= (BYTE *)new BYTE[bufsize];
	if (tb1==NULL) {
		return FALSE;
	}

	tb2= (BYTE *)new BYTE [bufsize];
	if (tb1==NULL) {
		return FALSE;
	}
	
	UINT row_cnt;     
	ULONG off1=0;
	ULONG off2=0;

	for (row_cnt=0;row_cnt<(height+1)/2;row_cnt++) {
		off1=row_cnt*bufsize;
		off2=((height-1)-row_cnt)*bufsize;   
		
		memcpy(tb1,inbuf+off1,bufsize);
		memcpy(tb2,inbuf+off2,bufsize);	
		memcpy(inbuf+off1,tb2,bufsize);
		memcpy(inbuf+off2,tb1,bufsize);
	}	

	delete [] tb1;
	delete [] tb2;

	return TRUE;
}        

void reverse (void *pointer,int lnCountdown)
{
	int lnCountup=0 ;
	BYTE bStore;
	LPBYTE lpAddress = (LPBYTE)pointer ;

	if (pointer==NULL) return;
	if (lnCountdown%2) return;

	while (lnCountup<lnCountdown)
	{
		lnCountdown-- ;
		bStore=lpAddress[lnCountdown] ;
		lpAddress[lnCountdown]=lpAddress[lnCountup] ;
		lpAddress[lnCountup]=bStore;
		lnCountup++ ;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -