Read/write PCX Image File Format
The PCX Image File Format first appeared in the PC paintbrush drawing software developed by zsoft. Because of its powerful functionality, it was successfully transplanted to the Windows operating system,
PCX is one of the earliest color-supported image formats. PCX has become a popular image format.
For programmers who develop Image Browsing and processing software, the most basic topic is how to read and store PCX image formats. Based on my understanding of PCX image formats,
The code has been developed to be useful to readers. Due to space limitations, the file format is not described here. For details, refer to the number of related codes.
The Code is as follows, simple explanation after calling the method section, the level is limited, please forgive me; my mailbox is: cadinfo@263.net, welcome to discuss.
========================================================== ======================
/*************************************** *************************************
* Function name: loadpcxline (ppcxhead ppcxhdr, lpbyte ppcximg, lpbyte ppcxbits) const
*
* Parameter: ppcxhead ppcxhdr-pointer to the pcxhead structure! Null: Imports bitplane, byteperline, => clscanlinesize
* Lpbyte ppcximg-pointer to PCX image zone! Null, RLE compression encoding, position increment + = rec.
* Obtain the first address pointer before calling:
* Lpbyte ppcxbits-pointer to the dib data zone, increasing by scanline Length
*
* Return: uint rec-returns the number of bytes after each row is extracted.
*
* Description: decodes RLE Based on the PCX Image Data Pointer.
**************************************** ************************************/
Uint cpcximage: loadpcxline (ppcxhead ppcxhdr, lpbyte ppcximg, lpbyte ppcxbits) const
{
Assert (ppcxhdr! = NULL & ppcximg! = NULL & ppcxbits! = NULL );
// Because in bitmap bits order, it's Blue => Green => Red
// However PCX is Red => Green => blue so use decrease order
//-----------------------------------------
Uint LPOS (0), // The total number of records stored in ppcxbits
IX (0), // record the serial number of each bit of the plane bytes
Rec (0); // read _ ppcximg _ byte number
For (int bp = ppcxhdr-> BitPlane-1; BP> = 0; BP --)
{
// RLE decoding ======
IX = 0;
While (IX <ppcxhdr-> byteperline)
{
Byte uivalue = ppcximg [Rec ++];
If (uivalue & 0xc0) = 0xc0) // determine whether to set 0xc0 for a high byte
{
Uivalue = uivalue & 0x3f; // duplicate Calculation
Byte color = ppcximg [Rec ++]; // extract color
// Store it in the memory Dib
For (byte brepeat = 0; brepeat <uivalue; brepeat ++)
{
Ppcxbits [(IX ++) * ppcxhdr-> bitplane + bp] = color;
LPOS ++;
}
}
Else
{
Ppcxbits [(IX ++) * ppcxhdr-> bitplane + bp] = uivalue;
LPOS ++;
}
}
}
Return REC;
}
/*************************************** *************************************
* Function name: packpcxline (ppcxhead ppcxhdr, lpbyte ppcximg, lpbyte ppcxbits) const
*
* Parameter: ppcxhead ppcxhdr-pointer to the pcxhead structure! Null: Imports bitplane, byteperline, => clscanlinesize
* Lpbyte ppcxbits-pointer to the dib data zone, increasing by scanline Length
* Lpbyte ppcximg-pointer to PCX image zone! Null, RLE compression encoding.
* Declaration before calling: lpbyte ppcximg = new byte [2 * bitplane * byteperline]
*
* Return: uint rec-returns the number of bytes after each row is compressed.
*
* Note: RLE encoding is performed based on the DIB image data pointer (the tested algorithm is perfect and supports 256 and 24bit true colors)
**************************************** ************************************/
Uint cpcximage: packpcxline (ppcxhead ppcxhdr, lpbyte ppcxbits, lpbyte ppcximg) const
{
//----------------------------------------
// RLE compression
Assert (ppcxhdr! = NULL & ppcxbits! = NULL & ppcximg! = NULL );
Byte I (1 );
Uint LPOS (0), REC (0 );
// ☆Rle encoding, maximum repetition <= 63 ☆
For (int bp = ppcxhdr-> BitPlane-1; BP> = 0; BP --)
{
LPOS = 0; // The processed RGB Sequence
While (LPOS <ppcxhdr-> byteperline) // The value is less than the image width.
{
I = 1; // reset the step-1
// -----------------> Check the following code:
While (ppcxbits [(I-1 + LPOS) * ppcxhdr-> bitplane + bp] = ppcxbits [(I + LPOS) * ppcxhdr-> bitplane + bp])
& (LPOS + I) <ppcxhdr-> byteperline) & (I <63) I ++;
If (I> 1 & I <64)
{
// Indicates that there are I repeated pixel values at the current pixel position, which are written to the PCX image data buffer in sequence
// 1. Repeated times
Ppcximg [Rec ++] = I | 0xc0;
// 2. pixel value
Ppcximg [Rec ++] = ppcxbits [LPOS * ppcxhdr-> bitplane + bp];
LPOS + = I; // LPOS-records the number of bytes processed in the current scan row
// Rec-records the number of bytes that have been written to the PCX file.
}
Else
{
// Indicates that the current pixel position does not contain duplicate pixel values.
// If the pixel value is greater than 0xc0 (192), the write mark 0xc1
If (ppcxbits [LPOS * ppcxhdr-> bitplane + bp] & 0xc0) = 0xc0) ppcximg [Rec ++] = 0xc1;
Ppcximg [Rec ++] = ppcxbits [LPOS * ppcxhdr-> bitplane + bp]; LPOS ++;
}
}
}
// Write image data to end
Return REC;
}
========================================================== ==============================
The call is as follows:
1. // RLE decoding -------------> already contains 8-bit and 24-bit Images
For (INT Iy = 0; Iy <= ppcxhdr-> Ymax; Iy ++)
{
Zeromemory (ppcxbits, clscanlinesize );
Ppcximg + = loadpcxline (ppcxhdr, ppcximg, ppcxbits); // read scanned row data
Ppcxbits + = clscanlinesize;
}
Ppcxhdr is a pointer to the pcxhead structure (128 bytes), ppcxbits is a buffer for storing decoded image data, and ppcximg is a pointer to a PCX Image File
The pointer to the image data, which increases with the number of scanned rows. The complete function is to decode the image data from the PCX file to the image data in the Windows bitmap format.
2. // RLE compression -------------> already contains 8-bit and 24-bit Images
// In the worst case, apply for a buffer of 2 times. The adjacent data is not repeated and the value must be greater than 0xc0.
Lpbyte ppcximg = new byte [2 * pcxhdr. bitplane * pcxhdr. byteperline]; // stores temporary scan rows
Uint Rec (0); // counter, such as the number of bytes in a PCX File
For (INT Iy = 0; Iy <= pcxhdr. Ymax; Iy ++)
{
Zeromemory (ppcximg, 2 * pcxhdr. bitplane * pcxhdr. byteperline );
Rec = packpcxline (& pcxhdr, ppcxbits, ppcximg );
// The number of rows scanned by Dib increases progressively.
Ppcxbits + = clscanlinesize;
Pfile-> write (ppcximg, REC );
}
Delete [] ppcximg;
The specific parameters are roughly the same as 1. ppcximg is the buffer after temporary RLE compression.
------ [Over ]------