精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
GDI+學(xué)習(xí)及代碼總結(jié)之-----坐標(biāo)變換、矩陣變換及色彩變換
坐標(biāo)變換、矩陣變換
在Graphics類中,有幾個(gè)函數(shù)實(shí)現(xiàn)了簡(jiǎn)單的坐標(biāo)變換
[cpp] view plaincopy
Graphics::TranslateTransform(dx, dy, order)//平移坐標(biāo)系
Graphics::RotateTransform(angle, order)//旋轉(zhuǎn)坐標(biāo)系
Graphics::ScaleTransform(sx, sy, order)//縮放坐標(biāo)系
這里有個(gè)order參數(shù)著重講一下,它是指矩陣的乘法順序,是左乘還是右乘;
除了這幾個(gè)基本函數(shù)以外,還可以使用矩陣來變換坐標(biāo)系,使用
[cpp] view plaincopy
Graphics::SetTransform(matrix)
來進(jìn)行設(shè)置,但目前還用不太到矩陣變換,所以就先不仔細(xì)寫筆記了,如果想具體了解,看《精通GDI+編程》第六章
色彩變換
GDI+提供了Image類和Bitmap類來保存、維護(hù)圖片的信息。對(duì)于色彩的存儲(chǔ),Image類和Bitmap類使用一個(gè)32位的數(shù)值來保存。紅、綠、藍(lán)及透明度各占8位,每一個(gè)色彩分量的取值范圍是0-255。透明度為0表示完全透明,為255時(shí),色彩完全可見。對(duì)透明度的的支持是GDI+的一大特色,但同時(shí)也為色彩的運(yùn)算增加了一定的難度。
一、色彩信息的矩陣表示
四階表示
由于一個(gè)色彩信息包含R、G、B、Alpha信息,所以,我們必然要使用一個(gè)4階色彩變換矩陣來修改色彩的每一個(gè)分量值:
注意:對(duì)于色彩變換矩陣,這里的色彩順序是R、G、B、A而不是A、R、G、B!!!
如果想將色彩(0,255,0,255)更改為半透明時(shí),可以使用下面的的矩陣運(yùn)算來表示:
為什么使用五階矩陣
上面使用四階矩陣完全可以改變圖片的RGBA值了,但考慮一種情況,如果我們只想在原有的R色上增加一些分量呢?
這時(shí),我們就得再多加一階來表示平移變換。所以,一個(gè)既包含線性變換,又包含平移變換的組合變換,稱為仿射變換。使用四階的色彩變換矩陣來修改色彩,只能夠?qū)ι实拿恳粋€(gè)分量值進(jìn)行乘(除)運(yùn)算,如果要對(duì)這些分量值進(jìn)行加減法的運(yùn)算(平移變換),只能通過五階矩陣來完成。
考慮下面這個(gè)變換:
1、紅色分量值更改為原來的2倍;
2、綠色分量增加100;
則使用4階矩陣的乘法無法實(shí)現(xiàn),所以,應(yīng)該在四階色彩變換矩陣上增加一個(gè)“啞元坐標(biāo)”,來實(shí)現(xiàn)所列的矩陣運(yùn)算。
這個(gè)矩陣中,分量值用的是100,但在實(shí)際應(yīng)用中,并沒有100這個(gè)數(shù),而是用下面的分量飽和度的方法來表示的。
色彩飽和度,是指某色彩占總飽和度(255)的分量,比如一個(gè)像素的紅色(R值)值為A,那么A/255的值就稱為紅色分量飽和度。上面的100分量,它的飽和度就是100/255=0.39
所以,假設(shè)有一個(gè)像素的色彩值為(0.2,0.0,0.7,1)---注意用了色彩飽和度表示,在實(shí)際運(yùn)算中,就是這么表示的。如果想達(dá)到對(duì)紅色分量飽和度擴(kuò)大2倍,并且分別將3種基準(zhǔn)色的飽和度都加上0.2,則引入的色彩矩陣應(yīng)該是:
GDI+的色彩變換矩陣(ColorMatrix)
在上面的所有講解之后,大家也應(yīng)該看出來了,色彩變換矩陣的表示形式,肯定是五階的那種,所以大家看一下,在默認(rèn)情況下,色彩變換矩陣的形式:
所以跟上面的講解一樣:
1、對(duì)角線上的數(shù)值,相當(dāng)于對(duì)RGB分量進(jìn)行乘法操作。
2、修改最后一行上的數(shù)值,相當(dāng)于對(duì)RGB分量的飽和度進(jìn)行加(減)運(yùn)算。
GDI+對(duì)色彩變換矩陣的修改是通過ImageAttributes對(duì)象的SetColorMatrix函數(shù)進(jìn)行的,其調(diào)用方法如下:
[cpp] view plaincopy
Status SetColorMatrix(
const ColorMatrix* colorMatrix,
ColorMatrixFlags mode,
ColorAdjustType type
);
參數(shù)說明:
colorMatrix:[in]色彩變換矩陣,數(shù)據(jù)類型為ColorMatrix,下面具體講;
mode:[in]修改的標(biāo)記,ColorMatrixFlags枚舉類,它的值可以是以下3個(gè)
[cpp] view plaincopy
enum ColorMatrixFlags{
ColorMatrixFlagsDefault   = 0,//修改所有的顏色值,包括灰度;
ColorMatrixFlagsSkipGrays = 1,//修改所有的顏色值,但不包括灰度;
ColorMatrixFlagsAltGray   = 2//對(duì)灰度和顏色使用不同的色彩變換矩陣進(jìn)行修改;
};
type:[in]使用色彩矩陣調(diào)整的對(duì)象;
著重講下colorMatrix
先看下定義:
[cpp] view plaincopy
struct ColorMatrix{
REAL  m[5][5];//5*5數(shù)組
};
所以我們?cè)诙xColorMatrix時(shí),應(yīng)當(dāng)這樣賦值
[cpp] view plaincopy
ColorMatrix colorMatrix={
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,2.0f,0.0f,0.0f,0.0f, //將綠色調(diào)調(diào)整為原來的2倍
0.0f,0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.2f,0.0f,0.0f,1.0f//在將綠色,在原有綠色調(diào)的基礎(chǔ)上增加0.2飽和度
};
就是上面這個(gè)轉(zhuǎn)換矩陣,看個(gè)例子
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMatrix colorMatrix={
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.2f,0.0f,0.0f,1.0f
};
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,RectF(0,0,width,height));
graphics.TranslateTransform(width+10,0);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
二、色彩幾種運(yùn)算方式(平移、縮放、旋轉(zhuǎn)、投射)
色彩的平移運(yùn)算
色彩的平移運(yùn)算,實(shí)際上就是色彩的加法運(yùn)算。其實(shí)就是在色彩變換矩陣的最后一行加上某個(gè)值;
圖中的灰色部分就是參與色彩平移運(yùn)算的4個(gè)矩陣元素。
我們看個(gè)例子,(圖片中紅色分量增加0.2飽和度)
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMatrix colorMatrix={
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,
0.2f,0.0f,0.0f,0.0f,1.0f
};
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,RectF(0,0,width,height));
graphics.TranslateTransform(width+10,0);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
我們看右邊的圖像是怎么變過來的,由于圖片是由一個(gè)個(gè)像素組成的,所以用每個(gè)像素的飽和度組成數(shù)組,來乘轉(zhuǎn)換矩陣,結(jié)果就是轉(zhuǎn)換后的當(dāng)前點(diǎn)的顏色值,值得說明的是,顏色的飽和度最大為1,當(dāng)運(yùn)算后的值超過1時(shí),截取小數(shù)部分做為色彩分量飽和度(書上是這么寫的P284,但試驗(yàn)之后,并不是);看下面這個(gè)轉(zhuǎn)換例子:
色彩的縮放運(yùn)算
色彩的縮放運(yùn)算其實(shí)就是色彩的乘法運(yùn)算。在色彩矩陣對(duì)角線上的分別代表R、G、B、A的幾個(gè)值,將其分別乘以指定的值。這就是所謂的縮放變換。
再重復(fù)一遍:值得說明的是,顏色的飽和度最大為1,當(dāng)運(yùn)算后的值超過1時(shí),截取小數(shù)部分做為色彩分量飽和度(書上是這么寫的P284,但試驗(yàn)之后,并不是);
看個(gè)例子吧:(將藍(lán)色分量擴(kuò)大兩倍)
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMatrix colorMatrix={
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,2.0f,0.0f,0.0f,//B分量變?yōu)?倍
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,1.0f
};
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,RectF(0,0,width,height));
graphics.TranslateTransform(width+10,0);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
縮放變換的特殊應(yīng)用(通道輸出)
由于在色彩變換矩陣中,對(duì)角線上的數(shù)的取值范圍是從0-1的,所以當(dāng)取0時(shí),這個(gè)色彩就完全不顯示,所以當(dāng)我們R、G都取0,而獨(dú)有B取1時(shí),就只顯示了藍(lán)色,所形成的圖像也就是我們通常說的藍(lán)色通道;看下幾個(gè)通道輸出的效果圖:
示例:(只演示綠色通道輸出)
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMatrix colorMatrix={
0.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,1.0f
};
//繪制原圖
graphics.DrawImage(&image,RectF(0,0,width,height));
//繪制變換后的圖像
graphics.TranslateTransform(width+10,0);
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
色彩的旋轉(zhuǎn)運(yùn)算
RGB色是如何旋轉(zhuǎn)的呢,首先用R、G、B三色建立立體坐標(biāo)系:
所以,我們可以把一個(gè)色彩值看成三維空間里的一個(gè)點(diǎn),色彩值的三個(gè)分量可以看成該點(diǎn)的坐標(biāo)(三維坐標(biāo))。我們先不考慮,在三個(gè)維度綜合情況下是怎么旋轉(zhuǎn)的,我們先看看,在某個(gè)軸做為Z軸,在另兩個(gè)軸形成的平面上旋轉(zhuǎn)的情況,下圖分析了,在將藍(lán)色軸做為Z軸,僅在紅—綠平面上旋轉(zhuǎn)a度的情況:
這里我們分別講解下為什么最終的R=原R*cosa-原G*sina;
在圖中,我們可以看到,在旋轉(zhuǎn)后,原R在R軸的分量變?yōu)?原R*cosa,但原G分量在旋轉(zhuǎn)后,在R軸上也有了分量,但分量落在了負(fù)軸上,所以我們要減去這部分分量,所以最終的結(jié)果是最終的R=原R*cosa-原G*sina;
下面就看下書上關(guān)于幾種旋轉(zhuǎn)計(jì)算及結(jié)果矩陣,(注意:這幾個(gè)圖只標(biāo)記了原X軸色彩分量的旋轉(zhuǎn),沒有把Y軸色彩分量的旋轉(zhuǎn)標(biāo)記出來)
構(gòu)造一個(gè)“紅色繞著藍(lán)色旋轉(zhuǎn)”的色彩變換矩陣
構(gòu)造一下“綠色繞著紅色旋轉(zhuǎn)”的色彩變換矩陣
構(gòu)造一下“藍(lán)色繞著紅色旋轉(zhuǎn)”的色彩變換矩陣
示例:(紅色向藍(lán)色旋轉(zhuǎn)60度)
注意:為了演示如何清除色彩矩陣,這里顛倒了變換圖像與原圖的顯示順序;注意加上頭文件<math.h>
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
//紅色繞藍(lán)色旋轉(zhuǎn)
ColorMatrix colorMatrix={
cos(60.0f),sin(60.0f),0.0f,0.0f,0.0f,
-sin(60.0f),cos(60.0f),0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,1.0f
};
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
//輸出原圖
graphics.TranslateTransform(width+10,0);
imageAttributes.ClearColorMatrix(ColorAdjustTypeBitmap);//清除色彩變換
graphics.DrawImage(&image,RectF(0,0,width,height));
色彩的投射運(yùn)算
上面我們對(duì)對(duì)角線上的值進(jìn)行了修改,對(duì)最后一行的值進(jìn)行了修改,但對(duì)其它位置的值還沒有修改。這里指的位置,看下圖陰影部分;
對(duì)這些值進(jìn)行修改時(shí),修改所使用的增加值來自于其它色彩分量的信息。
看下具體的運(yùn)算方式:
注意:最終結(jié)果的0.5=0.2*1+1*0.3,可見紅色分量在原有紅色分量的基礎(chǔ)上,增加了綠色分量值的0.3倍;利用其它色彩分量的倍數(shù)來更改自己色彩分量的值,這種運(yùn)算就叫投射運(yùn)算。
示例:(紅色分量在原有基礎(chǔ)上增加上綠色分量的40%)
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMatrix colorMatrix={
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.4f,0.0f,1.0f,0.0f,0.0f,//增加綠色分量值的0.4倍
0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,1.0f
};
//繪制原圖
graphics.DrawImage(&image,RectF(0,0,width,height));
//繪制變換后的圖
graphics.TranslateTransform(width+10,0);
imageAttributes.SetColorMatrix(&colorMatrix,ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
三、色彩映射(色彩替換)
色彩映射,說白了,就是對(duì)圖片原有的顏色進(jìn)行替換,比如將原來的藍(lán)色替換成紅色。在制作電視時(shí),背景通常都是藍(lán)色的,目的是為了方便后期視頻的深加工。如果需要更改背景或者進(jìn)行視頻合成,只需要將藍(lán)色背景摳去,保留主要畫面就行了。
GDI+中使用ColorMap結(jié)構(gòu)體就能實(shí)現(xiàn)將指定顏色替換成其它顏色。ImageAttributes類的SetRemapTable(設(shè)置重映射表)可以將這個(gè)數(shù)據(jù)結(jié)構(gòu)應(yīng)用到圖像中,SetRemapTable函數(shù)的調(diào)用格式為:
[cpp] view plaincopy
Status SetRemapTable(
UINT mapSize,
const ColorMap* map,
ColorAdjustType type
);
ColorMap的定義格式如下:
[cpp] view plaincopy
struct ColorMap{
Color  oldColor;
Color  newColor;
};
參數(shù)說明:
mapSize:[in]ColorMap數(shù)組大小;
map:[in]ColorMap數(shù)組,表示一種或多種色彩替換的對(duì)應(yīng)關(guān)系,如果數(shù)組中定義了多個(gè)替換關(guān)系,那么所有被定義要替換的顏色都將被替換掉。
type:[in]表示在什么對(duì)象上進(jìn)行色彩替換。
示例:(將原圖中的背景,全部替換成純紅色---注意背景由兩種顏色組成)
[cpp] view plaincopy
Image image(L"wlh.bmp");
ImageAttributes imageAttributes;
UINT width=image.GetWidth();
UINT height=image.GetHeight();
ColorMap colorMap[2];
colorMap[0].oldColor=Color(255,0,0,255);
colorMap[0].newColor=Color(255,255,0,0);
colorMap[1].oldColor=Color(255,0,145,247);
colorMap[1].newColor=Color(255,255,0,0);
imageAttributes.SetRemapTable(2,colorMap,ColorAdjustTypeBitmap);
graphics.DrawImage(&image,RectF(0,0,width,height));
//繪制變換后的圖
graphics.TranslateTransform(width+10,0);
graphics.DrawImage(&image,Rect(0,0,width,height),0,0,width,height,UnitPixel,&imageAttributes);
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C#兩種獲取灰度圖像的方法
GDI+的色彩變換
Android色彩矩陣
Windows GDI和GDI+編程實(shí)例剖析 (6)
Special effects on images with new GDIPlus-X classes - Part 1
一個(gè)菜鳥的圖像處理入門
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 太湖县| 兖州市| 抚顺县| 盘锦市| 东城区| 南投县| 苏州市| 张家川| 安康市| 孟州市| 山阴县| 洛川县| 江川县| 沭阳县| 高陵县| 贵德县| 邹平县| 麻阳| 咸宁市| 廊坊市| 张家界市| 克什克腾旗| 翁源县| 沙雅县| 黄山市| 即墨市| 博野县| 开平市| 高陵县| 和田市| 松桃| 始兴县| 兴文县| 迁西县| 太湖县| 福安市| 洪雅县| 富民县| 伊通| 金坛市| 扶余县|