2月92015
[教程]第十五讲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[2] = [5, 5], $right[2] = [305, 5], $leftd[2] = [5, 305] Global $TempBitmap = _GDIPlus_ImageClone($hfileBitmap) Global $hBitmap ;色调,亮度,饱和度,对比度 Global $hue = 0, $Lum = 0, $Sat = 1, $Con = 1 Global $hWnd, $hPicWnd, $hOldProc Global $color[4][2] 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[0][0] = GUICtrlCreateSlider(80, 405, 100) GUICtrlSetLimit(-1, 360, 0) GUICtrlSetData(-1, $hue) _GUICtrlSlider_SetTicFreq(-1, 30) $color[0][1] = GUICtrlCreateLabel("", 190, 405, 40, 25) GUICtrlSetData(-1, $hue) GUICtrlCreateLabel(" 图像亮度", 5, 435) $color[1][0] = GUICtrlCreateSlider(80, 435, 100) GUICtrlSetLimit(-1, 10, -10) GUICtrlSetData(-1, $Lum) _GUICtrlSlider_SetTicFreq(-1, 2) $color[1][1] = GUICtrlCreateLabel("", 190, 435, 40, 25) GUICtrlSetData(-1, $Lum) GUICtrlCreateLabel("图像饱和度", 5, 465) $color[2][0] = GUICtrlCreateSlider(80, 465, 100) GUICtrlSetLimit(-1, 10, 0) GUICtrlSetData(-1, 1) _GUICtrlSlider_SetTicFreq(-1, 1) $color[2][1] = GUICtrlCreateLabel("", 190, 465, 40, 25) GUICtrlSetData(-1, $Sat) GUICtrlCreateLabel("图像对比度", 5, 495) $color[3][0] = GUICtrlCreateSlider(80, 495, 100) GUICtrlSetLimit(-1, 100, 10) _GUICtrlSlider_SetTicFreq(-1, 10) GUICtrlSetData(-1, 10) $color[3][1] = 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[0][0]) $hue = GUICtrlRead($color[0][0]) GUICtrlSetData($color[0][1], $hue) Case GUICtrlGetHandle($color[1][0]) $Lum = GUICtrlRead($color[1][0]) / 10 GUICtrlSetData($color[1][1], $Lum) Case GUICtrlGetHandle($color[2][0]) $Sat = GUICtrlRead($color[2][0]) GUICtrlSetData($color[2][1], $Sat) Case GUICtrlGetHandle($color[3][0]) $Con = GUICtrlRead($color[3][0])/10 GUICtrlSetData($color[3][1], $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[0] = _WinAPI_LoWord($lParam) $left[1] = _WinAPI_HiWord($lParam) _WinAPI_InvalidateRect($hWnd) Case 2 $right[0] = _WinAPI_LoWord($lParam) $right[1] = _WinAPI_HiWord($lParam) _WinAPI_InvalidateRect($hWnd) Case 3 $leftd[0] = _WinAPI_LoWord($lParam) $leftd[1] = _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[0] - 3, $left[1] - 3, $left[0] + 3, $left[1] + 3) If _WinAPI_PtInRect($tRect, $tPoint) Then $flag = 1 EndIf $tRect = _WinAPI_CreateRect($right[0] - 3, $right[1] - 3, $right[0] + 3, $right[1] + 3) If _WinAPI_PtInRect($tRect, $tPoint) Then $flag = 2 EndIf $tRect = _WinAPI_CreateRect($leftd[0] - 3, $leftd[1] - 3, $leftd[0] + 3, $leftd[1] + 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[0], $left[1], $right[0], $right[1], $leftd[0], $leftd[1], _ 0, 0, $fileW, $fileH) Local $hPen = _GDIPlus_PenCreate(0xFFFF0000) ;绘制确定平行四边形的三个点的区域,当鼠标在这区域时能拖动 _GDIPlus_GraphicsDrawRect($hBackbuffer, $left[0] - 3, $left[1] - 3, 6, 6, $hPen) _GDIPlus_GraphicsDrawRect($hBackbuffer, $right[0] - 3, $right[1] - 3, 6, 6, $hPen) _GDIPlus_GraphicsDrawRect($hBackbuffer, $leftd[0] - 3, $leftd[1] - 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[1] < 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```
本文固定链接: http://jianyiit.com/post-70.html
扫描二维码,在手机上阅读
发表评论
木有头像就木JJ啦!还木有头像吗?点这里申请属于你的个性Gravatar头像吧!