C ++ Image Processing-PCX Format Image (I)

Source: Internet
Author: User

Reading Tips:

The C ++ image processing series focuses on code clarity and readability, all using C ++ code.

Delphi Image ProcessingThe series focuses on efficiency. The general code is Pascal, and the core code is BaSm.

Make sure that the two items are consistent and can be compared with each other.

 

PCX is an early image file format, which has been brilliant for a period of time. However, with the development of computer hardware and software, the image format has become a thing of the past, the main reason is that early PCX format images were designed in combination with the graphics card hardware at that time, such as CGA, Jakarta, and VGA. Now they are obviously outdated, although later versions added support for 256 colors and 24-bit true colors, operations were inconvenient due to the inherent insufficiency of the file format, for example, the color palette of a 256-color image is appended to the last face of the file in the form of a patch, and the 24-bit real color is stored in the form of a color area by line using the previous photo card; in addition, the RLE encoding of PCX is effective for the pixel format below 6 bits, which is not satisfactory for the current 8-bit pixel format compression. For example, after the 24-bit pixel format compression, sometimes it is larger than no compressed space.

Although there are not many PCX images currently, many software programs support this format, such as Photoshop. During image processing and programming, you may occasionally encounter images in this format. However, unlike BMP, JPEG, GIF, and other image formats, it is easy to find existing library functions or components, therefore, this article provides code for converting the image in PCX format and the image in GDI + bitmap. This article is divided into two chapters: the previous article converts the image in PCX format into a GDI + bitmap, next, we will convert the GDI + bitmap into a PCX image. The conversion source code is as follows:

Typedef struct // PCX File Header {byte flag; // mark byte version; // version number byte encodeing; // encoding byte bitsprepixel; // word xmin in the number of pixels in the plane; // minimum xword ymin; // minimum yword xmax; // maximum xword Ymax; // maximum yword hres; // horizontal resolution word vres; // vertical resolution byte palette [48]; // 16-color palette byte reserved; // retain byte planes; // number of planes word bytespreline; // number of bytes per line word palettetype; // palette type. 1: color or black/white, 2: grayscale byte filler [58];} pcxfileheader, * ppcxfileheader; // convert forceinlinelpbyte unpackpckline (lpbyte DEST, lpbyte source, int bytes) {While (Bytes> 0) {If (* Source> 0xc0) {int COUNT = * Source ++ & 0x3f; byte c = * Source ++; bytes-= count; for (; count> 0; * DEST ++ = C, count --);} else {* DEST ++ = * Source ++; bytes -- ;}} return so Urce;} // monochrome or 256-color void unpackpck (bitmapdata * data, lpbyte bitsmem, int bytespreline) {lpbyte P = (lpbyte) Data-> scan0; lpbyte M = bitsmem; For (uint y = 0; y <data-> height; y ++, P + = data-> STRIDE) {M = unpackpckline (p, m, bytespreline) ;}}// --------------------------------------------------------------------------- // 16-color void UN Packpck4 (bitmapdata * data, lpbyte bitsmem, int bytespreline) {lpbyte P = (lpbyte) Data-> scan0; lpbyte M = bitsmem; int datoffset = data-> stride-(getpixelformatsize (data-> pixelformat) * Data-> width + 7)> 3); If (data-> width & 1) datoffset ++; int bytes1 = bytespreline; int bytes2 = bytes1 <1; int bytes3 = bytes2 + bytes1; int bytes = bytes1 <2; lpbyte buffer = new byte [bytes]; for (uint y = 0; y <dat A-> height; y ++, P + = datoffset) {M = unpackpckline (buffer, M, bytes); lpbyte B = buffer; byte mask = 0x80; for (uint x = 0; x <data-> width; X ++) {If (* B & Mask) * p | = 1; if (* (B + bytes1) & Mask) * p | = 2; If (* (B + bytes2) & Mask) * p | = 4; If (* (B + bytes3) & Mask) * p | = 8; If (X & 1) P ++; else * P <= 4; mask> = 1; if (! Mask) {mask = 0x80; B ++ ;}} Delete [] buffer;} // bytes // 24-bit real-color void unpackpck24 (bitmapdata * data, lpbyte bitsmem, int bytespreline) {int bytes1 = bytespreline; int bytes2 = bytes1 <1; int bytes = bytes2 + bytes1; int width = (INT) Data-> width> bytespreline? Bytespreline: Data-> width; int datoffset = data-> stride-width * 3; prgbtriple P = (prgbtriple) Data-> scan0; lpbyte M = bitsmem; lpbyte buffer = new byte [bytes]; for (INT y = 0; y <(INT) Data-> height; y ++, (lpbyte) P + = datoffset) {M = unpackpckline (buffer, M, bytes); lpbyte B = buffer; For (INT x = 0; x <width; X ++, P ++, B ++) {P-> rgbtred = * B; P-> rgbtgreen = * (B + bytes1); P-> rgbtblue = * (B + bytes2 );}} Delete [] buffer;} // specify bitmap * unpackpckimage (lpbyte imagemem, int imagebytes) {pcxfileheader * Header = (pcxfileheader *) imagemem; If (header-> flag! = 0x0a) return NULL; prgbtriple ppal = NULL; pixelformat format = pixelformatundefined; If (header-> bitsprepixel = 1) {If (header-> planes = 4) {format = pixelformat4bppindexed; ppal = (prgbtriple) header-> palette;} else format = pixelformat1bppindexed;} else {If (header-> planes = 3) format = pixelformat24bpprgb; else if (header-> planes = 1) {ppal = (prgbtriple) (imagemem + imagebytes-256*3); If (* (lpbyte) Ppal-1) = 0x0c) format = pixelformat8bppindexed;} If (format = pixelformatundefined) return NULL; bitmap * BMP = new Bitmap (header-> xmax-header-> xmin + 1, header-> Ymax-header-> ymin + 1, format); If (ppal) {int COUNT = 1 <(header-> bitsprepixel * Header-> planes); colorpalette * pal = (colorpalette *) New byte [count * sizeof (argb) + sizeof (colorpalette)]; prgbquad pp = (prgbquad) Pal-> entries; For (int I = 0; I <count; I ++) {PP [I]. rgbblue = ppal [I]. rgbtred; PP [I]. rgbgreen = ppal [I]. rgbtgreen; PP [I]. rgbred = ppal [I]. rgbtblue; PP [I]. rgbreserved = 255;} Pal-> flags = 0; pal-> COUNT = count; BMP-> setpalette (PAL); Delete [] pal ;} lpbyte bitsmem = imagemem + sizeof (pcxfileheader); bitmapdata data; gdiplus: rect R (0, 0, BMP-> getwidth (), BMP-> getheight ()); BMP-> lockbits (& R, imagelockmoderead | imagelockmodewrite, F Ormat, & data); Switch (Format) {Case pixelformat4bppindexed: unpackpck4 (& Data, bitsmem, header-> bytespreline); break; Case pixelformat24bpprgb: unpcpackk24 (& Data, bitsmem, header-> bytespreline); break; default: unpackpck (& Data, bitsmem, header-> bytespreline);} BMP-> unlockbits (& data); Return BMP ;} // ------------------------------------------------------------------------------- bitmap * loadpcximagefromstream (istrea M * stream) {large_integer move; ularge_integer size; move. quadpart = 0; If (Stream-> seek (move, stream_seek_end, & size )! = S_ OK) return NULL; stream-> seek (move, stream_seek_set, null); lpbyte imagemem = new byte [size. lowpart]; bitmap * BMP = NULL; If (Stream-> Read (imagemem, size. lowpart, null) = s_ OK) BMP = unpackpckimage (imagemem, size. lowpart); Delete [] imagemem; return BMP ;}//---------------------------------------------------------------------------

In the above Code, the unpackpckimage function is the core code and is responsible for parsing and converting the memory image of the PCX format. Current versions of PCX format images are mainly monochrome, 16 color, 256 color and 24 real color. The code in this article can accurately parse these images. However, sometimes some non-standard images, such as 16-color images, must be in the format of pixel bits bitsprepixel = 1, pixel plane planes = 4, and the color palette data is stored in the palette of the file header, this is a legacy format from the render display card, but the format descriptions such as bitsprepixel = 4 and pixel plane planes = 1 are also in the 16-color format and comply with the modern 16-color format, I have used Photoshop to describe this format for an experiment, but it will show an incomplete file error. Since it is "incomplete" rather than an invalid error, the 16-color format description should be correct, so I tried to move the palette from the file header to the end of the file. As a result, Photoshop read the image, but only half of the width is displayed, as a result, I learned that this is a fault-tolerant reading of Photoshop, that is, it ignores the description of bitsprepixel = 4, but treats it as a 256-color image. In fact, in Photoshop, the 16-color image cannot be properly saved. It always saves the 16-color image in 256 colors. This fault tolerance method is also used in the mage function. As long as there is a palette at the end of the image, it can be treated as 256 colors; as long as planes = 3, it can be read as 24-bit real color, instead of other descriptions.

The loadpcximagefromstream function simply reads the PCX format image from the stream to the memory image. The reason for choosing to read from the stream is mainly to consider universality. In order to read the PCX image from a file, I also wrote an incomplete file stream class. Only the first six interface functions can be used. (In fact, only the read, write, and seekfunctions can be used ). The following is the code of the file stream class and loadpcximagefromfile function:

class FileStream : public IStream{HANDLE handle;INT refCount;public:HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvObject){if (lstrcmp((LPTSTR)&riid, (LPTSTR)&IID_IStream) == 0 ||lstrcmp((LPTSTR)&riid, (LPTSTR)&IID_IUnknown) == 0){*ppvObject = this;AddRef();return S_OK;}*ppvObject = NULL;return E_NOINTERFACE;}ULONG STDMETHODCALLTYPE AddRef(VOID){refCount ++;return refCount;}ULONG STDMETHODCALLTYPE Release(VOID){if (refCount > 0) -- refCount;if (refCount == 0) delete this;return refCount;}HRESULT STDMETHODCALLTYPE Read(VOID *pv, ULONG cb, ULONG *pcbRead){ULONG readBytes;if (ReadFile(handle, pv, cb, &readBytes, NULL)){if (pcbRead) *pcbRead = readBytes;return S_OK;}return E_FAIL;}HRESULT STDMETHODCALLTYPE Write(CONST VOID *pv, ULONG cb, ULONG *pcbWritten){ULONG writeBytes;if (WriteFile(handle, pv, cb, &writeBytes, NULL)){if (pcbWritten) *pcbWritten = writeBytes;return S_OK;}return E_FAIL;}HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition){ULARGE_INTEGER pos;dlibMove.LowPart = SetFilePointer(handle, dlibMove.LowPart, &dlibMove.HighPart, dwOrigin);if (plibNewPosition)plibNewPosition->QuadPart = dlibMove.QuadPart;return dlibMove.QuadPart == -1? E_FAIL : S_OK;}HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize){return Seek(*(LARGE_INTEGER*)&libNewSize, STREAM_SEEK_END, NULL);}HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten){return S_OK;}HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags){return S_OK;}HRESULT STDMETHODCALLTYPE Revert(VOID){return STG_E_REVERTED;}HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType){return STG_E_INVALIDFUNCTION;}HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType){return STG_E_INVALIDFUNCTION;}HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag){return S_OK;}HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm){return E_NOTIMPL;}public:FileStream(VOID) : refCount(0), handle((HANDLE)(-1)) {}FileStream(LPTSTR fileName, BOOL isRead) : refCount(0){handle = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,isRead? OPEN_EXISTING : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);}~FileStream(VOID){if (handle != (HANDLE)(-1))CloseHandle(handle);}};//---------------------------------------------------------------------------Bitmap *LoadPcxImageFromFile(LPTSTR fileName){IStream *stream = new FileStream(fileName, TRUE);stream->AddRef();Bitmap *bmp = LoadPcxImageFromStream(stream);stream->Release();return bmp;}//---------------------------------------------------------------------------

The following is an example code (bcb2010) That is read from a file and displayed ):

void __fastcall TForm1::Button2Click(TObject *Sender){Bitmap *bmp;if ((bmp = LoadPcxImageFromFile("d:\\1-1-8.pcx")) == NULL)throw new Exception("Load Image fail");Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle);g->DrawImage(bmp, 0, 0);delete g;delete bmp;}

This document does not provide a detailed description of the PCX file format. The main reason is that these files can be searched on the Internet. Although they are not completely reliable, it is feasible to refer to them, I can't speak more thoroughly than I do on the Internet. After all, the PCX format images are too "old", and I cannot find some files of previous versions that I want to experiment, you have to save the file by Photoshop or write the file in this format by yourself.

 

Due to limited levels, errors are inevitable. Correction and guidance are welcome. Email Address:Maozefa@hotmail.com

Here, you can access "C ++ Image Processing-Article Index".

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.