概念
CxImage類庫是一個優(yōu)秀的圖像操作類庫。它可以快捷地存取、顯示、轉(zhuǎn)換各種圖像。有的讀者可能說,有那么多優(yōu)秀的圖形庫,如OpenIL,FreeImage,PaintLib等等,它們可謂是功能強(qiáng)大,齊全,沒必要用其它的類庫。但我要說,這些類庫基本上沒有免費(fèi)的,使用這些類庫,你要被這樣那樣的許可協(xié)議所束縛。在這點(diǎn)上,CxImage類庫是完全免費(fèi)的。另外,在使用上述類庫時,你會遇到重重麻煩。因為它們大部分是平臺無關(guān)的,且用C語言寫成,有的還夾雜著基本的C++ wrapper和成堆的編譯選項的聲明需要你去處理。而CxImage類庫在這方面做得很好。還有讓我最看好的,就是作者完全公開了源代碼。相對于那些封裝好的圖形庫和GDI+來說,這一點(diǎn)使我們可以進(jìn)一步學(xué)習(xí)各種編解碼技術(shù),而不再浮于各種技術(shù)的表面。
介紹
一個CxImage對象是一個擴(kuò)展了的位圖。作者只是在位圖結(jié)構(gòu)上添加了一些起存儲信息作用的成員變量。一個CxImage對象(同時)也是一組層。每個層只有在需要時才會分配相應(yīng)的緩沖區(qū)。CxImage::pDib代表著背景圖像,CxImage::pAlpha代表著透明層,CxImage::pSelection代表著被選中的層,被用來創(chuàng)建圖像處理時讓用戶感興趣的區(qū)域。在這三個特殊層面的基礎(chǔ)上,你可以增加一些額外的層,這些層可以存儲在CxImage::pLayers中。一般說來,層是一個完整的CxImage對象。因此,你可以構(gòu)造很復(fù)雜的嵌套層。下面是CxImage的一些成員變量:
class CxImage
{
...
protected:
void* pDib; //包含文件頭,調(diào)色板等等
BITMAPINFOHEADER head; //標(biāo)準(zhǔn)的文件頭(位圖)
CXIMAGEINFO info; //擴(kuò)展了的信息
BYTE* pSelection; //用戶選中的區(qū)域
BYTE* pAlpha; //alpha通道
CxImage** pLayers; //通用層
}
typedef struct tagCxImageInfo {
DWORD dwEffWidth; //DWORD 掃描線寬
BYTE* pImage; //圖像位數(shù)
void* pGhost; //if this is a ghost, pGhost point to the body
DWORD dwType; //原圖像的格式
char szLastError[256]; //出錯信息
long nProgress; //監(jiān)視循環(huán)的次數(shù)
long nEscape; //跳出標(biāo)志
long nBkgndIndex; //GIF, PNG, MNG格式使用
RGBQUAD nBkgndColor; //RGB三原色透明度
BYTE nQuality; //JPEG格式使用
long nFrame; //TIF, GIF, MNG使用 :實際的幀數(shù)
long nNumFrames; //TIF, GIF, MNG使用 :幀總數(shù)
DWORD dwFrameDelay; //GIF, MNG使用
long xDPI; //水平分辨率
long yDPI; //垂直分辨率
RECT rSelectionBox; //選中的矩形區(qū)
BYTE nAlphaMax; //陰影的最大不透明度
bool bAlphaPaletteEnabled; //如果調(diào)色板中有Alpha通道則為真
bool bEnabled; //打開繪圖函數(shù)
long xOffset;
long yOffset;
DWORD dwEncodeOption; //一些編碼選項
RGBQUAD last_c; //一些優(yōu)化選項
BYTE last_c_index;
bool last_c_isvalid;
long nNumLayers;
DWORD dwFlags;
} CXIMAGEINFO;
要在picture box中顯示一個png格式的文件,只需:
CxImage image("myfile.png", CXIMAGE_FORMAT_PNG);
HBITMAP m_bitmap = image.MakeBitmap(m_picture.GetDC()->m_hDC);
m_picture.SetBitmap(m_bitmap);
其它格式則類推。
Examples: how to ...
... convert from a format to another
CxImage image;
// bmp -> jpg
image.Load("image.bmp", CXIMAGE_FORMAT_BMP);
if (image.IsValid()){
if(!image.IsGrayScale()) image.IncreaseBpp(24);
image.SetJpegQuality(99);
image.Save("image.jpg",CXIMAGE_FORMAT_JPG);
}
// png -> tif
image.Load("image.png", CXIMAGE_FORMAT_PNG);
if (image.IsValid()){
image.Save("image.tif",CXIMAGE_FORMAT_TIF);
}
... load an image resource
//Load the resource IDR_PNG1 from the PNG resource type
CxImage* newImage = new CxImage();
newImage->LoadResource(FindResource(NULL,MAKEINTRESOURCE(IDR_PNG1),
"PNG"),CXIMAGE_FORMAT_PNG);
or//Load the resource IDR_JPG1 from DLL
CxImage* newImage = new CxImage();
HINSTANCE hdll=LoadLibrary("imagelib.dll");
if (hdll){
HRSRC hres=FindResource(hdll,MAKEINTRESOURCE(IDR_JPG1),"JPG");
newImage->LoadResource(hres,CXIMAGE_FORMAT_JPG,hdll);
FreeLibrary(hdll);
}
or//Load a bitmap resource;
HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1)));
CxImage *newImage = new CxImage();
newImage->CreateFromHBITMAP(bitmap);
... decode an image from memory
CxImage image((BYTE*)buffer,size,image_type);
orCxMemFile memfile((BYTE*)buffer,size);
CxImage image(&memfile,image_type);
orCxMemFile memfile((BYTE*)buffer,size);
CxImage* image = new CxImage();
image->Decode(&memfile,type);
... encode an image in memory
long size=0;
BYTE* buffer=0;
image.Encode(buffer,size,image_type);
...
free(buffer);
orCxMemFile memfile;
memfile.Open();
image.Encode(&memfile,image_type);
BYTE* buffer = memfile.GetBuffer();
long size = memfile.Size();
...
free(buffer);
... create a multipage TIFF
CxImage *pimage[3];
pimage[0]=&image1;
pimage[1]=&image2;
pimage[2]=&image3;
FILE* hFile;
hFile = fopen("multipage.tif","w+b");
CxImageTIF multiimage;
multiimage.Encode(hFile,pimage,3);
fclose(hFile);
orFILE* hFile;
hFile = fopen("c:\multi.tif","w+b");
CxImageTIF image;
image.Load("c:\1.tif",CXIMAGE_FORMAT_TIF);
image.Encode(hFile,true);
image.Load("c:\2.bmp",CXIMAGE_FORMAT_BMP);
image.Encode(hFile,true);
image.Load("c:\3.png",CXIMAGE_FORMAT_PNG);
image.Encode(hFile);
fclose(hFile);
... copy/paste an image
//copy
HANDLE hDIB = image->CopyToHandle();
if (::OpenClipboard(AfxGetApp()->m_pMainWnd->GetSafeHwnd())) {
if(::EmptyClipboard()) {
if (::SetClipboardData(CF_DIB,hDIB) == NULL ) {
AfxMessageBox( "Unable to set Clipboard data" );
} } }
CloseClipboard();
//paste
HANDLE hBitmap=NULL;
CxImage *newima = new CxImage();
if (OpenClipboard()) hBitmap=GetClipboardData(CF_DIB);
if (hBitmap) newima->CreateFromHANDLE(hBitmap);
CloseClipboard();
需要大家注意的是:整個CxImage類庫非常大。如果你只需要能處理其中的幾種格式,你可以在主要的頭文件ximage.h中找到一些開關(guān)選項來關(guān)閉一些圖像庫。JPG、PNG、TIFF中的每一個庫,都會向最終程序增加約100KB的內(nèi)容。而CxImage類庫壓縮后只有約60KB。所以,你需要謹(jǐn)慎挑選一些你真正需要的類庫。作者提供的示例工程在編譯后,你會發(fā)現(xiàn)如下一些文件: ·CxImage : cximage.lib - static library
·CxImageCrtDll : cximagecrt.dll - DLL not using mfc
·CxImageMfcDll : cximage.dll - DLL using mfc
·Demo : demo.exe - program linked with cximage.lib and the C libraries
·DemoDll : demodll.exe - program linked with cximagecrt.dll
·j2k,jasper,jbig,jpeg,png,tiff,zlib : static C libraries
構(gòu)建這些工程需要耗費(fèi)幾分鐘的時間(中間文件可達(dá)60MB)。下面則是使用CxImage類庫前必須設(shè)置的一些參數(shù):
Project Settings
|- C/C++
| |- Code Generation
| | |- Use run-time library : Multithreaded DLL (must be the same for
| | | all the linked libraries)
| | |- Struct member alignment : must be the same for all the linked
| | | libraries
| |- Precompiled headers : not using precompiled headers
| |- Preprocessor
| |- Additional Include Directories: ..\cximage
|- Link
|- General
|- Object/library modules: ../png/Debug/png.lib
../jpeg/Debug/jpeg.lib
../zlib/Debug/zlib.lib
../tiff/Debug/tiff.lib
../cximage/Debug/cximage.lib ...
兼容性: - Microsoft Visual C++ 6.0 (static library, DLL and OCX builds) - Microsoft Visual C++ .NET 2003 - Borland C++ Builder version 3 and version 6 - Kdevelop 2.1 with gcc 2.96 (Linux)