程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++圖像處理 -- PCX格式圖像(上)

C++圖像處理 -- PCX格式圖像(上)

編輯:C++入門知識

        PCX是一個比較早的圖像文件格式,它也有過一段時間的輝煌,但隨著計算機硬、軟件的發展,該圖像格式基本已成過去時,主要是因為早期PCX格式圖像是配合當時顯卡硬件而設計的,如CGA/EGA/VGA等,現在顯然已經過時了,雖然後來的版本增加了對256色和24位真彩色的支持,但仍然因其文件格式的先天不足,導致操作很不方便,如256色圖像調色板就是以“補丁”形式追加到文件最後面的,24位真彩色用以前EGA圖像卡按行以彩色面形式存放等;另外PCX的RLE編碼對6位以下像素格式是比較有效的,對目前8位為主的像素格式壓縮也不盡人意,如24位像素格式壓縮後,有時比不壓縮空間占用還大。       雖然PCX格式圖像目前使用不多,但還是有很多軟件是支持這種格式的,如Photoshop。在圖像處理編程時,偶爾也會遇到這種格式的圖像,但不象BMP、JPEG、GIF等圖像格式容易找到現存的庫函數或組件,所以本文提供了PCX格式圖像與GDI+位圖的相互轉換的代碼,本文分上下兩篇,上篇將PCX格式圖像轉換為GDI+位圖,下篇將GDI+位圖轉換為PCX格式圖像。下面是轉換源碼:   [cpp]  typedef struct              // pcx文件頭    {       BYTE flag;              // 標記        BYTE version;           // 版本號        BYTE encodeing;         // 編碼方式        BYTE bitsPrePixel;      // 平面像素位數        WORD xMin;              // 最小X        WORD yMin;              // 最小Y        WORD xMax;              // 最大X        WORD yMax;              // 最大Y        WORD hRes;              // 水平分辨率        WORD vRes;              // 垂直分辨率        BYTE palette[48];       // 16色調色板        BYTE reserved;          // 保留        BYTE planes;            // 平面數        WORD bytesPreLine;      // 每行字節數        WORD paletteType;       // 調色板類型。1:彩色或黑白,2:灰度        BYTE filler[58];   }PcxFileHeader, *PPcxFileHeader;   //---------------------------------------------------------------------------       FORCEINLINE   LPBYTE 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 source;   }   //---------------------------------------------------------------------------       // 單色或256色    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色    VOID UnpackPck4(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 < data->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;   }   //---------------------------------------------------------------------------       // 24位真彩色    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;   }   //---------------------------------------------------------------------------       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, format, &data);       switch (format)       {           case PixelFormat4bppIndexed:               UnpackPck4(&data, bitsMem, header->bytesPreLine);               break;           case PixelFormat24bppRGB:               UnpackPck24(&data, bitsMem, header->bytesPreLine);               break;           default:               UnpackPck(&data, bitsMem, header->bytesPreLine);       }       bmp->UnlockBits(&data);       return bmp;   }   //---------------------------------------------------------------------------       Bitmap *LoadPcxImageFromStream(IStream *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;   }   //---------------------------------------------------------------------------     typedef struct         // pcx文件頭 { BYTE flag; // 標記 BYTE version; // 版本號 BYTE encodeing; // 編碼方式 BYTE bitsPrePixel; // 平面像素位數 WORD xMin; // 最小X WORD yMin; // 最小Y WORD xMax; // 最大X WORD yMax; // 最大Y WORD hRes; // 水平分辨率 WORD vRes; // 垂直分辨率 BYTE palette[48]; // 16色調色板 BYTE reserved; // 保留 BYTE planes; // 平面數 WORD bytesPreLine; // 每行字節數 WORD paletteType; // 調色板類型。1:彩色或黑白,2:灰度 BYTE filler[58]; }PcxFileHeader, *PPcxFileHeader; //---------------------------------------------------------------------------   FORCEINLINE LPBYTE 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 source; } //---------------------------------------------------------------------------   // 單色或256色 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色 VOID UnpackPck4(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 < data->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; } //---------------------------------------------------------------------------   // 24位真彩色 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; } //---------------------------------------------------------------------------   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, format, &data); switch (format) { case PixelFormat4bppIndexed: UnpackPck4(&data, bitsMem, header->bytesPreLine); break; case PixelFormat24bppRGB: UnpackPck24(&data, bitsMem, header->bytesPreLine); break; default: UnpackPck(&data, bitsMem, header->bytesPreLine); } bmp->UnlockBits(&data); return bmp; } //---------------------------------------------------------------------------   Bitmap *LoadPcxImageFromStream(IStream *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; } //---------------------------------------------------------------------------     上面代碼中,UnpackPckImage函數是核心代碼,負責對PCX格式圖像內存映像進行解析並轉換。現在版本的PCX格式圖像主要是單色、16色、256色和24位真彩色,本文代碼能准確的解析這幾種圖像。但有時也可能有些不規范圖像,如16色圖像,規范的格式應該是像素位數bitsPrePixel=1,像素平面planes=4,同時調色板數據在文件頭的palette中,這是從EGA顯示卡遺留下來的格式,但如bitsPrePixel=4,像素平面planes=1的格式描述,也同樣是16色格式,而且是符合現代16色格式的,我用Photoshop對這種格式描述做過實驗,但會顯示文件不完整的錯誤,既然是“不完整”而不是非法錯誤,證明這種16色格式描述也應該是正確的,因此我嘗試將調色板從文件頭移到文件尾,結果Photoshop果然將圖像讀出來了,但只顯示了一半的寬度,由此,我得知這是Photoshop的容錯讀取,即它忽略了bitsPrePixel=4這個描述,而是把它當256色圖像處理的,事實上,在Photoshop中是沒法正確保存16色圖像的,它總是將16色用256色方式保存的,我在UnpackPckImage函數中也采用了這種容錯方式,只要圖像尾部有調色板,就可以當256色處理;只要planes=3,就當24位真彩色讀取,而不再管其它描述。       LoadPcxImageFromStream函數只是簡單的從流讀取PCX格式圖像到內存映像而已,之所以選擇從流讀取,主要是考慮通用性。為了能從文件讀取PCX圖像,我也寫了一個不完整的文件流類,只需要前面6個接口函數能用就行了(事實上,只要Read、Write和Seek3個函數能用即可)。下面是這個文件流類和LoadPcxImageFromFile函數代碼:   [cpp]   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;   }   //---------------------------------------------------------------------------     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; } //---------------------------------------------------------------------------     下面是個從文件讀取並顯示的例子代碼(BCB2010):   [cpp]   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;   }     void __fastcall TForm1::Button2Click(TObject *Sender) {www.2cto.com 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; }    本文沒有對PCX文件格式進行詳細講解,主要原因是這些網上可以搜索得到,雖然並不完全可靠,但參考一下是可行的,而且,我自己也沒法比網上講的更透徹了,畢竟,PCX格式圖像太“古老”了,古老的我想找幾個以前版本的文件做實驗都沒法找到,只好靠Photoshop保存,或者自己寫這種格式文件,如16色圖像Photoshop就沒法正確保存。  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved