📄 tififd.cpp
字号:
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 + -