?? faxfile.cpp
字號:
/*****************************************************************************
* RelayFax Open Source Project
* Copyright 1996-2004 Alt-N Technologies, Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the RelayFax Open
* Source License. A copy of this license is available in file LICENSE
* in the top-level directory of the distribution.
*
* RelayFax is a registered trademark of Alt-N Technologies, Ltd.
*
* Individual files and/or contributed packages may be copyright by
* other parties and subject to additional restrictions.
*****************************************************************************/
#include "stdafx.h"
#include "FaxFile.h"
#include "ClassOne.h"
//////////////////////////////////////////////////////////////////////
// Local definitions
//////////////////////////////////////////////////////////////////////
# define WHITE 0
# define BLACK 0xff
# define FAXFILE_OFFTREE 10000
# define FAXFILE_EOL 11000
# define FAXFILE_EOL2 11001
# define FAXFILE_HORZ 11002
# define FAXFILE_V_MINUS3 11003
# define FAXFILE_V_MINUS2 11004
# define FAXFILE_V_MINUS1 11005
# define FAXFILE_V_0 11006
# define FAXFILE_V_PLUS1 11007
# define FAXFILE_V_PLUS2 11008
# define FAXFILE_V_PLUS3 11009
# define FAXFILE_PASS 11010
typedef int NODE [][2] ;
//////////////////////////////////////////////////////////////////////
// Statics
//////////////////////////////////////////////////////////////////////
BYTE CFaxFile::s_LeadZero[256] = {
8, 7, 6, 6, 5, 5, 5, 5,
4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
BYTE CFaxFile::s_TrailZero[256] = {
8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,
1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,
2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,
1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,
3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,
1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,
2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
};
unsigned char CFaxFile::s_FlipTable[] = {
0, 128, 64, 192, 32, 160, 96, 224, 16,
144, 80, 208, 48, 176, 112, 240, 8,
136, 72, 200, 40, 168, 104, 232, 24,
152, 88, 216, 56, 184, 120, 248, 4,
132, 68, 196, 36, 164, 100, 228, 20,
148, 84, 212, 52, 180, 116, 244, 12,
140, 76, 204, 44, 172, 108, 236, 28,
156, 92, 220, 60, 188, 124, 252, 2,
130, 66, 194, 34, 162, 98, 226, 18,
146, 82, 210, 50, 178, 114, 242, 10,
138, 74, 202, 42, 170, 106, 234, 26,
154, 90, 218, 58, 186, 122, 250, 6,
134, 70, 198, 38, 166, 102, 230, 22,
150, 86, 214, 54, 182, 118, 246, 14,
142, 78, 206, 46, 174, 110, 238, 30,
158, 94, 222, 62, 190, 126, 254, 1,
129, 65, 193, 33, 161, 97, 225, 17,
145, 81, 209, 49, 177, 113, 241, 9,
137, 73, 201, 41, 169, 105, 233, 25,
153, 89, 217, 57, 185, 121, 249, 5,
133, 69, 197, 37, 165, 101, 229, 21,
149, 85, 213, 53, 181, 117, 245, 13,
141, 77, 205, 45, 173, 109, 237, 29,
157, 93, 221, 61, 189, 125, 253, 3,
131, 67, 195, 35, 163, 99, 227, 19,
147, 83, 211, 51, 179, 115, 243, 11,
139, 75, 203, 43, 171, 107, 235, 27,
155, 91, 219, 59, 187, 123, 251, 7,
135, 71, 199, 39, 167, 103, 231, 23,
151, 87, 215, 55, 183, 119, 247, 15,
143, 79, 207, 47, 175, 111, 239, 31,
159, 95, 223, 63, 191, 127, 255,
};
const int CFaxFile::s_WTree [][2] =
{
{1, 80}, {40, 2}, {21, 3}, {4, -2}, {16, 5}, {10, 6}, {7, -256}, {9, 8}, {-1344, -1408},
{-1216, -1280}, {11, 13}, {-576, 12}, {-832, -896}, {14, 15}, {-960, -1024}, {-1088, -1152}, {-1664, 17},
{18, 19}, {-448, -512}, {20, -640}, {-704, -768}, {32, 22}, {23, 28}, {24, 26}, {-24, 25},
{-49, -50}, {27, -25}, {-51, -52}, {29, -192}, {30, 31}, {-55, -56}, {-57, -58}, {-11, 33},
{34, 36}, {-27, 35}, {-59, -60}, {37, -18}, {38, 39}, {-1472, -1536}, {-1600, -1728}, {59, 41},
{49, 42}, {43, -10}, {47, 44}, {46, 45}, {-320, -384}, {-63, 0}, {-28, 48}, {-61, -62},
{56, 50}, {53, 51}, {52, -21}, {-43, -44}, {55, 54}, {-41, -42}, {-39, -40}, {-12, 57},
{58, -26}, {-53, -54}, {70, 60}, {64, 61}, {62, -1}, {-19, 63}, {-31, -32}, {68, 65},
{67, 66}, {-37, -38}, {-35, -36}, {-20, 69}, {-33, -34}, {74, 71}, {72, -13}, {-23, 73},
{-47, -48}, {77, 75}, {76, -22}, {-45, -46}, {79, 78}, {-29, -30}, {FAXFILE_EOL, FAXFILE_OFFTREE}, {86, 81},
{83, 82}, {-6, -7}, {-5, 84}, {85, -64}, {-14, -15}, {90, 87}, {88, -4}, {-9, 89},
{-16, -17}, {-3, 91}, {-128, -8}
} ;
const int CFaxFile::s_BTree [][2] =
{
{2, 1}, {-3, -2}, {4, 3}, {-1, -4}, {6, 5}, {-6, -5}, {9, 7}, {8, -7}, {-9, -8},
{31, 10}, {30, 11}, {12, -12}, {23, 13}, {17, 14}, {15, 0}, {-21, 16}, {-42, -43},
{21, 18}, {20, 19}, {-38, -39}, {-36, -37}, {-20, 22}, {-34, -35}, {-15, 24}, {27, 25},
{26, -19}, {-28, -29}, {29, 28}, {-26, -27}, {-128, -192}, {-10, -11}, {57, 32}, {45, 33},
{34, -14}, {41, 35}, {38, 36}, {37, -22}, {-40, -41}, {40, 39}, {-32, -33}, {-30, -31},
{-17, 42}, {44, 43}, {-62, -63}, {-48, -49}, {-13, 46}, {51, 47}, {48, -16}, {50, 49},
{-61, -256}, {-57, -58}, {55, 52}, {54, 53}, {-46, -47}, {-44, -45}, {-23, 56}, {-50, -51},
{FAXFILE_EOL, 58}, {75, 59}, {67, 60}, {61, -64}, {65, 62}, {64, 63}, {-1152, -1216}, {-1024, -1088},
{-54, 66}, {-896, -960}, {72, 68}, {71, 69}, {70, -53}, {-512, -576}, {-384, -448}, {-25, 73},
{74, -320}, {-1664, -1728}, {85, 76}, {80, 77}, {78, -24}, {-60, 79}, {-1536, -1600}, {83, 81},
{82, -59}, {-1408, -1472}, {-56, 84}, {-1280, -1344}, {-18, 86}, {89, 87}, {88, -55}, {-768, -832},
{-52, 90}, {-640, -704}
} ;
const int CFaxFile::s_TwoTree [][2] =
{
{1, FAXFILE_V_0}, {2, 3}, {4, FAXFILE_HORZ}, {FAXFILE_V_MINUS1, FAXFILE_V_PLUS1},
{5, FAXFILE_PASS}, {6, 7}, {8, 9}, {FAXFILE_V_MINUS2, FAXFILE_V_PLUS2},
{FAXFILE_EOL, FAXFILE_OFFTREE}, {FAXFILE_V_MINUS3, FAXFILE_V_PLUS3}
} ;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFaxFile::CFaxFile()
{
m_PageCount = 0;
m_PageBuffer = NULL;
m_tiff = NULL;
m_nSendEncoding = FAXAPI_ENC_CCITT_T6;
m_bGotData = false;
bitspersample = 1;
width = 1728;
length = 0;
fillorder = 1;
g3opts = 0;
compression = COMPRESSION_CCITTFAX3;
xres = 204.0f;
yres = 196.0f;
m_bFileHasData = false;
}
CFaxFile::~CFaxFile()
{
}
//////////////////////////////////////////////////////////////////////
// IsHiRes
//////////////////////////////////////////////////////////////////////
bool CFaxFile::IsHiRes(void)
{
short oures=(short)((2*xres)/yres);
if (oures<3)
return true;
return false;
}
//////////////////////////////////////////////////////////////////////
// ReadFirstHeader
//////////////////////////////////////////////////////////////////////
int CFaxFile::ReadFirstHeader(void)
{
m_bFileHasData = true;
m_tiff = TIFFOpen( m_sFaxFile.c_str(), "r" );
m_PageCount = 0;
m_bPartialPage = false;
m_nBlockCount = 0;
if ( m_tiff == NULL )
{
return 1;
}
// read TIFF tags
ReadIfd();
if( width != 1728 )
{
TIFFClose( m_tiff );
m_tiff = NULL;
return 2;
}
return 0;
}
//////////////////////////////////////////////////////////////////////
// ReadIfd
//////////////////////////////////////////////////////////////////////
int CFaxFile::ReadIfd (void)
{
TIFFGetField( m_tiff, TIFFTAG_IMAGEWIDTH, &width );
TIFFGetField( m_tiff, TIFFTAG_IMAGELENGTH, &length);
TIFFGetField( m_tiff, TIFFTAG_BITSPERSAMPLE, &bitspersample);
TIFFGetField( m_tiff, TIFFTAG_FILLORDER, &fillorder);
TIFFGetField( m_tiff, TIFFTAG_XRESOLUTION, &xres );
TIFFGetField( m_tiff, TIFFTAG_YRESOLUTION, &yres );
TIFFGetField( m_tiff, TIFFTAG_ROWSPERSTRIP, &rowsperstrip );
return 0;
}
//////////////////////////////////////////////////////////////////////
// ReadPage
//////////////////////////////////////////////////////////////////////
bool CFaxFile::ReadPage( bool bUseECM, int nClass1Speed, WORD wMinLineChars, bool bClassTwoZero, bool bClassTwo )
{
unsigned int nTotalBytes;
int i;
int nMaxBytes;
int nFlagLength = 0;
unsigned int nOffset;
int nDataBits = 0;
bool bFoundRTC = false;
if( m_bPartialPage )
{
m_nBlockCount++;
nOffset = m_nPartialPagePos;
}
else
{
m_nBlockCount = 0;
nOffset = 0;
}
if( m_MemFile.ReadPage( m_tiff, m_nSendEncoding ) != 0 )
{
return false;
}
nBitCntr = 0;
nOctet = 0;
if( m_PageBuffer != NULL )
{
delete[] m_PageBuffer;
}
if( bUseECM )
{
nFlagLength = (int)(((float)(cls1Speeds[nClass1Speed].dwSpeed / 8)) * 0.2f);
nMaxBytes = nFlagLength + // initial flags
(3 * 6) + // RCP frames
(255) * (m_nECMFrameSize + ECM_DATA_HDR + 3) +
2; // DLE ETX
nMaxBytes = nMaxBytes*2; // zero/DLE insertion fudge factor
}
else
{
nZcnt = 0;
nRTCCnt = 0;
//m_bFoundEndOfPage = false;
if( wMinLineChars > 0 )
{
nMaxBytes = (wMinLineChars * rowsperstrip + m_MemFile.GetDataLen()) *2 + 2;
}
else
{
nMaxBytes = m_MemFile.GetDataLen()*2 + 2;
}
}
m_PageBuffer = new unsigned char[nMaxBytes];
m_PagePtr = (unsigned char*)m_PageBuffer;
// Initial flag sequence
if( bUseECM )
{
for( i = 0; i < nFlagLength; i++ )
{
*m_PagePtr++ = HDLC_FLAG;
}
nZeroBitDeleteCntr = 0;
m_ECMBuffer.InitFrame();
m_ECMBuffer.SetLastSeq(0);
m_ECMBuffer.SetHighestSeq(0);
}
if( m_bPartialPage )
{
m_bPartialPage = false;
}
nTotalBytes = m_MemFile.GetDataLen();
unsigned char* pData = m_MemFile.GetData(nOffset);
i = nOffset;
while( i < nTotalBytes )
{
// todo: byte order?
if( bUseECM )
{
unsigned char c = s_FlipTable[ *pData ];
if( m_ECMBuffer.GetSize() == 0 )
{
AddFCDHeader();
}
AddByte( c, true );
if( m_ECMBuffer.GetSize() == m_nECMFrameSize + ECM_DATA_HDR )
{
unsigned short wFCS = m_ECMBuffer.GetFCS();
AddByte( wFCS & 0xff, false );
AddByte( (wFCS >> 8) & 0xff, false );
AddFlag(); // FLAG
m_ECMBuffer.InitFrame();
if( GetFrameCount() == 255 )
{
// Set Partial Page flag and save state
m_bPartialPage = true;
m_nPartialPagePos = i + 1;
}
}
}
else
{
unsigned char c = *pData;
if (nZcnt)
{
nZcnt += s_LeadZero[c];
if (c && (nZcnt < 11))
{
nRTCCnt = 0;
nZcnt = s_TrailZero[c];
}
}
else
{
nZcnt = s_TrailZero[c];
if (!nZcnt) nRTCCnt = 0;
}
if( nZcnt > 10 && c != 0 )
{
nDataBits += s_LeadZero[c] + 1;
if( nDataBits > 12 )
{
int nInsertBytes = wMinLineChars - (nDataBits/8);
for( int ii = 0; ii < nInsertBytes; ii++ )
{
*m_PagePtr++ = 0;
}
}
else
{
nRTCCnt++;
}
nDataBits = (7 - s_LeadZero[c]);
if (nRTCCnt > 5)
{
bFoundRTC = true;
//char szMsg[80];
//wsprintf( szMsg, "ReadPage: Found RTC at byte %d\n", ftell(m_fp) - nBytesRead + i + 1 );
//OutputDebugString( szMsg );
//IncrementImageLength( -5 );
//m_bFoundEndOfPage = true;
}
else
{
//IncrementImageLength();
}
nZcnt = s_TrailZero[c];
}
else
{
nDataBits += 8;
}
c = s_FlipTable[c];
// DLE Insertion
if( c == DLE )
{
*m_PagePtr++ = c;
}
*m_PagePtr++ = c;
}
pData++;
i++;
if( m_bPartialPage )
{
i = nTotalBytes;
}
}
if( bUseECM )
{
if( m_ECMBuffer.GetSize() > 0 )
{
unsigned short wFCS = m_ECMBuffer.GetFCS();
AddByte( wFCS & 0xff, false );
AddByte( (wFCS >> 8) & 0xff, false );
AddFlag(); // FLAG
}
// now add RCP frames
AddRCPFrames();
}
else
{
// TODO: class 1 or class 2.0 should include RTC, but not class 2
if( !bFoundRTC && !bClassTwo )
{
// OutputDebugString( "ReadPage adding RTC!\n" );
*m_PagePtr++ = s_FlipTable[ 0x00 ];
*m_PagePtr++ = s_FlipTable[ 0x10 ];
*m_PagePtr++ = s_FlipTable[ 0x01 ];
*m_PagePtr++ = s_FlipTable[ 0x00 ];
*m_PagePtr++ = s_FlipTable[ 0x10 ];
*m_PagePtr++ = s_FlipTable[ 0x01 ];
*m_PagePtr++ = s_FlipTable[ 0x00 ];
*m_PagePtr++ = s_FlipTable[ 0x10 ];
*m_PagePtr++ = s_FlipTable[ 0x01 ];
}
}
*m_PagePtr++ = DLE;
if( bClassTwoZero )
{
*m_PagePtr++ = MorePages() ? 0x2c : 0x2e;
}
else
{
*m_PagePtr++ = ETX;
}
m_PageBufferSize = m_PagePtr - m_PageBuffer;
return true;
}
//////////////////////////////////////////////////////////////////////
// ReadBadFrames
//////////////////////////////////////////////////////////////////////
bool CFaxFile::ReadBadFrames( int nClass1Speed )
{
// get the bad frame numbers from SeqMap and construct frames
int i,j,k;
BYTE b;
BYTE bit;
int nSeqNum = 0;
m_PagePtr = (unsigned char*)m_PageBuffer;
nBitCntr = 0;
nOctet = 0;
int nFlagLength = (int)(((float)(cls1Speeds[nClass1Speed].dwSpeed / 8)) * 0.2f);
for( i = 0; i < nFlagLength; i++ )
{
*m_PagePtr++ = HDLC_FLAG;
}
for( i = 0; i < SEQ_MAP_SIZE; i++ )
{
b = m_ECMBuffer.GetSeqMap()[i];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -