www.pudn.com > viewImage.rar > Pcx.cpp
// Pcx.cpp: implementation of the CPcx class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include#include #include "Pcx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CPcx::CPcx() { m_pDib = NULL; } CPcx::CPcx(CDib *pDib) { m_pDib = NULL; SetDib(pDib); } CPcx::~CPcx() { if (m_pDib != NULL) delete m_pDib; } BOOL CPcx::Load(LPCTSTR lpstrFileName) { PCXPALETTE palette[256]; PCXHEADER header; int width, height, bytes, widthbytes; BYTE *lpBuffer; FILE *inFile; /*** Open the PCX file ***/ if ((inFile=fopen(lpstrFileName,"rb")) == NULL) return FALSE; /*** Read in the header ***/ if (!fread((char *)&header, sizeof(PCXHEADER), 1, inFile)) { fclose(inFile); return FALSE; } /*** Check to make sure it's a PCX ***/ if (header.manufacturer!=0x0A || header.version!=5) { fclose(inFile); return FALSE; } /*** Find the palette ***/ if (fseek(inFile, -1*(long)(sizeof(palette)+1), SEEK_END)) { fclose(inFile); return FALSE; } /*** Read in the palette data ***/ if (fgetc(inFile)!=0x0C || fread((char *)palette, 1, sizeof(palette), inFile) != sizeof(palette)) { fclose(inFile); return FALSE; } /*** Seek to start of image data ***/ fseek(inFile, (long)sizeof(PCXHEADER), SEEK_SET); /*** PCX dimension ***/ width = (header.xmax - header.xmin) + 1; height = (header.ymax - header.ymin) + 1; bytes = header.bytesPerLine; widthbytes = WIDTHBYTES(bytes*8); /*** Allocate buffer ***/ DWORD dwBitsSize = widthbytes * height; if ((lpBuffer = (BYTE*)malloc(dwBitsSize)) == NULL) { fclose(inFile); return FALSE; } /*** Translate the image data ***/ for (int i=0; i Attach(hDIB); return TRUE; } BOOL CPcx::Save(LPCTSTR lpstrFileName, CDib* pDib) { if (pDib == NULL) pDib = m_pDib; if (pDib == NULL) return FALSE; HDIB hDib = CopyHandle(pDib->GetHandle()); if (hDib == NULL) return FALSE; CDib* pDibTmp = new CDib; pDibTmp->Attach(hDib); UINT uWidth = pDibTmp->GetWidth(); UINT uHeight = pDibTmp->GetHeight(); // convert to 8-bit image if (pDibTmp->GetBitCount() != 8) pDibTmp->ConvertFormat(8); // make PCX header PCXHEADER header; memset((LPBYTE)&header, 0, sizeof(PCXHEADER)); header.manufacturer = 0x0A; header.version = 5; header.encoding = 1; header.bitsPerPixel = 8; header.xmin = 0; header.ymin = 0; header.xmax = uWidth-1; header.ymax = uHeight-1; //header.hres //header.vres; header.palette[0] = (BYTE)0x00; // for correct process for mono header.palette[1] = (BYTE)0x00; header.palette[2] = (BYTE)0x00; header.palette[3] = (BYTE)0xff; header.palette[4] = (BYTE)0xff; header.palette[5] = (BYTE)0xff; //header.palette[48]; header.reserved = 0; header.colourPlanes = 1; header.bytesPerLine = uWidth; header.paletteType = 2; //filler[58]; // construct PCX palette from DIB color table PCXPALETTE palette[256]; PALETTEENTRY PaletteColors[256]; pDibTmp->GetPalette()->GetPaletteEntries(0, 256, PaletteColors); for (int i=0;i<256;i++) { palette[i].rgbRed = PaletteColors[i].peRed; palette[i].rgbGreen = PaletteColors[i].peGreen; palette[i].rgbBlue = PaletteColors[i].peBlue; } // get bits ptr HDIB hDIB = CopyHandle(pDibTmp->GetHandle()); delete pDibTmp; LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); BYTE* lpBuffer = (BYTE *)FindDIBBits(lpDIB); WORD wWidthBytes = (WORD)BytesPerLine(lpDIB); /*** Open the PCX file ***/ FILE *outFile; if ((outFile=fopen(lpstrFileName,"wb")) == NULL) { GlobalUnlock(hDIB); GlobalFree(hDIB); return FALSE; } /*** Write the header ***/ fwrite((char *)&header, sizeof(PCXHEADER), 1, outFile); /*** Write image data ***/ for (i=(int)uHeight-1; i>=0; --i) { if (! WritePCXLine(header.bytesPerLine, lpBuffer+i*wWidthBytes, outFile)) { fclose(outFile); GlobalUnlock(hDIB); GlobalFree(hDIB); return FALSE; } } /*** Write the palette data ***/ fputc(0x0c, outFile); fwrite((char *)palette, 1, sizeof(palette), outFile); // clear & close fclose(outFile); GlobalUnlock(hDIB); GlobalFree(hDIB); return TRUE; } /**** ***** Read a single line of a PCX file. ****/ BOOL CPcx::ReadPCXLine(int bytes, BYTE *p, FILE *fp) { int n=0; register int c, i; /*** Null the buffer ***/ do { c = fgetc(fp) & 0xFF; /* get a key byte */ /*** If it's a run of bytes field ***/ if ((c&0xC0) == 0xC0) { i = c & 0x3F; /* AND off high bits */ c = fgetc(fp); /* get the run byte */ while (i--) /* run the byte */ p[n++] = c; } /*** Else just store it ***/ else p[n++] = c; } while (n < bytes); return (ferror(fp) ? FALSE : TRUE); } /**** ***** Write a single line of a PCX file. ****/ BOOL CPcx::WritePCXLine(int bytes, BYTE *p, FILE *fp) { unsigned int i=0, j=0, t=0; do { i = 0; while ((p[t+i]==p[t+i+1]) && ((t+i)<(WORD)bytes) && (i<63)) ++i; if (i > 0) /* there are i equal pixels from current position */ { fputc(i|0xc0, fp); /* write duplicated number */ fputc(p[t], fp); /* write pixel value */ t += i; /* bytes have been processed */ j += 2; /* bytes have been written to file */ } else /* no duplicated pixel */ { if (((p[t]) & 0xc0) == 0xc0) /* pixel value > 192 ? */ { fputc(0xc1, fp); /* write identify sign 0xc1 */ ++j; } fputc(p[t++], fp); ++j; } } while (t < (WORD)bytes); return (ferror(fp) ? FALSE : TRUE); } // // vertically flip a buffer // note, this operates on a buffer of widthBytes bytes, not pixels!!! // BOOL CPcx::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; }