Beruflich Dokumente
Kultur Dokumente
Galina Istatkova
Abstract: MFC program SFFViewer, intended for reading, decompressing and visualization of fax
document compressed with modified Huffman code and saved in SFF file format, is described. Two C++
classes – CSFFFile and CSFFPage, in which the most part of functionality is collected, are discussed in
more details. The code of three methods of CSFFPage, intended for Huffman data decompression, creation
of CBitmap object, needed for one page of document visualization, saving the graphic image of fax
document’s page in BMP file, are given and commented. The design of the program allows the same
structure to be applied for viewer program development of other type of compressed graphic images.
Key words: Modified Huffman code decompressing, C++ Visual, Computer Graphic, Object-oriented
programming.
INTRODUCTION
With the low cost of fax modems in the past couple of years, a great many of today's
faxed documents never touch actual paper; they are sent and received purely as electronic
images between two computers. Structured Fax File (SFF) is one of the files’ formats
intended for a representation and an exchanging fax images between computers. It
consists of information defining the page structure and compressed data of the fax
document. Data compression was a concern for faxes from the beginning because
scanned image data tends to be rather large. Statistical evidence showed that the typical
page was composed of many small black images (runs of pixels) and fewer long white
runs. By using a modified Huffman encoding scheme [1] (Modified Huffman coding
combines the variable length of Huffman codes with the run-length encoding scheme), the
statistical probability of run lengths could be used to achieved a reasonable compression
ratio: frequently occurring run lengths were assigned the shortest codes and infrequently
occurring run lengths were assigned the longest codes. The statistical information used for
encoding fax images is a fixed table so that it does not have be transmitted with each page
(of course, being fixed information it will not always be optimal for all images). The
encoding of the runs of pixels as Huffman (minimum redundancy) codes presents a
problem for writing an efficient decoder since the codes do not fall neatly on byte
boundaries. The codes are also designed to not need separators (prefix codes); each code
is uniquely decodable. The codes can be decoded by picking up one bit at a time and
traversing the Huffman binary tree; branching left for a zero and right for a one. This
solution is the most obvious one from the creation of the codes, but is definitely not the
most efficient. The nature of Huffman codes allows a more elegant solution to this
problem. Since the codes are designed to be unique sequences of bits when decoded
from start to finish, it’s possible to construct a table for decoding each code in one iteration
instead of one iteration per bit. By using the code as an address to index into the table, the
bit sequence might be decoded in one step. The SFFViewer program developed with
Visual Microsoft C++ is intended to read, to decompress and to render fax pages from SFF
files. The program was designed using object-oriented approach and the most important
functionality is collected in two classes CSFFFile and CSFFPage. The class CSFFPage is
intended to process one page from SFF file and objects of this class are embedded in
CSFFFFile class. Because the most interesting algorithms – decompressing Huffman
data, rendering fax pages, saving pages in BMP file format, are implemented in CSFFFile
and CSFFPage classes, describing of these classes is the main goal of this report.
MODIFIED HUFFMAN CODE DECOMPRESSING ALGORITHM
Compressed fax page - Huffman data, are saved in the array of bytes and the
pointers to every line of Huffman data in the array of doubles:
- I.4-1 -
International Conference on Computer Systems and Technologies - CompSysTech’07
//Huffman data
CDWordArray indexes; //indexes in the data of the lines
LPBYTE data; //allocated with malloc, because we use realloc
Decompressing algorithm for one line of Huffman data is implemented as the method
of SFFPage class:
void CSFFPage::SetPixels (BYTE* row, int index) const
{
int rowSize = indexes[index + 1] - indexes[index];// Length of Huffman record
x += sCode;
sCode = ClimbBlack(inbuf, &iBit, &iOff,rowSize);
if (iLen < 0)
{
lBit |= rBit;
rBit = 0xff;
}
p = &row[x >> 3];
*p++ &= lBit;
while (iLen > 0)
{
*p++ = 0;
iLen--;
}
*p &= rBit;
x += sCode;
} // end of while
}
Input argument – index, defines the line of Huffman data to be decompressed. This
line is passed in bytes array inbuf to external functions ClimbWhite and ClimBlack
implemented in procedural form of the library, in which the black and white tables (tables
with codes for black and white runs) needed for decompressing are defined. In one
- I.4-2 -
International Conference on Computer Systems and Technologies - CompSysTech’07
iteration of outer while cycle, two codes – for one white and one black runs, are
decompressed. This approach could be applied because Huffman data for fax images
always start with white run, followed by the black one. After decompression, the black run
is written to the output buffer, is given by pointer row. The output buffer is used for creation
of bitmapped image of fax image, in which black runs are corresponded to bits set in 0.
The length of the black runs is returned by ClimBlack and the length of the white runs is
returned by ClimWhite. To set bits in 1 for white runs isn’t necessary because the output
buffer for bitmapped image of fax page is filled with 0xFF. The method SetPixels is used
as the base operation in creation and rendering of bitmapped images of fax pages.
CREATION OF BITMAPPED IMAGE OF FAX DOCUMENT PAGES
Bitmapped graphics format (BMP or DIB) is used internally by the Microsoft Windows
graphics subsystem (GDI), and used commonly as a simple graphics file format. MFC
library contains class CBitmap, intended especially for working with bitmapped images and
allowed programmers to create and visualize BMP images very easy [2]. The algorithm of
the fax page bitmapped image creation might be parted in few steps:
1. The buffer size’s calculation.
2. Allocate memory needed for creation bitmapped image.
3. Filling buffer with 0xFF.
4. Creation bitmapped image in buffer, using SetPixels.
5. Create CBitmap object and fill it with bitmapped images of fax page from the
buffer.
This algorithm is implemented as the method of CFFPage class, code of which is
given below:
CBitmap* CSFFPage::GetBitmap () const
{
int width = GetWidth (PIXEL);
int height = GetHeight(PIXEL);
int bytesInRow = ( width % 16 )?( (width / 16 + 1) * 2):(width / 16* 2);
BYTE* buf = (BYTE*)malloc (bytesInRow * height);
memset (buf, 0xFF, bytesInRow * height);
for (int i = 0; i < height; i++)
{
SetPixels (buf + i * bytesInRow, i);
}
CBitmap *pBmp = new CBitmap;
pBmp->CreateBitmap (bytesInRow * 8, height, 1, 1, buf);
free (buf);
return pBmp;
}
The bitmapped image of fax page created in the buffer buf is saved to CBitmap object with
the method of CBitmap class CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT
nBitcount, const void* lpBits ). This method initializes a device-dependent memory bitmap
that has the specified width, height, and bit pattern. For monochrome bitmap, the
parameters nplanes (the number of color planes), nBitcount (the number of bit for every
color) are set in 1. Although the created bitmap cannot be directly selected in a display
device for rendering, it can be selected as the current bitmap for a memory device context
by using CDC::SelectObject method in OnDraw function of CView class, which is intended
to render images in MFC object-oriented program.
VISUALIZATION OF BITMAPPED IMAGES OF FAX DOCUMENTS
The part of OnDraw method code, used for visualization fax page images, saved in
CBitmap object is given below:
void CSFFViewerView::OnDraw(CDC* pDC)
{
// Select CBitmap object for currently selected page of fax document
- I.4-3 -
International Conference on Computer Systems and Technologies - CompSysTech’07
CBitmap* pbitmapold = m_pcdcMemory ->SelectObject(m_ppageBmp);
// Copy the bitmapped images into the destination rectangle in display context
pDC->StretchBlt (ptBitmap.x,ptBitmap.y,distsize.cx,distsize.cy, m_pcdcMemory,
0, 0,m_sourcesize.cx,m_sourcesize.cy, SRCCOPY);
//Deselect object
m_pcdcMemory -> SelectObject(pbitmapold);
}
The main window of SFFViewer program with bitmapped image of one page of the
decompressed SFF file is given on fig. 1.
- I.4-4 -
International Conference on Computer Systems and Technologies - CompSysTech’07
// and fills the BITMAPINFOHEADER, BITMAPFILEHEADER structures
int width = GetWidth (PIXEL);
int height = GetHeight(PIXEL);
//! Rows in DIB must be padded to 4-byte boundary
int bytesInRow = ( width % 32 )?( (width / 32 + 1) * 4):(width / 32* 4);
BYTE* buf = (BYTE*)malloc (bytesInRow * height);
memset (buf, 0xFF, bytesInRow * height);
int i,j;
// Allocate temporary buffer for mirror row in X-direction
BYTE* tmp = (BYTE*)malloc (bytesInRow);
BYTE* curbuf;
if (m_nAngle)//m_nAngle=180 -> first row in Dib is the top row of page
{
for ( i = 0; i < height; i++)
{
curbuf = buf + i * bytesInRow;
SetPixels (curbuf, i);
//Makes byte's mirror in X-direction
for ( j = 0; j < bytesInRow; j++)
{
tmp[j] = curbuf[bytesInRow-j-1];
}
// Makes bits mirror in X-direction
DoMirror( tmp, bytesInRow );
memcpy(curbuf,tmp,bytesInRow);
}
}
else // m_nAngle=0 -> first row in Dib is the bottom row of page
{
for ( i = height-1; i >=0; i--)
- I.4-5 -
International Conference on Computer Systems and Technologies - CompSysTech’07
try {
pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
pFile->Write((LPVOID) &bi, sizeof(BITMAPINFOHEADER));
pFile->Write((LPVOID) &black, sizeof(DWORD));
pFile->Write((LPVOID) &white, sizeof(DWORD));
- I.4-6 -