第十五讲GDI+图像之颜色矩阵
一、GDI+图像绘制时,可以通过图像属性来改变图像1、图像属性建立
$hIA = _GDIPlus_ImageAttributesCreate()
2、图像属性设置颜色矩阵
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pColorMatrix)
$pColorMatrix为指向颜色矩阵的指针
3、根据图像属性绘制图像
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, 位图句柄, 源矩形区域, 目标矩形区域, $hIA)
二、颜色矩阵
_GDIPlus_ColorMatrixCreate()
例子中有几个颜色矩阵的示例
颜色矩阵网上写的较好的,地址
GDI+ for VCL基础 -- 颜色调整矩阵ColorMatrix详解
GDI+ ColorMatrix的完全揭秘
测试中发现图像属性设置颜色矩阵,只对24位色以上起作用,所以示例中增加了位深不足时,转换位深的例子
#include <APIConstants.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>
#include <GDIPlusEx.au3>
#include <GuiSlider.au3>
Global $au3Dir = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\Autoit", "InstallDir");au3安装目录
Global $imageFile = $au3Dir & '\Examples\WinAPIEx\Extras\AutoIt.bmp'
Global $hCallback = DllCallbackRegister("YourFunc", "int", "hWnd;uint;wparam;lparam");函数名,返回值,参数
Global $ptrCallback = DllCallbackGetPtr($hCallback)
Global $flag = 0
_GDIPlus_Startup()
Global $hfileBitmap = _GDIPlus_BitmapCreateFromFile($imageFile)
Global $fileW = _GDIPlus_ImageGetWidth($hfileBitmap)
Global $fileH = _GDIPlus_ImageGetHeight($hfileBitmap)
;左上角、右上角和左下角
Global $left = , $right = , $leftd =
Global $TempBitmap = _GDIPlus_ImageClone($hfileBitmap)
Global $hBitmap
;色调,亮度,饱和度,对比度
Global $hue = 0, $Lum = 0, $Sat = 1, $Con = 1
Global $hWnd, $hPicWnd, $hOldProc
Global $color
Global $hRestore, $hGray, $hInverse, $hRed
Global $open, $save
GuiInit()
update()
While 1
$Msg = GUIGetMsg()
Switch $Msg
Case -3
ExitLoop
Case $hRestore
restore()
Case $hGray
gray()
Case $hInverse
inverse()
Case $hRed
red()
Case $open
open()
Case $save
save()
EndSwitch
WEnd
_GDIPlus_ImageDispose($TempBitmap)
_GDIPlus_BitmapDispose($hfileBitmap)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()
GUIDelete()
Exit
Func GuiInit()
$hWnd = GUICreate("第十五讲GDI+图像", 500, 525)
GUICtrlCreatePic("", 0, 0, 500, 400)
$hPicWnd = GUICtrlGetHandle(-1)
$hOldProc = _WinAPI_SetWindowLong($hPicWnd, $GWL_WNDPROC, $ptrCallback)
GUICtrlCreateLabel(" 图像色调", 5, 405)
$color = GUICtrlCreateSlider(80, 405, 100)
GUICtrlSetLimit(-1, 360, 0)
GUICtrlSetData(-1, $hue)
_GUICtrlSlider_SetTicFreq(-1, 30)
$color = GUICtrlCreateLabel("", 190, 405, 40, 25)
GUICtrlSetData(-1, $hue)
GUICtrlCreateLabel(" 图像亮度", 5, 435)
$color = GUICtrlCreateSlider(80, 435, 100)
GUICtrlSetLimit(-1, 10, -10)
GUICtrlSetData(-1, $Lum)
_GUICtrlSlider_SetTicFreq(-1, 2)
$color = GUICtrlCreateLabel("", 190, 435, 40, 25)
GUICtrlSetData(-1, $Lum)
GUICtrlCreateLabel("图像饱和度", 5, 465)
$color = GUICtrlCreateSlider(80, 465, 100)
GUICtrlSetLimit(-1, 10, 0)
GUICtrlSetData(-1, 1)
_GUICtrlSlider_SetTicFreq(-1, 1)
$color = GUICtrlCreateLabel("", 190, 465, 40, 25)
GUICtrlSetData(-1, $Sat)
GUICtrlCreateLabel("图像对比度", 5, 495)
$color = GUICtrlCreateSlider(80, 495, 100)
GUICtrlSetLimit(-1, 100, 10)
_GUICtrlSlider_SetTicFreq(-1, 10)
GUICtrlSetData(-1, 10)
$color = GUICtrlCreateLabel("", 190, 495, 40, 25)
GUICtrlSetData(-1, $Con)
$hRestore = GUICtrlCreateButton("复位颜色", 250, 405)
$hGray = GUICtrlCreateButton("灰度图", 250, 435)
$hInverse = GUICtrlCreateButton("反色图", 250, 465)
$hRed = GUICtrlCreateButton("红色通道", 250, 495)
$open = GUICtrlCreateButton("打开", 350, 405, 100, 50)
$save = GUICtrlCreateButton("保存", 350, 465, 100, 50)
GUIRegisterMsg($WM_HSCROLL, "onHSCROLL")
GUISetState()
EndFunc ;==>GuiInit
Func onHSCROLL($hWnd, $iMsg, $wParam, $lParam)
Switch $lParam
Case GUICtrlGetHandle($color)
$hue = GUICtrlRead($color)
GUICtrlSetData($color, $hue)
Case GUICtrlGetHandle($color)
$Lum = GUICtrlRead($color) / 10
GUICtrlSetData($color, $Lum)
Case GUICtrlGetHandle($color)
$Sat = GUICtrlRead($color)
GUICtrlSetData($color, $Sat)
Case GUICtrlGetHandle($color)
$Con = GUICtrlRead($color)/10
GUICtrlSetData($color, $Con)
EndSwitch
ChangeColor()
EndFunc ;==>onHSCROLL
Func YourFunc($hWnd, $iMsg, $wParam, $lParam)
Switch $iMsg
Case $WM_PAINT
Local $tPAINTSTRUCT
Local $hDC = _WinAPI_BeginPaint($hWnd, $tPAINTSTRUCT)
update()
Return _WinAPI_EndPaint($hWnd, $tPAINTSTRUCT)
Case $WM_MOUSEMOVE
WM_MOUSEMOVE($hWnd, $iMsg, $wParam, $lParam)
Case $WM_LBUTTONDOWN
WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
Case $WM_LBUTTONUP
WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
EndSwitch
Return _WinAPI_CallWindowProc($hOldProc, $hWnd, $iMsg, $wParam, $lParam);没有处理的消息让原先的处理程序处理
EndFunc ;==>YourFunc
Func WM_MOUSEMOVE($hWnd, $Msg, $wParam, $lParam)
Switch $flag
Case 1
$left = _WinAPI_LoWord($lParam)
$left = _WinAPI_HiWord($lParam)
_WinAPI_InvalidateRect($hWnd)
Case 2
$right = _WinAPI_LoWord($lParam)
$right = _WinAPI_HiWord($lParam)
_WinAPI_InvalidateRect($hWnd)
Case 3
$leftd = _WinAPI_LoWord($lParam)
$leftd = _WinAPI_HiWord($lParam)
_WinAPI_InvalidateRect($hWnd)
EndSwitch
Return 1
EndFunc ;==>WM_MOUSEMOVE
Func WM_LBUTTONDOWN($hWnd, $Msg, $wParam, $lParam)
Local $tPoint = _WinAPI_CreatePoint(_WinAPI_LoWord($lParam), _WinAPI_HiWord($lParam))
$tRect = _WinAPI_CreateRect($left - 3, $left - 3, $left + 3, $left + 3)
If _WinAPI_PtInRect($tRect, $tPoint) Then
$flag = 1
EndIf
$tRect = _WinAPI_CreateRect($right - 3, $right - 3, $right + 3, $right + 3)
If _WinAPI_PtInRect($tRect, $tPoint) Then
$flag = 2
EndIf
$tRect = _WinAPI_CreateRect($leftd - 3, $leftd - 3, $leftd + 3, $leftd + 3)
If _WinAPI_PtInRect($tRect, $tPoint) Then
$flag = 3
EndIf
Return 0
EndFunc ;==>WM_LBUTTONDOWN
Func WM_LBUTTONUP($hWnd, $Msg, $wParam, $lParam)
$flag = 0
Return 0
EndFunc ;==>WM_LBUTTONUP
Func update()
Local $HWND_CX = _WinAPI_GetWindowWidth($hPicWnd)
Local $HWND_CY = _WinAPI_GetWindowHeight($hPicWnd)
Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hPicWnd)
;==========================二次缓冲绘制开始,先把图片绘制在$hBitmap上=======================
_GDIPlus_BitmapDispose($hBitmap)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($HWND_CX, $HWND_CY, $hGraphics)
Local $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsClear($hBackbuffer, 0xFFECE9D8)
;根据三点确定平行四边形,把图像绘制到平行四边形中
_GDIPlus_GraphicsDrawImagePointsRect($hBackbuffer, $TempBitmap, $left, $left, $right, $right, $leftd, $leftd, _
0, 0, $fileW, $fileH)
Local $hPen = _GDIPlus_PenCreate(0xFFFF0000)
;绘制确定平行四边形的三个点的区域,当鼠标在这区域时能拖动
_GDIPlus_GraphicsDrawRect($hBackbuffer, $left - 3, $left - 3, 6, 6, $hPen)
_GDIPlus_GraphicsDrawRect($hBackbuffer, $right - 3, $right - 3, 6, 6, $hPen)
_GDIPlus_GraphicsDrawRect($hBackbuffer, $leftd - 3, $leftd - 3, 6, 6, $hPen)
;绘制图片控件的下边框,看着舒服一点
_GDIPlus_PenSetColor($hPen, 0xFFA0A0A0)
_GDIPlus_GraphicsDrawLine($hBackbuffer, 0, $HWND_CY - 1, $HWND_CX, $HWND_CY - 1, $hPen)
_GDIPlus_PenDispose($hPen)
;==========================二次缓冲绘制结束=======================
;==========================把$hBitmap绘制到$pic控件画布上=======================
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $HWND_CX, $HWND_CY)
_GDIPlus_GraphicsDispose($hBackbuffer)
_GDIPlus_GraphicsDispose($hGraphics)
EndFunc ;==>update
Func ChangeColor()
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($TempBitmap)
Local $hIA = _GDIPlus_ImageAttributesCreate()
;创建单位颜色矩阵
Local $tColorMatrix = _GDIPlus_ColorMatrixCreate()
Local $pColorMatrix = DllStructGetPtr($tColorMatrix)
;创建色调颜色矩阵
Local $tPreHue = _GDIPlus_ColorMatrixCreate()
Local $tPostHue = _GDIPlus_ColorMatrixCreate()
_GDIPlus_ColorMatrixInitHue($tPreHue, $tPostHue)
;创建亮度颜色矩阵
Local $tLumMatrix = _GDIPlus_ColorMatrixCreateTranslate($Lum, $Lum, $Lum)
;创建饱和度颜色矩阵
Local $tSatMatrix = _GDIPlus_ColorMatrixCreateSaturation($Sat)
;创建对比度颜色矩阵,对比度矩阵网上说法较多,我感觉这个效果还可以
Local $tConMatrix = _GDIPlus_ColorMatrixCreateScale($Con, $Con, $Con)
;矩阵相乘
_GDIPlus_ColorMatrixMultiply($tColorMatrix, $tLumMatrix)
_GDIPlus_ColorMatrixMultiply($tColorMatrix, $tSatMatrix)
_GDIPlus_ColorMatrixMultiply($tColorMatrix, $tConMatrix)
;通过旋转$hue角度调整图像色调
_GDIPlus_ColorMatrixRotateHue($tColorMatrix, $tPreHue, $tPostHue, $hue)
;设置颜色矩阵到图像属性
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pColorMatrix)
;根据$hIA图像属性绘制图像
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hfileBitmap, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH, $hIA)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageAttributesDispose($hIA)
;更新图片控件
_WinAPI_InvalidateRect($hPicWnd)
EndFunc ;==>ChangeColor
Func restore()
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($TempBitmap)
_GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hfileBitmap, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH)
_GDIPlus_GraphicsDispose($hGraphics)
;更新图片控件
_WinAPI_InvalidateRect($hPicWnd)
EndFunc ;==>restore
Func gray()
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($TempBitmap)
Local $hIA = _GDIPlus_ImageAttributesCreate()
;灰度矩阵
Local $tColorMatrix = _GDIPlus_ColorMatrixCreateGrayScale()
Local $pColorMatrix = DllStructGetPtr($tColorMatrix)
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pColorMatrix)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hfileBitmap, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH, $hIA)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageAttributesDispose($hIA)
;更新图片控件
_WinAPI_InvalidateRect($hPicWnd)
EndFunc ;==>gray
Func inverse()
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($TempBitmap)
Local $hIA = _GDIPlus_ImageAttributesCreate()
;反色矩阵
Local $tColorMatrix = _GDIPlus_ColorMatrixCreateNegative()
Local $pColorMatrix = DllStructGetPtr($tColorMatrix)
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pColorMatrix)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hfileBitmap, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH, $hIA)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageAttributesDispose($hIA)
;更新图片控件
_WinAPI_InvalidateRect($hPicWnd)
EndFunc ;==>inverse
Func red()
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($TempBitmap)
Local $hIA = _GDIPlus_ImageAttributesCreate()
Local $tColorMatrix = _GDIPlus_ColorMatrixCreate()
Local $pColorMatrix = DllStructGetPtr($tColorMatrix)
DllStructSetData($tColorMatrix, "m", 1, 1);主对角线1设置为1,就是红色成份全部显示
DllStructSetData($tColorMatrix, "m", 0, 7);主对角线7设置为0,就是绿色成份不显示
DllStructSetData($tColorMatrix, "m", 0, 13);主对角线13设置为0,就是蓝色成份不显示
_GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pColorMatrix)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hfileBitmap, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH, $hIA)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageAttributesDispose($hIA)
;更新图片控件
_WinAPI_InvalidateRect($hPicWnd)
EndFunc ;==>red
Func open()
$imageFile = FileOpenDialog("请选择文件", @DesktopDir, "图像 (*.jpg;*.bmp;*.png)")
If @error Then
MsgBox(4096, "", "没有选择文件!")
Else
_GDIPlus_ImageDispose($TempBitmap)
_GDIPlus_BitmapDispose($hfileBitmap)
Local $hfile = _GDIPlus_BitmapCreateFromFile($imageFile)
$fileW = _GDIPlus_ImageGetWidth($hfileBitmap)
$fileH = _GDIPlus_ImageGetHeight($hfileBitmap)
$ret = _GDIPlus_ImageGetPixelFormat($hfile);获取颜色位深,位深小于24不能使用颜色矩阵
If $ret < 24 Then;如果位深小于24,则转换为24位深位图
$hfileBitmap = _GDIPlus_BitmapCreateFromScan0($fileW, $fileH);建立24位深位图
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hfileBitmap)
_GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hfile, 0, 0, $fileW, $fileH, 0, 0, $fileW, $fileH)
_GDIPlus_GraphicsDispose($hGraphics)
Else
$hfileBitmap = _GDIPlus_ImageClone($hfile)
EndIf
_GDIPlus_ImageDispose($hfile)
$TempBitmap = _GDIPlus_ImageClone($hfileBitmap)
_WinAPI_InvalidateRect($hPicWnd)
EndIf
EndFunc ;==>open
Func save()
Local $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
_GDIPlus_ImageSaveToFileEx($hBitmap, @DesktopDir & "\15讲图像.jpg", $sCLSID)
MsgBox(4096,"","图像保存成功!")
EndFunc ;==>save 可以发现代码中融入了状态机思想,真是漂亮。 回复 2# pusofalse
原来,flag = 0,1,2,3叫状态机,领教了 感谢seniors分享,辛苦了~~ 没有在autoit看到过状态机怎么使用,但在NI的软件中经常使用,学习下。 楼主技术不错,教程不仅对AU3,学哪种语言的想多熟悉了解GDI+,看楼主的教程没错 楼主牛得很呀!~~ 厉害 厉害啊 学习了.......支持一下 学习了.......支持一下 慢慢学习 谢谢大师
页:
[1]