Jump to content

Recommended Posts

Posted

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: 

  1. User opens an image of his choice. Image is shown on the screen.
  2. User draws a line into the image. This happens by marking the startpixel and the endpixel of the line
  3. The line is drawn, so the user can check visually if he is happy with the line.
  4.  The following pixel based properties belonging to the line are stored in Excel:
    1. X-Coordinate
    2. Y-Coordinate
    3. Color Value
  5. 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

 

 

Posted (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 by dejhost
grammar
Posted (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 by Nine
Posted

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 :-)

Posted (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 by dejhost
Posted
3 hours ago, dejhost said:

What do you mean by "std func"? Standard functions?

Yes here to start you up :

#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

 

Posted

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.  

#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

 

Posted

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.

 

 

 

 

Posted

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....

 

 

Posted (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 by Malkey
Added link to _GDIPlus_ColorMatrixCreateGrayScale
Posted

Thank you very much! Works like a charm :D

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?

 

 

 

 

Posted (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. 

#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 by Malkey
Updated import image to GUI.
Posted
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. 

#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... :o

I am currently stuck and working on another problem, but will soon implement your solution. 

Best regards,

dejhost

Posted (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...).

Global $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 by dejhost
Improved explanations
Posted
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. 

Posted

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.

#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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (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 by dejhost
more context
  • 3 weeks later...
Posted

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.

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...