網(wǎng)站導(dǎo)航:銳英源開源技術(shù)
下面內(nèi)容主要來自網(wǎng)絡(luò),〖IT168 專稿】,也加入了我們銳英源老師的理解。想學(xué)其中部分代碼可以聯(lián)系銳英源,專業(yè)為您服務(wù)。
CxImage是一個(gè)可以用于MFC 的C++圖像處理類庫(kù)類,它可以打開,保存,顯示,轉(zhuǎn)換各種常見格式的圖像文件,比如BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K 等格式的文件。可以實(shí)現(xiàn)BMP<->JPG,PNG <>TIFF格式等等的互相轉(zhuǎn)換。
CxImage不僅可以實(shí)現(xiàn)圖像文件的類型轉(zhuǎn)換,還可以實(shí)現(xiàn)在內(nèi)存圖像數(shù)據(jù)的類型轉(zhuǎn)換,并且使用很方便。除了文件格式的相互轉(zhuǎn)換,它還提供了很多很多圖像后處理的功能,比如圖像模糊,銳化等等,功能非常強(qiáng)大和實(shí)用。
CxImage中的x,大約代表了豐富的圖像格式支持和豐富的圖像處理功能,可以說CxImage是圖像處理的十全大補(bǔ)湯。
用CxImage實(shí)現(xiàn)的圖像處理程序
開發(fā)環(huán)境:
VC6, C++, Windows, MFC, Visual Studio, VS6, Dev
1簡(jiǎn)介和許可
CxImaage是一個(gè)可以簡(jiǎn)便而快速地打開,保存,顯示和轉(zhuǎn)換圖像文件的C++類庫(kù)。CxImage類庫(kù)是免費(fèi)的。對(duì)于TIFF,JPEG,PNG和ZLIB,"如果你在你的產(chǎn)品中使用了這些源代碼,雖然致謝不是必須的,但是卻會(huì)得到眾人的欣賞。"
CxImage是開源的并在zlib許可下發(fā)布。簡(jiǎn)單地說,你可以隨意地使用這些代碼,只要你不說它是你自己的就行了。
2 文件格式和鏈接的庫(kù)
CxImage支持如下這些庫(kù)的最新版本:
Zlib (1.2.3), Jasper ( 1.900.1), LibMNG (1.0.10), LibPNG (1.2.24). LibTIFF 3.8.2
j2k庫(kù)(現(xiàn)在被稱為openjpeg)和相關(guān)的類CxImageJ2K已經(jīng)從項(xiàng)目中刪除。JPEG2000格式的文件由Jasper和CximageJAS來支持。
Cximage 6.00提供了一個(gè)新的類CximageRAW和新的庫(kù)LibDCR,用于讀取來自數(shù)碼相機(jī)的RAW圖像。常見的文件擴(kuò)展名有:RAW, CRW, NEF, CR2, DNG, ORF, ARW, ERF, 3FR, DCR, X3F, MEF, RAF, MRW, PEF, SR2。
CximageRAW提供了對(duì)圖像的基本解碼功能,它唯一的可選參數(shù)可以由SetCodecOption進(jìn)行設(shè)置,以對(duì)插值質(zhì)量進(jìn)行可控制??蛇x的選項(xiàng)有(DECODE_QUALITY_LIN=0, DECODE_QUALITY_VNG=1, DECODE_QUALITY_PPG=2, DECODE_QUALITY_AHD=3).
CximagePNG:現(xiàn)在可以讀取所有PNG_COLOR_TYPE_類型。但是,每個(gè)通道含有超過8位像素深度的PNG文件,會(huì)被轉(zhuǎn)換到8位,這是CxImage的一個(gè)主要限制。
CxImageGIF:現(xiàn)在能夠更好地支持對(duì)動(dòng)態(tài)GIF圖像的讀取,通過SetRetreiveAllFrames設(shè)置屬性,可以同時(shí)對(duì)圖像中的所有幀進(jìn)行解碼。在CxImage的示例項(xiàng)目中,展示了如何實(shí)現(xiàn)這一選項(xiàng),并展示了如何播放一副GIF動(dòng)畫。
CxImageBMP: 支持對(duì)32位圖像的讀寫(支持Alpha通道)
CxImageICO: 支持對(duì)Vista PNG圖標(biāo)的讀寫;添加對(duì)多頁(yè)圖標(biāo)的支持。
CxImageMNG: 支持對(duì)MNG Alpha圖層的讀取。
CxImageSKA: 新的用于支持SKA圖像格式的類,這種圖像通常用在視頻租賃軟件中。
CxImageJPG: 為JPEG圖像格式的二次采樣提供了 新的選項(xiàng)。ENCODE_SUBSAMPLE_422,ENCODE_SUBSAMPLE_444),默認(rèn)情況下是 高采樣率的4:1:1 。當(dāng)然,也可以被設(shè)置成中等的4:2:2或者低等的4:4:4。
下圖展示了不同采樣率下,在壓縮圖像中所產(chǎn)生的不同數(shù)量的偽影。在壓縮有著明顯輪廓的圖像的時(shí)候,采用4:4:4的采樣率有助于減少輪廓的偽影。
3 可移植性
所有的類和項(xiàng)目都通過了不同編譯器的測(cè)試,包括從VC++6 到VC++2008的微軟系列編譯器,Borland C++ Builder 3和6,同時(shí)部分地支持wxDev-C++和MinGW。
所有的庫(kù)都支持UNICODE 和非UNICODE兩個(gè)版本。(感謝Eric Jesover)
對(duì)于第一次使用的用戶,你可以使用一個(gè)輕量級(jí)的版本(cximage600_lite)。這個(gè)版本去除了C庫(kù),但是添加了一個(gè)簡(jiǎn)單的示例項(xiàng)目。
所有控制臺(tái)示例(\demo2)和CxImageCrtDll項(xiàng)目可以在VC++Express2005和 Microsoft Platform SDK環(huán)境下編譯通過。如果你在編譯鏈接的時(shí)候,遇到像"unresolved external..."(無法找到外部符號(hào)…)這樣的錯(cuò)誤,請(qǐng)檢查是否所有C庫(kù)都被編譯了。或者手動(dòng)地添加gdi32.lib 和user32.lib為項(xiàng)目的依賴庫(kù)。
同時(shí),CxImage也可以在Pocket PC 2003上工作。在CxImage中,為VC++ 2005編譯器提供了一個(gè)可以工作的版本和相應(yīng)的實(shí)例(cximage600_ce)。對(duì)于舊式的嵌入式VC編譯器,最主要的限制是無法支持對(duì)異常的處理。為了解決這個(gè)問題,相應(yīng)的異常處理語句try,throw和catch已經(jīng)被定義在ximadef.h中的三個(gè)宏取代,同時(shí)還定義了CXIMAGE_SUPPORT_EXCEPTION_HANDLING。通過這樣的方法,取消對(duì)異常處理的支持,可以成功編譯鏈接整個(gè)庫(kù)。雖然這個(gè)解決辦法不是那么優(yōu)雅,但是當(dāng)異常處理被取消的時(shí)候,對(duì)代碼的影響是最小的。同時(shí),當(dāng)異常處理被啟用的時(shí)候,同樣不會(huì)造成源代碼的修改與變動(dòng)。
對(duì)于平臺(tái)之間little-endian和big-endian的兼容性,對(duì)于內(nèi)建支持的圖像文件格式(bmp, ico, tga, pcx, gif, ska),由ntohs和ntohl控制。
4功能示例
大多數(shù)新的特性可以在CxImage的主要示例程序中嘗試和體驗(yàn)。這個(gè)示例程序只是一個(gè)測(cè)試平臺(tái),雖然它提供很多有用的特性,但是它實(shí)在不是一個(gè)嚴(yán)謹(jǐn)?shù)膽?yīng)用程序。
·CQuantizer : 這個(gè)類被DecreaseBpp菜單項(xiàng)所使用。在以前的版本中,這里有一個(gè)取整的錯(cuò)誤,在某些情況下,白色(255,255,255)會(huì)被轉(zhuǎn)換成(254,254,254)。在新的版本中,這個(gè)問題已經(jīng)被修復(fù)了。
·Copy/Paste : 現(xiàn)在,新的粘貼功能支持元文件圖像(例如,從Office應(yīng)用程序中復(fù)制而來的圖像)。這個(gè)示例內(nèi)部使用了自定義的剪切板格式以測(cè)試Dump/Undump方法。Copy只工作在當(dāng)前選區(qū),但是你可以通過CxImage\Remove Selection 復(fù)制整幅圖像。
·FloodFill : (\View\Tools\Flood Fill) 通過一個(gè)浮動(dòng)的對(duì)話框,你可以測(cè)試色彩填充的顏色,偏差,透明度和是否選擇。當(dāng)透明度為0并且選擇區(qū)域功能啟用的時(shí)候,這個(gè)功能就變現(xiàn)為"魔法棒",用于根據(jù)顏色選區(qū)某個(gè)區(qū)域。
·Graph data extraction : (\Filters\graph data extraction) 這個(gè)示例演示了如何從圖像(從掃描儀獲取或者從互聯(lián)網(wǎng)下載所得)中提取數(shù)字信息。轉(zhuǎn)換后的數(shù)據(jù)被粘貼到剪切板,同時(shí)可以被保存成文本文件或者Excel表格文件。
數(shù)據(jù)提取對(duì)話框
數(shù)據(jù)提取結(jié)果
·RedEyeRemove : (\Filters\Non Linear\Remove Red Eye) 去除紅眼的功能在照片處理中經(jīng)常用到。你 必須在紅眼周圍選擇一個(gè)區(qū)域,然后去除紅眼的功能就會(huì)對(duì)紅色通道進(jìn)行過濾,從而去掉照片中的紅眼。紅眼的選區(qū)是一個(gè)矩形區(qū)域,同時(shí)可以包括部分的虹膜(眼黑),過濾器會(huì)在以選區(qū)中點(diǎn)為中心的圓心區(qū)域工作,不會(huì)影響到選中的眼黑部分。
·SelectiveBlur / UnsharpMask : 這些非線性的濾鏡可以增加圖像的質(zhì)量。SelectiveBlur可以去除二次噪聲(比如JPEG圖像中的偽影或者是數(shù)碼相機(jī)的噪聲),從而展示圖像中的更多細(xì)節(jié)。而UnsharpMask可以增強(qiáng)圖像的細(xì)節(jié),但是卻不會(huì)添加噪聲。
·Custom linear filters : (\Filters\Linear\Custom) 一個(gè)用于測(cè)試新的濾鏡功能核心的圖像用戶界面。
·Histogram : (\Colors\Histogram\...) 為了測(cè)試HistogramStretch(直方圖),這個(gè)示例中提供了很多菜單項(xiàng),通過不同的方法(0 = luminance, 1 = linked channels , 2 = independent channels)來測(cè)試直方圖功能。對(duì)于有噪聲的圖像,閾值(threshold)這個(gè)參數(shù)增強(qiáng)了算法的健壯性。半飽和度(Half Saturation)和全飽和度(Full Saturation)可以測(cè)試轉(zhuǎn)換顏色空間(ConvertColorSpace),直方圖(Histogram)和飽和度(Saturate)在YUV顏色空間對(duì)直方圖的拉伸效果。
·Thresholding : ( \Colors\Threshold... and \Colors\Adaptive Threshold). 透明度閾值(OptimalThreshold)是一個(gè)新的用于查找二進(jìn)制圖像透明度閾值的新方法。可選的算法有:
1 = 最大類間方差 (Otsu);
2 = 基特勒和伊爾林格沃斯(Kittler & Illingworth);
3 = 最大熵(maximum entropy);
4 = 位差(potential difference);
0 = 平均所有方法 (默認(rèn)情況下,這也是示例程序中所使用的方法);
"保留低于閾值的顏色"(preserve colors less than the threshold)的選項(xiàng),將測(cè)試Threshold2方法。這對(duì)于過濾帶有噪聲背景的彩色圖像很有用。經(jīng)過處理,我們將得到一幅帶有一致背景的彩色圖像(噪聲被去除)。AdaptiveThreshold是對(duì)方法OptimalThreshold的一個(gè)應(yīng)用,它將創(chuàng)建很多閾值模板。AdaptiveThreshold對(duì)于有著不一致的燈光照射效果的圖像,非常有用。對(duì)于這類圖像,我們不能簡(jiǎn)單地在整幅圖像中使用某個(gè)單一的閾值。但是,如果我們的參數(shù)設(shè)置得不對(duì),我們將得到一個(gè)非常差勁的處理結(jié)果。
·Add shadow : (\Filters\Add Shadow...) 這個(gè)菜單項(xiàng)的功能演示了如何將CxImage的多個(gè)小功能(選擇(selections),高斯模糊( GaussianBlur),混合( Mix))組合使用,以達(dá)到常見的圖像處理效果。
·Text smoothing : DrawStringEx 實(shí)現(xiàn)了一個(gè)新的選項(xiàng)CXTEXTINFO::smooth。我們可以通過文本工具(位于\View\Tools\Text),,選中抗鋸齒("antialias")選項(xiàng)對(duì)這個(gè)功能進(jìn)行測(cè)試。
類似的效果也同樣可以利用TextBlur (\Filters\Non Linear\Text Blur)進(jìn)行后處理獲得。這是一個(gè)非線性的過濾器,它只對(duì)角或圓形的邊緣起作用,從而不會(huì)影響到縱向或橫向的線。下圖展示了不同平滑方法的實(shí)際效果:
5 CxImage庫(kù)的結(jié)構(gòu)
在整個(gè)庫(kù)的繼承樹中,CxImage位于所有其他模塊的頂部。這不是一個(gè)完全的符合OOP的方式,但是至少?gòu)淖畛醯陌姹疽恢钡浆F(xiàn)在,它都工作得很好。現(xiàn)在想要改變整個(gè)結(jié)構(gòu),已經(jīng)太晚了。但是,你總是可以使用這些繼承類來操作相應(yīng)格式的圖像,例如你可以使用CxImageTIF來保存多頁(yè)的TIFF文件。這樣顯得非常直觀。
連接所有模塊和C庫(kù)的是CxFile。這是一個(gè)虛類,它提供了標(biāo)準(zhǔn)的方法,用于訪問硬盤或者內(nèi)存的文件數(shù)據(jù)。
5.1 CxImage的繼承樹
一個(gè)CxImage對(duì)象基本上對(duì)應(yīng)于一副位圖,同時(shí)添加了一些額外的成員變量用于存儲(chǔ)一些有用的信息。
class CxImage
{
...
protected:
void* pDib; //包含文件頭,調(diào)色板和像素?cái)?shù)據(jù)
BITMAPINFOHEADER head; //標(biāo)準(zhǔn)文件頭
CXIMAGEINFO info; //擴(kuò)展信息
BYTE* pSelection; //選區(qū)
BYTE* pAlpha; //alpha通道
CxImage** ppLayers; //普通層
CxImage** ppFrames; //動(dòng)畫的幀
}
CxImage::head 是位圖文件的文件頭,而CxImage::pDib就是一個(gè)普通的位圖(就像你在CxImageBMP::Encode中看到的一樣)。
CxImage::info 是一個(gè)方便的信息容器。這些信息被不同的文件格式所共享,同時(shí)供所有成員函數(shù)訪問。
typedef struct tagCxImageInfo {
DWORD dwEffWidth; //雙字節(jié)對(duì)齊寬度
BYTE* pImage; //圖像數(shù)據(jù)
void* pGhost; //如果這是一個(gè)備份(ghost),
//則pGhost指向它的原始對(duì)象
DWORD dwType; //原始圖像格式
char szLastError[256]; //調(diào)試信息,最后的錯(cuò)誤信息
long nProgress; //進(jìn)度
long nEscape; //取消
long nBkgndIndex; //GIF, PNG, MNG使用
RGBQUAD nBkgndColor; //RGB透明使用
BYTE nQuality; //JPEG使用
long nFrame; //TIF, GIF, MNG使用,表示當(dāng)前活動(dòng)幀
long nNumFrames; //TIF, GIF, MNG使用,表示總幀數(shù)
DWORD dwFrameDelay; //GIF, MNG使用,表示幀的延遲
long xDPI; //水平分辨率
long yDPI; //垂直分辨率
RECT rSelectionBox; //對(duì)象的外包圍框
BYTE nAlphaMax; //最大透明度
bool bAlphaPaletteEnabled; //如果調(diào)色板中的alpha值是啟用的,
//則這個(gè)變量為true
bool bEnabled; //啟用繪制函數(shù)
long xOffset;
long yOffset;
DWORD dwEncodeOption; //GIF, TIF使用:
// 0=def.1=unc,2=fax3,3=fax4,
// 4=pack,5=jpg
RGBQUAD last_c; //用于優(yōu)化GetNearestIndex
BYTE last_c_index;
bool last_c_isvalid;
long nNumLayers;
DWORD dwFlags;
} CXIMAGEINFO;
要理解CxImage的設(shè)計(jì)思路,通過類派生關(guān)系可以看出來,工程的類視圖里,在CxImage類上點(diǎn)右鍵,再點(diǎn)“Derived Classes”可以看到CxImage基類派生出來了哪些類,下面是彈出窗口的截圖:
從上圖可以看出,不同的派生類對(duì)應(yīng)一種不同的格式圖片。
5.2 CxImage的不同層
CxImage對(duì)象同樣是圖層的集合,每個(gè)圖層的緩沖區(qū)只在需要的時(shí)候申請(qǐng)。
CxImage::pDib是背景圖像。 CxImage::pAlpha是透明層。CxImage::pSelection是選區(qū)層,用于創(chuàng)建要對(duì)圖像的感興趣區(qū)域進(jìn)行處理的選擇區(qū)域。在這三個(gè)特殊層之上,你可以添加通用的其他層,這些層都保存在CxImage::ppLayers中。通用層也是完整的CxImage對(duì)象,所以你可以創(chuàng)建復(fù)雜的嵌套層。CxImage::ppFrames 為動(dòng)態(tài)圖像(GIF)所預(yù)留。
CxImage類成員和操作
CxImage使用Doxygen 產(chǎn)生文檔,但是由于一些歷史的原因,很多不太通用的功能還沒有文檔。類成員的參考資料,發(fā)布?xì)v史以及許可信息都可以在這里(here )找到。
5.3 支持的格式和選項(xiàng)
整個(gè)CxImage庫(kù)非常大,在主要的頭文件ximcfg.h中,你可以找到很多編譯選項(xiàng)開關(guān),用于啟用或者禁用某些特定的圖像格式或者功能。每個(gè)JPG, PNG和 TIFF庫(kù)將使得應(yīng)用程序增加大約100KB的大小,同時(shí),CxImage將使得應(yīng)用程序增加大約50KB的大小。所以,為了減小你的應(yīng)用程序的體積,你應(yīng)該支持和鏈接你的應(yīng)用程序確實(shí)需要的格式。
格式
|
定義#define
|
需要的庫(kù)
|
尺寸 [KB]
|
BMP GIF ICO TGA PCX WBMP WMF SKA
|
CXIMAGE_SUPPORT_BMP CXIMAGE_SUPPORT_GIF CXIMAGE_SUPPORT_ICO CXIMAGE_SUPPORT_TGA CXIMAGE_SUPPORT_PCX CXIMAGE_SUPPORT_WBMP CXIMAGE_SUPPORT_WMF CXIMAGE_SUPPORT_SKA
|
內(nèi)建
|
24
|
JPEG
|
CXIMAGE_SUPPORT_JPG
|
jpeg
|
88
|
PNG
|
CXIMAGE_SUPPORT_PNG
|
png, zlib
|
104
|
MNG
|
CXIMAGE_SUPPORT_MNG
|
mng, zlib, jpeg
|
148
|
TIFF
|
CXIMAGE_SUPPORT_TIF
|
tiff, zlib, jpeg
|
124
|
JBIG
|
CXIMAGE_SUPPORT_JBG
|
jbig
|
28
|
PNM,PPM,PGM RAS
|
CXIMAGE_SUPPORT_PNM CXIMAGE_SUPPORT_RAS
|
jasper
|
176
|
JPEG-2000
|
CXIMAGE_SUPPORT_JP2 CXIMAGE_SUPPORT_JPC CXIMAGE_SUPPORT_PGX
|
jasper
|
176
|
RAW
|
CXIMAGE_SUPPORT_RAW
|
libdcr
|
132
|
選項(xiàng)
|
定義#define
|
尺寸[KB]
|
CxImage核心
|
所有開關(guān)關(guān)閉
|
20
|
幾何變換 (geometric transformations)
|
CXIMAGE_SUPPORT_TRANSFORMATION
|
16
|
圖像處理
(image processing)
|
CXIMAGE_SUPPORT_DSP
|
24
|
繪制和特殊的窗口函數(shù)
(drawing and windows specific functions)
|
CXIMAGE_SUPPORT_WINDOWS
|
12
|
透明
(transparency)
|
CXIMAGE_SUPPORT_ALPHA
|
4
|
選擇
(selections)
|
CXIMAGE_SUPPORT_SELECTION
|
4
|
多層支持
(multiple layers)
|
CXIMAGE_SUPPORT_LAYERS
|
< 4
|
圖像格式轉(zhuǎn)換
(graphic formats conversion)
|
CXIMAGE_SUPPORT_DECODE CXIMAGE_SUPPORT_ENCODE
|
< 4
|
插值函數(shù)
(interpolation functions)
|
CXIMAGE_SUPPORT_INTERPOLATION
|
< 4
|
異常處理
(exception handling)
|
CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
< 4
|
5.4 文件處理類
CxFile為基類,派生出了CxIOFile和CxMemFile,第一個(gè)用于I/O交互操作使用的類,第二個(gè)用于數(shù)據(jù)在內(nèi)存中時(shí)模擬文件操作的使用。
6在你的項(xiàng)目中使用CxImage
如下圖所示,CxImgLib.dsw工作空間展示了構(gòu)建一個(gè)包含絕大多數(shù)功能和支持大多數(shù)圖像格式的應(yīng)用程序(demo.exe)所需要的所有庫(kù)。你必須先編譯所有的庫(kù),然后才可以鏈接你最終的應(yīng)用程序。
6.1 CxImgLib.dsw工作空間
在相同的工作空間中,你可以找到用于構(gòu)建不同庫(kù)和應(yīng)用程序的項(xiàng)目:
·CxImage : cximage.lib - 靜態(tài)庫(kù)
·CxImageCrtDll : cximagecrt.dll - DLL,不使用MFC
·CxImageMfcDll : cximage.dll - DLL,使用MFC
·Demo : 示例程序demo.exe,跟cximage.lib和C庫(kù)鏈接。
·DemoDll : demodll.exe - 跟cximagecrt.dll鏈接
·libdcr,jasper,jbig,jpeg,png,tiff,zlib : 靜態(tài)的C庫(kù)
構(gòu)建這些項(xiàng)目需要幾分鐘時(shí)間,當(dāng)所有項(xiàng)目構(gòu)建完成后,你可以選擇demo項(xiàng)目并執(zhí)行應(yīng)用程序。
要想在你自己的項(xiàng)目中使用CxImage,你必須編輯下面這些項(xiàng)目設(shè)置設(shè)置(針對(duì)Visual C++ 6.0):
Project Settings(項(xiàng)目設(shè)置)
|- C/C++
| |- Code Generation
| | |- 運(yùn)行時(shí)庫(kù) : 多線程DLL(所有鏈接的庫(kù)都必須使用相同的設(shè)置)
| | |- 結(jié)構(gòu)成員對(duì)齊方式 : 所有鏈接的庫(kù)都必須相同
| |- 預(yù)編譯頭文件 : 不使用預(yù)編譯頭文件
| |- 預(yù)處理器:
| |- 添加額外的包含(Include)路徑: ..\cximage
|- Link
|- General
|- Object/library modules(附加的依賴庫(kù)): ../png/Debug/png.lib
../raw/Debug/libdcr.lib
../jpeg/Debug/jpeg.lib
../zlib/Debug/zlib.lib
../tiff/Debug/tiff.lib
../jasper/Debug/jasper.lib
../cximage/Debug/cximage.lib ...
在你的源代碼中,你必須引入CxImage的頭文件ximage.h。在你的代碼中添加如下語句:
#include "ximage.h"。
注意,不要混合debug和release模塊,每個(gè)配置必須使用各自相應(yīng)的庫(kù)文件。
6.2 在CxImage中添加自定義的函數(shù)
為CxImage添加一個(gè)新的圖像處理函數(shù)并不困難。在這里,我將以CxImage::Jitter為例子,描述如何為CxImage添加自定義的函數(shù)。雖然這個(gè)函數(shù)很簡(jiǎn)單, 但是它卻展示了使用CxImage時(shí)所需要注意的方方面面。
首先,我們需要聲明這個(gè)函數(shù):
bool Jitter(long radius=2)
在ximage.h頭文件的CXIMAGE_SUPPORT_DSP部分,你可以在public區(qū)域的任何部分聲明這個(gè)函數(shù)。
現(xiàn)在,我們開始定義這個(gè)函數(shù):
bool CxImage::Jitter(long radius)
{
// 檢查圖像是否合法,這應(yīng)當(dāng)是這個(gè)函數(shù)的第一行
if (!pDib) return false;
// 局部變量
long nx,ny;
// 臨時(shí)圖像,用于存儲(chǔ)算法的部分結(jié)果
CxImage tmp(*this,pSelection!=0,true,true);
// 限制函數(shù)僅僅作用在選區(qū)(通過Selection...()函數(shù)定義)的最小區(qū)域
// 這將加快整個(gè)循環(huán)的速度,提高算法效率
long xmin,xmax,ymin,ymax;
if (pSelection){
xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
} else {
xmin = ymin = 0;
xmax = head.biWidth; ymax=head.biHeight;
}
// 主循環(huán) : 垂直方向掃描圖像
for(long y=ymin; y <ymax; y++){
// 監(jiān)視循環(huán)的進(jìn)度
info.nProgress = (long)(100*y/head.biHeight);
// 檢查應(yīng)用程序是否已經(jīng)退出
if (info.nEscape) break;
// 主循環(huán) : 水平方向掃描圖像
for(long x=xmin; x<xmax; x++){
// 如果選區(qū)功能啟用了,則僅僅處理選區(qū)內(nèi)部的像素
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsInside(x,y))
#endif //CXIMAGE_SUPPORT_SELECTION
{
// 主算法
nx=x+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
ny=y+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
if (!IsInside(nx,ny)) {
nx=x;
ny=y;
}
// 保存結(jié)果到臨時(shí)圖像中.
// 如果可以,24位圖像請(qǐng)使用PixelColor,
// 而8,4和1位圖像請(qǐng)使用PixelIndex,這樣可以加快速度。
if (head.biClrUsed==0){
tmp.SetPixelColor(x,y,GetPixelColor(nx,ny));
} else {
tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny));
}
// 如果啟用了透明度功能,則處理透明圖層中的像素
#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaSet(x,y,AlphaGet(nx,ny));
#endif //CXIMAGE_SUPPORT_ALPHA
}
}
}
// 保存結(jié)果并退出
Transfer(tmp);
return true;
}
6.3示例: 如何轉(zhuǎn)換一種格式到另外一種格式
CxImage image;
// bmp -> jpg
image.Load("image.bmp", CXIMAGE_FORMAT_BMP);
if (image.IsValid()){
if(!image.IsGrayScale()) image.IncreaseBpp(24);
image.SetJpegQuality(80);
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);
}
6.4 如何從資源中加載圖像
//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);
或者
//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);
}
或者
//Load a bitmap resource;
HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1)));
CxImage *newImage = new CxImage();
newImage->CreateFromHBITMAP(bitmap);
CxImage image((BYTE*)buffer,size,image_type);
或者
CxMemFile memfile((BYTE*)buffer,size);
CxImage image(&memfile,image_type);
或者
CxMemFile memfile((BYTE*)buffer,size);
CxImage* image = new CxImage();
image->Decode(&memfile,type);
6.6 如何對(duì)內(nèi)存中的圖像編碼
long size=0;
BYTE* buffer=0;
image.Encode(buffer,size,image_type);
...
image.FreeMemory(buffer);
或者
CxMemFile memfile;
memfile.Open();
image.Encode(&memfile,image_type);
BYTE* buffer = memfile.GetBuffer();
long size = memfile.Size();
...
image.FreeMemory(buffer);
6.7 如何創(chuàng)建一副多頁(yè)的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);
或者
FILE* 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);
6.8 如何復(fù)制和粘貼圖像
//復(fù)制(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();
6.9 如何在圖片框控件(Picture Box)中顯示圖像
HBITMAP m_bitmap = NULL;
CxImage image("myfile.png", CXIMAGE_FORMAT_PNG);
...
CDC* hdc = m_picture.GetDC();
HBITMAP m_bitmap = image.MakeBitmap(hdc->m_hDC);
HBITMAP hOldBmp = m_picture.SetBitmap(m_bitmap);
if (hOldBmp) DeleteObject(hOldBmp);
if (hdc->m_hDC) m_picture.ReleaseDC(hdc);
...
if (m_bitmap) DeleteObject(m_bitmap);
譯后序:
關(guān)于圖像處理庫(kù),我相信大家有一個(gè)共同的疑問:這么多圖像處理庫(kù),我該如何選擇?在CSDN的blog中有這樣一段文字,比較透徹地回答了這個(gè)問題,感謝作者的透徹解釋:
"CxImage類庫(kù)是一 個(gè)優(yōu)秀的圖像操作類庫(kù)。它可以快捷地存取、顯示、轉(zhuǎn)換各種圖像。有的讀者可能說,有那么多優(yōu)秀的圖形庫(kù),如OpenIL,FreeImage, PaintLib等等,它們可謂是功能強(qiáng)大,齊全,沒必要用其它的類庫(kù)。但我要說,這些類庫(kù)基本上沒有免費(fèi)的,使用這些類庫(kù),你要被這樣那樣的許可協(xié)議所束縛。
在這點(diǎn)上,CxImage類庫(kù)是完全免費(fèi)的。另外,在使用上述類-align:left;mso-pagination:widow-orphan'> 譯后序:
關(guān)于圖像處理庫(kù),我相信大家有一個(gè)共同的疑問:這么多圖像處理庫(kù),我該如何選擇?在CSDN的blog中有這樣一段文字,比較透徹地回答了這個(gè)問題,感謝作者的透徹解釋:
"CxImage類庫(kù)是一 個(gè)優(yōu)秀的圖像操作類庫(kù)。它可以快捷地存取、顯示、轉(zhuǎn)換各種圖像。有的讀者可能說,有那么多優(yōu)秀的圖形庫(kù),如OpenIL,FreeImage, PaintLib等等,它們可謂是功能強(qiáng)大,齊全,沒必要用其它的類庫(kù)。但我要說,這些類庫(kù)基本上沒有免費(fèi)的,使用這些類庫(kù),你要被這樣那樣的許可協(xié)議所束縛。
在這點(diǎn)上,CxImage類庫(kù)是完全免費(fèi)的。另外,在使用上述類庫(kù)時(shí),你會(huì)遇到重重麻煩。因?yàn)樗鼈兇蟛糠质瞧脚_(tái)無關(guān)的,且用C語言寫成,有的還夾雜 著基本的C++ wrapper和成堆德編譯選項(xiàng)的聲明需要你去處理。而CxImage類庫(kù)在這方面做得很好。還有讓我最看好的,就是作者完全公開了源代碼。相對(duì)于那些封裝好的圖形庫(kù)和GDI+來說,這一點(diǎn)使我們可以進(jìn)一步學(xué)習(xí)各種編解碼技術(shù),而不再浮于各種技術(shù)的表面。"