Jump to content
Sign in to follow this  
dejhost

Extracting color-values of image along a user specified line

Recommended Posts

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

 

 

Share this post


Link to post
Share on other sites

Hello again,

documenting roughly what I've done so far:

  • Open image: 
_GDIPlus_ImageLoadFromFile 

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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.

 

 

 

 

Share this post


Link to post
Share on other sites

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

 

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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?

 

 

 

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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. 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
;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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By nacerbaaziz
      hello evrybody
      here is an example about how to split your texts using a delimiter with the ability to select how much of delimiters shows in each colum  with $i_number
      e.g
      you have a long text and you want to split it in an array
      that evry colum have a number (n) of lines
      i made a function that do that for you
      just call it with a three params
      $s_text
      your text
      $i_number
      the number that you want to put in each col
      $s_siparator
      the siparator
      default is "|"
      here is the function with example
      i hope that it will be useful for you
       
      ****
       
      #include <Array.au3> $s_txt = "some text1some text2|some text3|some text4|some text5|some text6" $array = splitText($s_txt, 2) _ArrayDisplay($array) Func splitText($s_text, $i_number, $s_siparator = "|") Local $a_TXT = StringSplit($s_text, $s_siparator) Local $a_Return[$a_TXT[0] + 1] If ($a_TXT[0] <= $i_number) Or ($i_number <= 0) Then ReDim $a_Return[2] $a_Return[0] = 1 $a_Return[1] = $s_text Return $a_Return EndIf Local $i_Processed = 1, $i_arrayProcessed = 1 Do For $i = $i_Processed To ($i_Processed + $i_number) - 1 If ($a_TXT[0] < $i) Then ExitLoop If Not ($a_Return[$i_arrayProcessed]) Then $a_Return[$i_arrayProcessed] = $a_TXT[$i] Else $a_Return[$i_arrayProcessed] &= $s_siparator & $a_TXT[$i] EndIf $i_Processed += 1 Next $i_arrayProcessed += 1 Until ($a_TXT[0] < $i_Processed) ReDim $a_Return[$i_arrayProcessed] $a_Return[0] = $i_arrayProcessed - 1 Return $a_Return EndFunc ;==>splitText
      accept my greetings
      thanks to
      @Dan_555
      for his notes
       
    • By coronatuss
      Hello everyone,
      Im developing an script to check the size of all .jpg stored in windows folder.
      The problem is that it doesn´t work properly with rotated images. 
      With _GDIPlus_ImageGetWidth() and _GDIPlus_ImageGetHeight()  I get the Width and Height of images as if they had not been rotated, and I need to know how they are rotated (orientation and grades).
      Any help is welcome! If more info is needed, please tell. 😁
    • By argumentum
      ..I'm coding the High Contrast theme editor and using the _ChooseColor() I wandered why it does not keep the the custom colors I've added.
      Found that adding a static declaration would do it. But why stop there. Why not keep going, So I put this together that is non code braking ( backwards compatible ), to replace the one in <Misc.au3>
       
      Hopefully will replace the default one in the next release 
      Better use the new code down this post.
    • By GOSM
      Hey,
      as part of a larger Programm I am trying to copy the values from one cell in an Excel file to another. The code I am using is the folowing.
       
      Local $oExcel = _Excel_Open() If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeCopy Example", "Error creating the Excel application object." & @CRLF & "@error = " & @error & ", @extended = " & @extended) _Excel_RangeCopyPaste($oExcel.ActiveSheet, "V4:W43", "X4", False, $xlPasteValues, Default, True) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeCopy Example 4", "Error copying rows." & @CRLF & "@error = " & @error & ", @extended = " & @extended) MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeCopy Example 4", "2 Rows successfully pasted from the clipboard to row 1.") As I understood it the option $xlPasteValues should do the trick  but it is still copying the inserted formulas. I attached a test code and excel file.
      Thanks for the help Simon
      Copy Values Test.zip
    • By nacerbaaziz
      hello autoit team
      please i've a question for you.
      am creating a audio player
      and in this audio player i want to show the current trac info
      such as the total time and the position ... etc
      i know i can show it as label
      but the screen reader for the blind read the text every change
      because it have a screen scan
      what i want is to show this informations but such image or icon
      i mean i need to create
      GUICtrlCreatepic or GUICtrlCreateicon ....
      or some thing as that
      and show this informations as image on it
      i think that i can do that with the 
      _GDIPlus functions
      but i couldn't find the currect way to do it
      i tried the _GDIPlus_GraphicsDrawString
      but i couldn't know how it work
      what i need is a small example that create a GUI
      and add a multy line text to it as graphic or image.
      so i need a simple way because it will changed every sec
      i hope any one can help me to do that
      global $GUI = GUICreate("text", 400, 400) global $label = GUICtrlCreateLabel(GetText(), 10, 10, 380, 380) GUISetState() do sleep(100) until GUIGetMSG() = -3 exit func GetText() return StringFormat("file name is test.mp3 \r\n total time is 00:30:00 \r\n position is 00:05:50") endFunc  
×
×
  • Create New...