dejhost Posted January 3, 2019 Share Posted January 3, 2019 Happy New Year everyone! I would like to extract the color values of certain pixels in an image. This is how I picture the workflow: User opens an image of his choice. Image is shown on the screen. User draws a line into the image. This happens by marking the startpixel and the endpixel of the line The line is drawn, so the user can check visually if he is happy with the line. The following pixel based properties belonging to the line are stored in Excel: X-Coordinate Y-Coordinate Color Value Additional operations: Extracting for max- and min. color values; Statistical operations. Browsing through the helpfile of AutoIt I find plenty of functions for treating images (e.g. GDIPlus), but I am completely unsure if Autoit will get me there. Should I read the entire image into an array? Should I rather attempt to script an external image software (e.g. IrfanView, Gimp)? I would be very thankful if someone could give some recommendations and maybe list a couple of the most important commands to use. Thank you very much. Dejhost Link to comment Share on other sites More sharing options...
dejhost Posted January 4, 2019 Author Share Posted January 4, 2019 (edited) Hello again, documenting roughly what I've done so far: Open image: _GDIPlus_ImageLoadFromFile Draw the Image: _GDIPlus_GraphicsDrawImageRect Ask user for Start- and End-point of the line by running twice: MouseGetPos() But how to retrieve the pixel-coordinates that the line covers? Is there a way to get a 2D-array? Afterward, I would use the following function to get the pixel colors: _GDIPlus_BitmapGetPixel Thanks in advance for any advice! Edited January 4, 2019 by dejhost grammar Link to comment Share on other sites More sharing options...
Nine Posted January 4, 2019 Share Posted January 4, 2019 (edited) Yes it is totally doable with GDI+. There are a few examples in the help file that are somewhat close to what you want to create. The functions that you mentioned will certainly be part of the solution...To get the pixel, you will probably have to use some of the basic geometry that you learned in HS. Happy scripting ! Edited January 4, 2019 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
dejhost Posted January 4, 2019 Author Share Posted January 4, 2019 Thank you for your encouraging words. So at least I am on the right track :-) If I have to rely on my HS-memories, the result would not be accurate: I recall that there are plenty of ways to connect 2 points based on pixels. I'd rather use the same method for retrieving the pixel coordinates as the AutoIt uses for drawing the line: Within the GDIPlus.au3, I find the function _GDIPlus_GraphicsDrawLine calls for a dll: Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipDrawImageRectRect", "handle", $hGraphics, "handle", $hImage, _ "float", $nDstX, "float", $nDstY, "float", $nDstWidth, "float", $nDstHeight, _ "float", $nSrcX, "float", $nSrcY, "float", $nSrcWidth, "float", $nSrcHeight, _ "int", $iUnit, "handle", $pAttributes, "ptr", 0, "ptr", 0) I will try to track down this dll. Hoping it is so kind to tell me how it draws lines :-) Link to comment Share on other sites More sharing options...
Nine Posted January 5, 2019 Share Posted January 5, 2019 nn for that complex dllcalll. dont over-complex your script when you can do it with std func. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
dejhost Posted January 5, 2019 Author Share Posted January 5, 2019 (edited) 10 hours ago, Nine said: nn for that complex dllcalll. dont over-complex your script when you can do it with std func. What do you mean by "std func"? Standard functions? If you know a function that could suit, please share. thx. Edited January 5, 2019 by dejhost Link to comment Share on other sites More sharing options...
Nine Posted January 5, 2019 Share Posted January 5, 2019 3 hours ago, dejhost said: What do you mean by "std func"? Standard functions? Yes here to start you up : expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WinAPIHObj.au3> #include <Color.au3> Global $g_hGUI, $g_hGfxCtxt, $g_hBitmap, $g_hBMP, $g_hGraphics Global $aCursA, $aCursB, $Completed = False AutoItSetOption("GUIOnEventMode", 1) _GDIPlus_Startup() $g_hBMP = _GDIPlus_BitmapCreateFromFile ("BaseImage.jpg") Global $iWidth = _GDIPlus_ImageGetWidth ($g_hBMP), $iHeight = _GDIPlus_ImageGetHeight ($g_hBMP) $g_hGUI = GUICreate("GDI+", $iWidth, $iHeight+100) $idButton = GUICtrlCreateButton ("Completed", int($iWidth/2)-100, $iHeight+30, 200, 50) GUICtrlSetOnEvent(-1, "Complete") GUISetState(@SW_SHOW) $g_hGraphics = _GDIPlus_GraphicsCreateFromHWND($g_hGUI) ;create a graphics object from a window handle $g_hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $g_hGraphics) $g_hGfxCtxt = _GDIPlus_ImageGetGraphicsContext($g_hBitmap) GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") _GDIPlus_GraphicsDrawImage($g_hGfxCtxt, $g_hBMP, 0, 0) ;draw bitmap to backbuffer Do _GDIPlus_GraphicsDrawImageRect($g_hGraphics, $g_hBitmap, 0, 0, $iWidth, $iHeight) ;copy drawn bitmap to graphics handle (GUI) $aCursA = GUIGetCursorInfo ($g_hGUI) if @error then ContinueLoop $aCursB = $aCursA Local $iX = -1, $iY = -1 While $aCursB[2] and $aCursB[0] <= $iWidth and $aCursB[1] <= $iHeight $aCursB = GUIGetCursorInfo ($g_hGUI) if $iX = $aCursB[0] and $iY = $aCursB[1] then ContinueLoop $iX = $aCursB[0] $iY = $aCursB[1] _GDIPlus_GraphicsClear($g_hGfxCtxt, 0xFF000000) ;clear bitmap for repaint _GDIPlus_GraphicsDrawImage($g_hGfxCtxt, $g_hBMP, 0, 0) _GDIPlus_GraphicsDrawImageRect($g_hGraphics, $g_hBitmap, 0, 0, $iWidth, $iHeight) _GDIPlus_GraphicsDrawLine($g_hGraphics, $aCursA[0], $aCursA[1], $aCursB[0], $aCursB[1]) _GDIPlus_GraphicsDrawLine($g_hGfxCtxt, $aCursA[0], $aCursA[1], $aCursB[0], $aCursB[1]) Wend Sleep (100) Until $Completed _Exit () Func Complete () $Completed = True EndFunc Func _Exit() _GDIPlus_GraphicsDispose($g_hGfxCtxt) _GDIPlus_GraphicsDispose($g_hGraphics) _GDIPlus_BitmapDispose($g_hBitmap) _GDIPlus_BitmapDispose($g_hBMP) _GDIPlus_Shutdown() GUIDelete($g_hGUI) EndFunc “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Malkey Posted January 6, 2019 Share Posted January 6, 2019 This _PixelsInLineToArray function will calculate the "x" or "y" value from the equation of a straight line of two points. Example:- If the two points are pt1(10,10) and pt2(13, 30) then the "y" values are used to calculate the 21 "x" values. (The difference in "y" values is greater than the difference in "x" values.) This will return 21 x, y, and pixel colours in the array. If the "x" values were used, there would only be 4 calculations made from 10 to 13, which would return a 4 element array. expandcollapse popup#include <Array.au3> #include <WinAPIGdi.au3> ; Using $scale in position calculations is sometimes necessary when, under the system's ; "Display" settings, the "Scale and layout" parameter is not 100%. ; When the "Scale and layout" parameter is 100%, this $scale value = 1. Global $scale = _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth Local $Pt1[2] = [52, 28] Local $Pt2[2] = [50, 60] _ArrayDisplay(_PixelsInLineToArray($Pt1[0], $Pt1[1], $Pt2[0], $Pt2[1])) ; Parameters:- ; $Pt1X, $Pt1Y - are the x and y coordinates of point 1 ; $Pt2X, $Pt2Y - are the x and y coordinates of point 2 ; Returns: A 2D array:- ; $aArray[0] contains the X coordinate of the pixel ; $aArray[1] contains the Y coordinate of the pixel ; $aArray[3] contains the colour of the pixel in 0xRRGGBB 24bit hex. colour format. (This is what PixelGetColor returns) ; Where, "RR" (0-255) Red channel, "GG" (0-255) Green channel, "BB" (0-255) Blue channel. ; For 32bit GDIPlus hex colour format is 0xAARRGGBB. Where. "AA" (0-255) is Alpha channel (transparency). ; Examples of 0xRRGGBB 24bit hex. colour format:- 0xFFFFFF is white, 0x000000 is black, 0xFF0000 is red, 0x00FF00 is green. ; Func _PixelsInLineToArray($Pt1X, $Pt1Y, $Pt2X, $Pt2Y) If Abs($Pt1X - $Pt2X) > Abs($Pt1Y - $Pt2Y) Then If $Pt1X > $Pt2X Then ; If Abs($Pt1X - $Pt2X) has the greater distance, make Point 2 "x" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line Local $aArray[($Pt2X - $Pt1X) + 1][3] For $x = $Pt1X To $Pt2X ; Note: $Pt2X has a greater value than $Pt1X. $aArray[$x - $Pt1X][0] = $x $aArray[$x - $Pt1X][1] = Round(($m * $x) - ($m * $Pt1X) + $Pt1Y, 0) ; y = $m(x - x1) + y1 (y value from equation for a straight line) $aArray[$x - $Pt1X][2] = "0x" & Hex(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale), 6) Next Return $aArray Else If $Pt1Y > $Pt2Y Then ; If Abs($Pt1Y - $Pt2Y) has the greater distance, make Point 2 "y" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient Local $aArray[$Pt2Y - $Pt1Y + 1][3] For $y = $Pt1Y To $Pt2Y ; Note: $Pt2Y has a greater value than $Pt1Y $aArray[$y - $Pt1Y][0] = Round(($y / $m) - ($Pt1Y / $m) + $Pt1X, 0) ; x = (y - y1)/$m + x1 (x value from equation for a straight line) $aArray[$y - $Pt1Y][1] = $y $aArray[$y - $Pt1Y][2] = "0x" & Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6) Next Return $aArray EndIf EndFunc ;==>_PixelsInLineToArray Gianni 1 Link to comment Share on other sites More sharing options...
dejhost Posted January 6, 2019 Author Share Posted January 6, 2019 I used "UEZ" tool "show Histogram" as a starting point for my approach: https://bit.ly/2GXZMZ9. The histograms are a "nice to have" feature for me, and everything is nicely done. I am about to implement "Bresenham's line algorithm" (https://bit.ly/2RGh2Gx) to get the pixels in the line. Once done, I will implement drawing the line based on the points in the array - and then compare our results with one another. I will come back to you soon. Link to comment Share on other sites More sharing options...
dejhost Posted January 7, 2019 Author Share Posted January 7, 2019 Hello Malkey, I realized by now that you implemented the Bresenham's formula. :-) I used the function For $k = 1 to UBound($aArray,1)-1 Step 1 _GDIPlus_GraphicsFillRect( $hGraphics, $aArray[$k][0], $aArray[$k][1], 1,1 ) Next to draw the line from the array - just as a visual control. It seems correct. But I struggle with the color code, although you have inserted a nice description: Quote Where, "RR" (0-255) Red channel, "GG" (0-255) Green channel, "BB" (0-255) Blue channel. ; For 32bit GDIPlus hex colour format is 0xAARRGGBB. Where. "AA" (0-255) is Alpha channel (transparency). ; Examples of 0xRRGGBB 24bit hex. colour format:- 0xFFFFFF is white, 0x000000 is black, 0xFF0000 is red, 0x00FF00 is green. I am currently only treating grayscale images. So in case, the user opens a color image, it will get converted to grayscale prior analysis.* In this case, the values for R, G and B are identical. So the information I am looking for is actually contained in each channel. My goal is to get the gray values in a scale of 0-255. So, hexadecimal is not the right format for my purposes. This is why I changed your code from $aArray[$y - $Pt1Y][2] = "0x" & Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6) to $aArray[$y - $Pt1Y][2] = StringRight(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale),2) How do I proceed? How to apply the scale that I am looking for? Thank you all for your support! *I read in an post that the grayscale conversion by GDIPLUS is not very good. The post was quite old - did the function improve? Would you recommend to use another program to perform the conversion? I could send a command to IrfanView, for example.... Link to comment Share on other sites More sharing options...
Malkey Posted January 8, 2019 Share Posted January 8, 2019 (edited) See the comments in the attached example about the color channel's value. To address your concerns about grayscale conversion quality, see the example under the _GDIPlus_ColorMatrixCreateGrayScale function in the AutoIt help file. ; This gets the 24 bit pixel colour in hex. colour format 0xRRGGBB ; These three separate colour channels, Red, Green, and Blue each range hexadeciminally from "00" to "FF" (0-255). ConsoleWrite("0x" & Hex(PixelGetColor(100, 150), 6) & @CRLF) ; Example return 0xF0F4F9 ; This gets the pixel's far right 8 bit colour channel, Blue, in hexadeciminal (base 16). ConsoleWrite("0x" & StringRight(Hex(PixelGetColor(100, 150), 6), 2) & @CRLF) ; Example return 0xF9 ; This gets the pixel's far right 8 bit colour channel, Blue, in deciminal (base 10). ConsoleWrite(Dec(StringRight(Hex(PixelGetColor(100, 150), 6), 2)) & @CRLF) ; Example return 249 ; Replacement line for script. ; $aArray[$y - $Pt1Y][2] = Dec(StringRight(Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6), 2)) Edited January 8, 2019 by Malkey Added link to _GDIPlus_ColorMatrixCreateGrayScale Link to comment Share on other sites More sharing options...
dejhost Posted January 8, 2019 Author Share Posted January 8, 2019 Thank you very much! Works like a charm I am using _GDIPlus_ColorMatrixCreateGrayScale - function. The GDIPlus.au3 calls a dll - meaning I can't track down how the matrix is setup. Would be nice to know how the red-, green- and blue channels get weighted during the conversion. But I can compare with the results of GDIPlus and IrfanView at a later stage. --- As I mentioned earlier, I use _GDIPlus_GraphicsDrawLine and _GDIPlus_GraphicsFillRect to draw lines. These lines are drawn on top of an image that I opened with _GDIPlus_GraphicsDrawImageRectRect. Applying the function _GDIPlus_ImageSaveToFile does not save the line along with the image - only the original image itself. In order to get a snapshot of both, image and line, I've used a workaround so far: I am taking a screenshot with autoit. But the soution not very convenient and fails easily. Is there a more elegant way to save image and line together in a jpg? Link to comment Share on other sites More sharing options...
Malkey Posted January 9, 2019 Share Posted January 9, 2019 (edited) When this example first starts the values in the 5x5 gray-scale color matrix are displayed. To use this example:- Press left mouse button down, drag and move the mouse, then release the left mouse button to draw a line. Press middle mouse button or Ctrl key to clear lines, Press Alt+"s" to save the image with the last line drawn. expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <ScreenCapture.au3> #include <WinAPIHObj.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <Misc.au3> Global $scale = _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth Example() Func Example() Local $dll = DllOpen("user32.dll"), $aMPosNew If Not FileExists(@ScriptDir & "\cmy-circles.jpg") Then _ InetGet("http://www.epi-centre.com/basics/color/images/cmy-circles.jpg", _ @ScriptDir & "\cmy-circles.jpg") _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\cmy-circles.jpg") Local $iWidth = _GDIPlus_ImageGetWidth($hImage) Local $iHeight = _GDIPlus_ImageGetHeight($hImage) Local $hGUI = GUICreate("GDI+ Example (" & @ScriptName & ")", $iWidth, $iHeight, 10, 10, $WS_POPUP) ;create a test GUI GUISetState(@SW_SHOW) Local $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI) ;create a graphics object from a window handle Local $hBM = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphicGUI) ;create a Bitmap object based on a graphics object Local $hGraphicBM = _GDIPlus_ImageGetGraphicsContext($hBM) ;get the graphics context of the image / bitmap to draw on image / bitmap _GDIPlus_GraphicsSetSmoothingMode($hGraphicBM, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;sets the graphics object rendering quality (antialiasing) Local $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object Local $tColorMatrix = _GDIPlus_ColorMatrixCreateGrayScale() ;create greyscale color matrix _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set greyscale color matrix _GDIPlus_GraphicsClear($hGraphicBM, 0xFF000000) _GDIPlus_GraphicsDrawImageRectRect($hGraphicBM, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hIA) ;draw the bitmap while applying the color adjustment _GDIPlus_GraphicsDrawImageRect($hGraphicGUI, $hBM, 0, 0, $iWidth, $iHeight) Local $hPen = _GDIPlus_PenCreate(0xffff0000, 2) _DisplayColorMatrix($tColorMatrix) Do Select Case _IsPressed("01", $dll) ; Left mouse button down - Drag and move mouse - Release left mouse button to draw a line If WinExists("Pixels", "") Then WinClose("Pixels", "") $aMPos = MouseGetPos() Do Sleep(10) Until Not _IsPressed("01", $dll) $aMPosNew = MouseGetPos() Local $aArr = _PixelsInLineToArray($aMPos[0], $aMPos[1], $aMPosNew[0], $aMPosNew[1]) If UBound($aArr) > 1 Then _GDIPlus_GraphicsDrawLine($hGraphicGUI, $aMPosNew[0], $aMPosNew[1], $aMPos[0], $aMPos[1], $hPen) _ArrayDisplay($aArr, "Pixels") EndIf Case _IsPressed("04", $dll) Or _IsPressed("11", $dll) ; Press middle mouse button, or, Ctrl key to clear lines _GDIPlus_GraphicsClear($hGraphicBM) _GDIPlus_GraphicsClear($hGraphicGUI) _GDIPlus_GraphicsDrawImageRectRect($hGraphicBM, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hIA) ;draw the bitmap while applying the color adjustment _GDIPlus_GraphicsDrawImageRect($hGraphicGUI, $hBM, 0, 0, $iWidth, $iHeight) Case _IsPressed("12", $dll) And _IsPressed("53", $dll) ; Press Alt + "s" to save image _GDIPlus_GraphicsDrawLine($hGraphicBM, $aMPosNew[0], $aMPosNew[1], $aMPos[0], $aMPos[1], $hPen) _GDIPlus_ImageSaveToFile($hBM, @ScriptDir & "\SCTesta.jpg") ShellExecuteWait(@ScriptDir & "\SCTesta.jpg") EndSelect Until GUIGetMsg() = $GUI_EVENT_CLOSE ;cleanup GDI+ resources _GDIPlus_ImageAttributesDispose($hIA) _GDIPlus_GraphicsDispose($hGraphicGUI) _GDIPlus_GraphicsDispose($hGraphicBM) _GDIPlus_PenDispose($hPen) _GDIPlus_BitmapDispose($hImage) _GDIPlus_BitmapDispose($hBM) _GDIPlus_Shutdown() GUIDelete($hGUI) EndFunc ;==>Example Func _DisplayColorMatrix($tCMStruct) ; See $tagGDIPCOLORMATRIX AutoIt Help File Local $aArray[5][5] For $i = 1 To 5 For $j = 1 To 5 $aArray[$i - 1][$j - 1] = DllStructGetData($tCMStruct, 1, (($i - 1) * 5) + $j) Next Next _ArrayDisplay($aArray, "Display ColorMatrix") EndFunc ;==>_DisplayColorMatrix ; Parameters:- ; $Pt1X, $Pt1Y - are the x and y coordinates of point 1 ; $Pt2X, $Pt2Y - are the x and y coordinates of point 2 ; Returns: A 2D array:- ; $aArray[0] contains the X coordinate of the pixel ; $aArray[1] contains the Y coordinate of the pixel ; $aArray[3] contains the colour of the pixel in 0xRRGGBB hex. colour format. ; Func _PixelsInLineToArray($Pt1X, $Pt1Y, $Pt2X, $Pt2Y) ConsoleWrite($Pt1X & " " & $Pt1Y & " " & $Pt2X & " " & $Pt2Y & @CRLF) If Abs($Pt1X - $Pt2X) > Abs($Pt1Y - $Pt2Y) Then If $Pt1X > $Pt2X Then ; If Abs($Pt1X - $Pt2X) has the greater distance, make Point 2 "x" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line ; x = x1 +(y - y1)/$m Local $aArray[($Pt2X - $Pt1X) + 1][3] For $x = $Pt1X To $Pt2X ; Note: $Pt2X has a greater value than $Pt1X. $aArray[$x - $Pt1X][0] = $x $aArray[$x - $Pt1X][1] = Round(($m * $x) - ($m * $Pt1X) + $Pt1Y, 0) $aArray[$x - $Pt1X][2] = "0x" & Hex(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale), 6) Next Return $aArray Else If $Pt1Y > $Pt2Y Then ; If Abs($Pt1Y - $Pt2Y) has the greater distance, make Point 2 "y" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line Local $aArray[$Pt2Y - $Pt1Y + 1][3] For $y = $Pt1Y To $Pt2Y ; Note: $Pt2Y has a greater value than $Pt1Y $aArray[$y - $Pt1Y][0] = Round(($y / $m) - ($Pt1Y / $m) + $Pt1X, 0) $aArray[$y - $Pt1Y][1] = $y $aArray[$y - $Pt1Y][2] = "0x" & Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6) Next Return $aArray EndIf EndFunc ;==>_PixelsInLineToArray Edited January 11, 2019 by Malkey Updated import image to GUI. Link to comment Share on other sites More sharing options...
dejhost Posted January 11, 2019 Author Share Posted January 11, 2019 On 1/9/2019 at 1:54 PM, Malkey said: When this example first starts the values in the 5x5 gray-scale color matrix are displayed. To use this example:- Press left mouse button down, drag and move the mouse, then release the left mouse button to draw a line. Press middle mouse button or Ctrl key to clear lines, Press Alt+"s" to save the image with the last line drawn. expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <ScreenCapture.au3> #include <WinAPIHObj.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <Misc.au3> Global $scale = _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth Example() Func Example() Local $dll = DllOpen("user32.dll"), $aMPosNew If Not FileExists(@ScriptDir & "\cmy-circles.jpg") Then _ InetGet("http://www.epi-centre.com/basics/color/images/cmy-circles.jpg", _ @ScriptDir & "\cmy-circles.jpg") _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\cmy-circles.jpg") Local $iWidth = _GDIPlus_ImageGetWidth($hImage) Local $iHeight = _GDIPlus_ImageGetHeight($hImage) Local $hGUI = GUICreate("GDI+ Example (" & @ScriptName & ")", $iWidth, $iHeight, 10, 10, $WS_POPUP) ;create a test GUI GUISetState(@SW_SHOW) Local $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI) ;create a graphics object from a window handle Local $hBM = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphicGUI) ;create a Bitmap object based on a graphics object Local $hGraphicBM = _GDIPlus_ImageGetGraphicsContext($hBM) ;get the graphics context of the image / bitmap to draw on image / bitmap _GDIPlus_GraphicsSetSmoothingMode($hGraphicBM, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;sets the graphics object rendering quality (antialiasing) Local $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object Local $tColorMatrix = _GDIPlus_ColorMatrixCreateGrayScale() ;create greyscale color matrix _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set greyscale color matrix _GDIPlus_GraphicsClear($hGraphicBM, 0xFF000000) _GDIPlus_GraphicsDrawImageRectRect($hGraphicBM, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hIA) ;draw the bitmap while applying the color adjustment _GDIPlus_GraphicsDrawImageRect($hGraphicGUI, $hBM, 0, 0, $iWidth, $iHeight) Local $hPen = _GDIPlus_PenCreate(0xffff0000, 2) _DisplayColorMatrix($tColorMatrix) Do Select Case _IsPressed("01", $dll) ; Left mouse button down - Drag and move mouse - Release left mouse button to draw a line If WinExists("Pixels", "") Then WinClose("Pixels", "") $aMPos = MouseGetPos() Do Sleep(10) Until Not _IsPressed("01", $dll) $aMPosNew = MouseGetPos() Local $aArr = _PixelsInLineToArray($aMPos[0], $aMPos[1], $aMPosNew[0], $aMPosNew[1]) If UBound($aArr) > 1 Then _GDIPlus_GraphicsDrawLine($hGraphicGUI, $aMPosNew[0], $aMPosNew[1], $aMPos[0], $aMPos[1], $hPen) _ArrayDisplay($aArr, "Pixels") EndIf Case _IsPressed("04", $dll) Or _IsPressed("11", $dll) ; Press middle mouse button, or, Ctrl key to clear lines _GDIPlus_GraphicsClear($hGraphicBM) _GDIPlus_GraphicsClear($hGraphicGUI) _GDIPlus_GraphicsDrawImageRectRect($hGraphicBM, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hIA) ;draw the bitmap while applying the color adjustment _GDIPlus_GraphicsDrawImageRect($hGraphicGUI, $hBM, 0, 0, $iWidth, $iHeight) Case _IsPressed("12", $dll) And _IsPressed("53", $dll) ; Press Alt + "s" to save image _GDIPlus_GraphicsDrawLine($hGraphicBM, $aMPosNew[0], $aMPosNew[1], $aMPos[0], $aMPos[1], $hPen) _GDIPlus_ImageSaveToFile($hBM, @ScriptDir & "\SCTesta.jpg") ShellExecuteWait(@ScriptDir & "\SCTesta.jpg") EndSelect Until GUIGetMsg() = $GUI_EVENT_CLOSE ;cleanup GDI+ resources _GDIPlus_ImageAttributesDispose($hIA) _GDIPlus_GraphicsDispose($hGraphicGUI) _GDIPlus_GraphicsDispose($hGraphicBM) _GDIPlus_PenDispose($hPen) _GDIPlus_BitmapDispose($hImage) _GDIPlus_BitmapDispose($hBM) _GDIPlus_Shutdown() GUIDelete($hGUI) EndFunc ;==>Example Func _DisplayColorMatrix($tCMStruct) ; See $tagGDIPCOLORMATRIX AutoIt Help File Local $aArray[5][5] For $i = 1 To 5 For $j = 1 To 5 $aArray[$i - 1][$j - 1] = DllStructGetData($tCMStruct, 1, (($i - 1) * 5) + $j) Next Next _ArrayDisplay($aArray, "Display ColorMatrix") EndFunc ;==>_DisplayColorMatrix ; Parameters:- ; $Pt1X, $Pt1Y - are the x and y coordinates of point 1 ; $Pt2X, $Pt2Y - are the x and y coordinates of point 2 ; Returns: A 2D array:- ; $aArray[0] contains the X coordinate of the pixel ; $aArray[1] contains the Y coordinate of the pixel ; $aArray[3] contains the colour of the pixel in 0xRRGGBB hex. colour format. ; Func _PixelsInLineToArray($Pt1X, $Pt1Y, $Pt2X, $Pt2Y) ConsoleWrite($Pt1X & " " & $Pt1Y & " " & $Pt2X & " " & $Pt2Y & @CRLF) If Abs($Pt1X - $Pt2X) > Abs($Pt1Y - $Pt2Y) Then If $Pt1X > $Pt2X Then ; If Abs($Pt1X - $Pt2X) has the greater distance, make Point 2 "x" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line ; x = x1 +(y - y1)/$m Local $aArray[($Pt2X - $Pt1X) + 1][3] For $x = $Pt1X To $Pt2X ; Note: $Pt2X has a greater value than $Pt1X. $aArray[$x - $Pt1X][0] = $x $aArray[$x - $Pt1X][1] = Round(($m * $x) - ($m * $Pt1X) + $Pt1Y, 0) $aArray[$x - $Pt1X][2] = "0x" & Hex(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale), 6) Next Return $aArray Else If $Pt1Y > $Pt2Y Then ; If Abs($Pt1Y - $Pt2Y) has the greater distance, make Point 2 "y" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line Local $aArray[$Pt2Y - $Pt1Y + 1][3] For $y = $Pt1Y To $Pt2Y ; Note: $Pt2Y has a greater value than $Pt1Y $aArray[$y - $Pt1Y][0] = Round(($y / $m) - ($Pt1Y / $m) + $Pt1X, 0) $aArray[$y - $Pt1Y][1] = $y $aArray[$y - $Pt1Y][2] = "0x" & Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6) Next Return $aArray EndIf EndFunc ;==>_PixelsInLineToArray 2 Malkey, once again: thank you very much for your help. I always wonder how you guys manage to post entire scripts as replies: takes me many days to get my stuff working, and you seem to be able to write withing 10min... I am currently stuck and working on another problem, but will soon implement your solution. Best regards, dejhost Link to comment Share on other sites More sharing options...
dejhost Posted January 14, 2019 Author Share Posted January 14, 2019 (edited) Do you know the (old) Star-Wars scene where a X-wing tries to defeat the death-star? Trying to get into the right position to fire the torpedo, the pilot repeats "I'm almost there...I'm almost there...". I just feel the same way ;-) Hopefully in the end more lucky than the X-wing pilot, though... A remaining problem I have: The two functions "PixelGetColor()" and "_GDIPlus_GraphicsDrawLine()" (used to save the image together with the line) seem to use a different Coordinate system than the rest of my program. I placed Opt("PixelCoordMode", 0) ;1=absolute, 0=relative, 2=client in the beginning of the subroutines, and tried all three options. None of the options results in correct output. The colors extracted show different values than expected, and the image saved shows the line that was drawn by the user at the wrong position. I believe it has something to do with the image position and the image dimension that I handle wrong(?) Here is the relevant code. It's not the complete code (which is too untidy to be published . Yes. Far more untidy than the code below...). expandcollapse popupGlobal $scale = _WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth Global $hUserDll = DllOpen("user32.dll") Global $hGraphics, $hGraphicBM, $pos, $iWidth, $iHeight, $hBM, $hIA Global $scale = 1;_WinAPI_EnumDisplaySettings('', $ENUM_CURRENT_SETTINGS)[0] / @DesktopWidth Global $aArray Opt("MustDeclareVars", 1) Opt("MouseCoordMode", 1) Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase Func _LoadImage() ;Load Image $sFile = FileOpenDialog("Select an image", "", "Images (*.bmp;*.png;*.jpg;*.gif;*.tif)", 1) $Path =_Pathsplit($sFile, $sDrive, $sDir, $sFileName, $sExtension) If @error Or Not FileExists($sFile) Then MsgBox($MB_SYSTEMMODAL, "File doesn't exist - 267", "Error opening file " & $Path) $hImage = _GDIPlus_ImageLoadFromFile($sFile) _WinAPI_DeleteObject($hImage) ;release GDI bitmap resource because not needed anymore $iWidth = _GDIPlus_ImageGetWidth($hImage) $iHeight = _GDIPlus_ImageGetHeight($hImage) ;== DRAW IMAGE, APPLYING GRAYSCALE IF NECESSARY ; GUI ;~ Global $iWidth = @DesktopWidth*3/4; ;~ Global $iHeight = @DesktopHeight*3/4;_GDIPlus_ImageGetHeight($hImage) * $iWidth / _GDIPlus_ImageGetWidth($hImage) Global $hGui2 = GUICreate("GDI+ v1.1 (" & @ScriptName & ")", $iWidth, $iHeight) GUISetState(@SW_SHOW) ;GREYSCALE $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI2) ;create a graphics object from a window handle $hBM = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics) $hGraphicBM = _GDIPlus_ImageGetGraphicsContext($hBM) $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object Global $tColorMatrix = _GDIPlus_ColorMatrixCreateGrayScale() ;create greyscale color matrix _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set greyscale color matrix WinClose(StringRegExpReplace($sFile, "^.*\\|\..*$", "")) If NOT _IsImageGrayScale($sFile) Then _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hImage, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetHeight($hImage), 0, 0, $iWidth, $iHeight,$hiA);, 0, 0, 1400, 900,$hIA ) ;draw the bitmap while applying the color adjustment Else _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hImage, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetHeight($hImage), 0, 0, $iWidth, $iHeight);, 0, 0, 1400, 900,$hIA ) ;draw the bitmap while applying the color adjustment EndIf Return $Path EndFunc ;==>LoadImage Func _SaveScreenshot() ;~ $iWidth = _GDIPlus_ImageGetWidth($hImage) ;~ $iHeight = _GDIPlus_ImageGetHeight($hImage) ;~ Local $hGUI = GUICreate("GDI+ Example (" & @ScriptName & ")", $iWidth, $iHeight, 10, 10, $WS_POPUP) ;create a test GUI Local $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI2) ;create a graphics object from a window handle Local $hBM = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphicGUI) ;create a Bitmap object based on a graphics object Local $hGraphicBM = _GDIPlus_ImageGetGraphicsContext($hBM) ;get the graphics context of the image / bitmap to draw on image / bitmap _GDIPlus_GraphicsClear($hGraphicBM, 0xFF000000) _GDIPlus_GraphicsDrawImageRectRect($hGraphicBM, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hIA) ;draw the bitmap while applying the color adjustment _GDIPlus_GraphicsDrawImageRect($hGraphicGUI, $hBM, 0, 0, $iWidth, $iHeight) Local $hPen = _GDIPlus_PenCreate(0xffff0000, 2) _GDIPlus_GraphicsDrawLine($hGraphicBM, $Pt1[0], $Pt1[1], $Pt2[0], $Pt2[1], $hPen) _GDIPlus_ImageSaveToFile($hBM, @ScriptDir & "\screenshot.jpg") ;~ ShellExecuteWait(@ScriptDir & "\screenshot.jpg")Sc EndFunc ;==>_SaveScreenshot Func _PixelsInLineToArray($Pt1X, $Pt1Y, $Pt2X, $Pt2Y) Local $m ProgressOn("Progress of Pixel processing", "", "0%", 100, 100) ; Display progressbar If Abs($Pt1X - $Pt2X) > Abs($Pt1Y - $Pt2Y) Then If $Pt1X > $Pt2X Then ; If Abs($Pt1X - $Pt2X) has the greater distance, make Point 2 "x" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient ; y - y1 = $m(x - x1) ; Equation for a straight line Global $aArray[($Pt2X - $Pt1X) + 1][3] For $x = $Pt1X To $Pt2X ; Note: $Pt2X has a greater value than $Pt1X. ;msgbox(0,"progress value",Floor($x / $Pt2X * 100) & "%",1) $aArray[$x - $Pt1X][0] = $x $aArray[$x - $Pt1X][1] = Round(($m * $x) - ($m * $Pt1X) + $Pt1Y, 0) ; y = $m(x - x1) + y1 (y value from equation for a straight line) $aArray[$x - $Pt1X][2] = Dec(StringRight(Hex(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale), 6), 2)) ;$aArray[$x - $Pt1X][2] = "0x" & Hex(PixelGetColor($aArray[$x - $Pt1X][0] * $scale, $aArray[$x - $Pt1X][1] * $scale), 6) ProgressSet(Floor($x / $Pt2X * 100),"%","soon finished calculating") ;increase Progressbar Next ProgressSet(100, "Done", "operation completed") Sleep(1000) ProgressOff() ;_ArrayDisplay($aArray) Return $aArray Else If $Pt1Y > $Pt2Y Then ; If Abs($Pt1Y - $Pt2Y) has the greater distance, make Point 2 "y" value have the larger value. Local $TempX, $TempY $TempX = $Pt1X $TempY = $Pt1Y $Pt1X = $Pt2X $Pt1Y = $Pt2Y $Pt2X = $TempX $Pt2Y = $TempY EndIf $m = ($Pt2Y - $Pt1Y) / ($Pt2X - $Pt1X) ; line's gradient Global $aArray[$Pt2Y - $Pt1Y + 1][3] For $y = $Pt1Y To $Pt2Y ; Note: $Pt2Y has a greater value than $Pt1Y ;msgbox(0,"progress value",Floor($y / $Pt2y * 100)& "%",1) $aArray[$y - $Pt1Y][0] = Round(($y / $m) - ($Pt1Y / $m) + $Pt1X, 0) ; x = (y - y1)/$m + x1 (x value from equation for a straight line) $aArray[$y - $Pt1Y][1] = $y $aArray[$y - $Pt1Y][2] = Dec(StringRight(Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6), 2)) ;$aArray[$y - $Pt1Y][2] = "0x" & Hex(PixelGetColor($aArray[$y - $Pt1Y][0] * $scale, $aArray[$y - $Pt1Y][1] * $scale), 6) ProgressSet(Floor($y / $Pt2Y *100),"%","soon finished calculating") Next ProgressSet(100, "Done", "operation completed") Sleep(1000) ProgressOff() ;_ArrayDisplay($aArray) Return $aArray EndIf EndFunc ;==>_PixelsInLineToArray I cannot get my head around this, because I do not yet understand the code in all details yet. Could somebody please help me out? Edited January 14, 2019 by dejhost Improved explanations Link to comment Share on other sites More sharing options...
Nine Posted January 14, 2019 Share Posted January 14, 2019 use _GDIPlus_BitmapGetPixel instead “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
dejhost Posted January 14, 2019 Author Share Posted January 14, 2019 2 hours ago, Nine said: use _GDIPlus_BitmapGetPixel instead I implemented the _GDIPlus_BitmapGetPixel into _PixelsInLineToArray. It appears that the _PixelsInLineToArray has now the same coordinate system as _SaveScreenshot. So definatevly an improvement. Now I need to get both consistent with what the user sees/draws. Link to comment Share on other sites More sharing options...
UEZ Posted January 14, 2019 Share Posted January 14, 2019 Here another way to do it. I draw a bezier curve and read out the colors of that curve. You can us a line instead. Advantage is that you do not need to calculate the path of any line to read out the pixel color accordingly. expandcollapse popup#include <ScreenCapture.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Array.au3> _GDIPlus_Startup() Global Const $hGUI = GUICreate("Test", 512, 512) GUISetState() Global Const $hHBitmap = _ScreenCapture_Capture("", 0, 0, 511, 511, False), _ $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap), _ $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage), _ $hImage2 = _GDIPlus_BitmapCreateFromScan0(512, 512), _ $hGfx2 = _GDIPlus_ImageGetGraphicsContext($hImage2), _ $hPen = _GDIPlus_PenCreate(0xFFFF0000, 8) ;change the pen size accordingly _GDIPlus_GraphicsSetSmoothingMode($hGfx2, 0) _GDIPlus_GraphicsDrawBezier($hGfx2, 50, 50, _ 100, 350, _ 325, 25, _ 450, 500, $hPen) Global Const $hCanvas = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, 511, 511) _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage2, 0, 0, 511, 511) Global $aColors = GetColors($hImage2, $hImage), $i Global $hImageResult = _GDIPlus_BitmapCreateFromScan0(512, 512, $GDIP_PXF24RGB) For $i = 0 To UBound($aColors) - 1 _GDIPlus_BitmapSetPixel($hImageResult, $aColors[$i][0], $aColors[$i][1], $aColors[$i][2]) ;slow - faster is to use _GDIPlus_BitmapLockBits() but I was to lazy :-) Next MsgBox(0, "Test", "Click OK to view result") _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImageResult, 0, 0, 511, 511) ;_ArrayDisplay($aColors) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_DeleteObject($hHBitmap) _GDIPlus_PenDispose($hPen) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hGfx2) _GDIPlus_ImageDispose($hImage2) _GDIPlus_ImageDispose($hImageResult) _GDIPlus_Shutdown() Func GetColors($hBitmap1, $hBitmap2, $iSearchColor = 0xFFFF0000) Local $aDim = _GDIPlus_ImageGetDimension($hBitmap1) Local $iW = $aDim[0], $iH = $aDim[1] ;this is the bitmap with the red bezier only Local $tBitmapData1 = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) ;locks a portion of a bitmap for reading and writing. More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx Local $iScan01 = DllStructGetData($tBitmapData1, "Scan0") ;get scan0 (pixel data) from locked bitmap Local $tPixel1 = DllStructCreate("int[" & $iW * $iH & "];", $iScan01) ;this is the bitmap where we read the colors Local $tBitmapData2 = _GDIPlus_BitmapLockBits($hBitmap2, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) ;locks a portion of a bitmap for reading and writing. More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx Local $iScan02 = DllStructGetData($tBitmapData2, "Scan0") ;get scan0 (pixel data) from locked bitmap Local $tPixel2 = DllStructCreate("int[" & $iW * $iH & "];", $iScan02) Local $iPixel, $iRowOffset, $p = 0 Local $aColors[$iW * $iH][3] ;x, y, color For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 ;get each pixel in each line and row $iPixel = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color from bezier If $iPixel = $iSearchColor Then $aColors[$p][0] = $iX $aColors[$p][1] = $iY $aColors[$p][2] = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;save pixel color from original image without bezier $p += 1 EndIf Next Next _GDIPlus_BitmapUnlockBits($hBitmap1, $tBitmapData1) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits _GDIPlus_BitmapUnlockBits($hBitmap2, $tBitmapData2) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits ReDim $aColors[$p - 1][3] Return $aColors EndFunc I don't know whether this is something your are looking for... Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
dejhost Posted January 16, 2019 Author Share Posted January 16, 2019 (edited) ;Call the function: _PixelsInLineToArray($Pt1[0]-$centerX, $Pt1[1]-$centerY, $Pt2[0]-$centerX, $Pt2[1]-$centerY) @UEZ: Thank you very much. But since I was "almost there..." anyhow, I decided to bring the first approach to its well-deserved glory, first. I have of course looked at your code, but I need more time to study the "GetColors" function more closely. Will do so soon and compare both approaches. Finally managed to fix the coordinate problem for both: saving the image and the pixel2array: Also Malkey's code saves a faulty line. Reason is that the image has a "left =10" and "top = 10" position when it get drawn. So the line that is saved is actually 10 pixels too far to the right, and 10 pixels too far down. Im my code, the image is drawn centered. That means that both functions (getColors and pixel2array) need to get corrected accordingly: $centerX = (@DesktopWidth/2)-($iWidth/2) $centerY = (@DesktopHeight/2)-($iHeight/2) Call of the function Pixel2Array: _PixelsInLineToArray($Pt1[0]-$centerX, $Pt1[1]-$centerY, $Pt2[0]-$centerX, $Pt2[1]-$centerY) $aArray[$x - $Pt1X][0] = $centerX + $x $aArray[$x - $Pt1X][1] = $centery + Round(($m * $x) - ($m * $Pt1X) + $Pt1Y, 0) ; y = $m(x - x1) + y1 (y value from equation for a straight line) $aArray[$x - $Pt1X][2] = Dec(StringRight(Hex(PixelGetColor(($aArray[$x - $Pt1X][0] * $scale), ($aArray[$x - $Pt1X][1] * $scale)), 6), 2)) In the function SaveImage: _GDIPlus_GraphicsDrawLine($hGraphicBM, $Pt1[0]-$centerX, $Pt1[1]-$centerY, $Pt2[0]-$centerX, $Pt2[1]-$centerY,$hPen) Edited January 16, 2019 by dejhost more context Link to comment Share on other sites More sharing options...
dejhost Posted February 2, 2019 Author Share Posted February 2, 2019 Last question - just out of curiosity: would it be possible to extract the pixelcolor from a closed image? My reason for asking: if the image has to be opened, then it might have to be resized in order to fit the screen. Only then the user can see the entire image, and indicate start- and endpoint of the line. But in this means that the extracted grayvalues do not refer to the original image - only to the resized one. Information gets lost. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now