Jump to content
c.haslam

GDI+: Clipping fails after rotation

Recommended Posts

c.haslam

UEZ has kindly provided me with code that rotates an image per a line: see here

Because I want to trim a photograph after rotation, I need to crop the photo. I wrote code which calls _GDIPlus_GraphicsSetClipRect() to do this, but it places spurious stuff in the corners: see 2.jpg attached.

I want only the trimmed photo to show.

The original jpeg is also attached.

The arguments to _GDIPlus_GraphicsSetClipRect() come from solving 2 simultaneous equations: if a and b are the width and height of the original photo, find x and y, the width and height of the rotated and cropped rectangle;

a = x cos(ang) + y sin(ang)

b = x sin(ang) + y cos(ang)

My solution is:

x = (b * sin(ang) - a*cos(ang)) / (sin(ang)^2 - (cos(ang)^2)

y = (b * cos(ang) - a * sin(ang)) / (cos(ang)^2 - sin(ang)^2)

To try to get a handle on the problem, I have temporarily added in several lines in Case $btn. In 2.jpg, you can see that the rectangle bounding the area to be retained is in the wrong place.

The code is:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8
Global Const $fPi = ACos(-1), $fPi2 = $fPi / 2, $fRad = 180 / $fPi

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0=10,$gX1=580,$gY0,$gY1,$gForm1,$glblPic,$iLW,$iLH,$iW,$iH
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap,$ghMatrix,$ghImageClone,$ghGfxClone

Global Const $kDegToRads = 3.14159/180
main()

Func main()
$gForm1 = GUICreate("Form1", 623, 601, 192, 114)
$iLW = 589
$iLH = 500
$glblPic = GUICtrlCreateLabel("", 8, 8, $iLW, $iLH)
Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
GUISetState(@SW_SHOW)

    Local $oldY0,$oldY1,$fAngle

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF999999,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('H:\b\pergola.jpg')
    Local $h = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = 400
    $gY1 = 400
    $iW = _GDIPlus_ImageGetWidth($ghImage)
    $iH = _GDIPlus_ImageGetHeight($ghImage)
    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    $ghMatrix = _GDIPlus_MatrixCreate()
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE
                    ExitLoop
                Case $btn
                    $ghImageClone=_GDIPlus_BitmapCreateFromScan0($iW, $iH)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImageClone)
                    _GDIPlus_MatrixTranslate($ghMatrix, $iW/2, $iH/2)
$gY1 = 300  ; temp
                    Local $ang = -Angle($gY1-$gY0, $gX1-$gX0)
                    _GDIPlus_MatrixRotate($ghMatrix, $ang)
;~                    _GDIPlus_MatrixRotate($ghMatrix, -Angle($gY1-$gY0, $gX1-$gX0))
                    _GDIPlus_MatrixTranslate($ghMatrix, -$iW/2, -$iH/2)
                    _GDIPlus_GraphicsSetTransform($ghGfxClone, $ghMatrix)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImage,0,0,$iW,$iH)
                    Local $angRads = $ang*$kDegToRads
                    Local $sinAng = Sin($angRads)
                    Local $cosAng = Cos($angRads)
                    Local $wid = ($iLH*$sinAng-$iLW*$cosAng)/($sinAng^2-$cosAng^2)
                    Local $left = ($iLW-$wid)/2
                    Local $ht = ($iLH*$cosAng-$iLW*$sinAng)/($cosAng^2-$sinAng^2)
                    Local $top = ($iLH-$ht)/2
 _GDIPlus_GraphicsDrawRect($ghGfxClone,$left,$top,$wid,$ht,$ghPen)  ; temp
                    _GDIPlus_GraphicsSetClipRect($ghGfxClone,$left,$top,$wid,$ht,0)
                   _GDIPlus_GraphicsDispose($ghGfxClone)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    _GDIPlus_GraphicsClear($ghImage)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImageClone,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    _GDIPlus_ImageDispose($ghImageClone)
                    $gy0 = 400
                    $gy1 = 400
                    Paint()
                    _GDIPlus_ImageSaveToFile($ghImage,'H:\b\2.jpg') ; added - is rotated, with same size as original file
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($ghMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $kYmax=$iLH-1,$kDelta=2
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iLW, $iLH)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch True
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

I also don't understand how the rotated picture gets displayed. There are graphics objects, graphics contexts and PDI+ bitmaps. How are they related?

Help would be much appreciated.

pergola.jpg

2.jpg

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
SlackerAl

There appears to be a useful discussion of this problem and a js solution here calculate-largest-rectangle-in-a-rotated-rectangle perhaps it is worth checking out?


Problem solving step 1: Write a simple, self-contained, running, replicator of your problem.

Share this post


Link to post
Share on other sites
c.haslam

Thank you for the link. I have already studied that one carefully. It didn't help, perhaps because I don't know JS.

I think my basic problem may be not understanding how GD+ works with graphics objects, graphics contexts and PDI+ bitmaps. MSDN hasn't helped either.

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ

You mean something like this here?

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8
Global Const $fPi = ACos(-1), $fPi2 = $fPi / 2, $fRad = 180 / $fPi

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0,$gX1,$gY0,$gY1,$gForm1,$glblPic,$iW,$iH
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap,$ghMatrix,$ghImageClone,$ghGfxClone,$ghImageCropped
main()

Func main()
    Local $oldY0,$oldY1,$fAngle

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF000000,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('pergola.jpg')
    $iW = _GDIPlus_ImageGetWidth($ghImage)
    $iH = _GDIPlus_ImageGetHeight($ghImage)
    $gX0=10
    $gX1=$iW-10

    $gForm1 = GUICreate("Form1", $iW + 16, $iH + 50)
    $glblPic = GUICtrlCreateLabel("", 8, 8, $iW, $iH)
    Local $btn = GUICtrlCreateButton("Rotate", $iW - 100, $iH + 20, 65, 25)
    GUISetState(@SW_SHOW)

    Local $h = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = $iH / 2 + 100
    $gY1 = $iH / 2 - 90

    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    $ghMatrix = _GDIPlus_MatrixCreate()
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE
                    ExitLoop
                Case $btn
                    $ghImageClone=_GDIPlus_BitmapCreateFromScan0($iW, $iH)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImageClone)
                    _GDIPlus_MatrixTranslate($ghMatrix, $iW/2, $iH/2)
                    _GDIPlus_MatrixRotate($ghMatrix, -Angle($gY1-$gY0, $gX1-$gX0))
                    _GDIPlus_MatrixTranslate($ghMatrix, -$iW/2, -$iH/2)
                    _GDIPlus_GraphicsSetTransform($ghGfxClone, $ghMatrix)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImage,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    _GDIPlus_GraphicsClear($ghGfxClone)
                    _GDIPlus_GraphicsClear($ghImage)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImageClone,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    $gY0 = $iH / 2
                    $gY1 = $iH / 2
                    Paint()
                    $ghImageCropped=_GDIPlus_BitmapCloneArea($ghImageClone,120,66,745,403)
                    _GDIPlus_ImageDispose($ghImageClone)
                    _GDIPlus_ImageSaveToFile($ghImageCropped, @ScriptDir & "\pergola_RnC.jpg")
                    _GDIPlus_ImageDispose($ghImageCropped)
                    ShellExecute(@ScriptDir & "\pergola_RnC.jpg")
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($ghMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $kYmax=$iH-1,$kDelta=2
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iW, $iH)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch $x
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

I need to think about an automatic crop solution...

  • Like 1

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

UEZ, thanks.

Unfortunately, pergola.jpg shows full screen, because your code makes $lblPiC the size of the jpeg, which is 2557x1374. The Rotate button is way of-screen.

I look forward to the result of your endeavors, I won't have time to visit the forum for a few days.

Edited by c.haslam
fixed typo

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
c.haslam

UEZ,

I have purposely rotated by much more than what happens in real life: in this sample, the camera was held about 10 degrees off level; in my experience, 3 degrees is as much off as I have seen. It does, however, show that I am  looking at the problem wrongly geometrically and algebraically!

I need to do some more head-scratching to figure out what is going on.

My original idea was to improve on the way Irfanview de-skews a photo: it has the user enter the angle as a number; I would like to get a better result by the user rotating a line. Here is what Irfanview does with 10 degree rotation.

Irfanview's result is too small to be useful -- another reason why I have undertaken this project!pergola IV change size.jpg

 

pergola IV change size.jpgpergola IV keep size.jpg

Neither is what I want to do. I have been trying to do the "change .. size' option, but I now realize that I need to do IV's "keep ... size" option, then crop to get rid of the 4 corner triangles, by cropping.

Hope this makes sense.

(Onlt the first 2 images in this post apply. I can't delete the third, erroneous, one.)

pergola IV keep size.jpg

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ

I would do it this way:

Create a large preview window of the image with a slider from -360 to 360 degrees which the user can use to rotate the image

Have a horizontal movable line over the image to have an orientation

Use mouse wheel to zoom the image

A checkbox with the open to keep original image as background


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

I don't see a need to rotate the image more than about 10 degrees. For the Photos I take, there is some feature that should be horizontal: in the case of the image I am testing with, it is the edge of the pool. More typically, the feature is near the bottom of the picture.

I have been thinking about the image Irfanview produces when Keep the original image/canvas size is checked.

I would be happy if a way can be found to replace the erroneous corner triangles with black (or the background colour AutoIt uses in a dialog box).

Then the script would then show a crop rectangle on the image.

This rectangle would initially have as its (left, bottom) the mid point of the hypotenuse of the lower left triangle, and as its (top, right) the mid point of the hypotenuse of the upper right triangle. (This is based on the image I used in Irfanview, i.e. landscape with clockwise rotation).

The script would allow the user to change the size of the rectangle, by dragging the edges, constrained by the corner triangles.

The user would then click on a Crop button to define the cropped image.

Does this make sense?


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ

I don't get it with the corner issue you have. When you rotate the image then you will get automatically the black triangle corners.

Or do you mean after rotation to zoom in the image that you cannot see any black triangle corner?


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

If you look at the second image in Post #1, at the top right corner, you can see lattice on an angle. and part of the top of the fence: in a triangle. This triangle should be solid black. I also see triangles in the other 3 corners. They too should be black.

 


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ

The code in post#4 is exactly producing the image with the black corners! What you have to do is to remove the cropping (zoom in to avoid the black corners).


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

It occurs to me that whether the corners are black or bits of the un-rotated image are irrelevant, because they will be cropped out.

So the question is: how to crop the triangles?

SlackerAl, in Post #2, gives a link to a thread on stackoverflow. The  post in that thread posted Feb 8 '14 at 21:17 contains code that apparently crops, yielding maximum area:

CropRotatedDimensionsForMaxArea[{w_, h_}, alpha_] := 
With[
  {phi = Abs@Mod[alpha, Pi, -Pi/2]},
  Which[
   w == h, {w,h} Csc[phi + Pi/4]/Sqrt[2],
   w > h, 
     If[ Cos[2 phi]^2 < 1 - (h/w)^2, 
       h/2 {Csc[phi], Sec[phi]}, 
       Sec[2 phi] {w Cos[phi] - h Sin[phi], h Cos[phi] - w Sin[phi]}],
   w < h, 
     If[ Cos[2 phi]^2 < 1 - (w/h)^2, 
       w/2 {Sec[phi], Csc[phi]}, 
       Sec[2 phi] {w Cos[phi] - h Sin[phi], h Cos[phi] - w Sin[phi]}]
  ]
]

I don't understand the code. Perhaps someone would help me by translating this into AutoIt code. Or perhaps other code in that thread would work.

 


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
c.haslam

In Post 4,  I see _GDIPlus_GraphicsClear($ghImage) but the Help says that the parameter should be a graphics object. $ghImage is an image object.

Is this why the corner triangles are not black?

I have made some progress on auto-cropping, but have not tested it yet.

 
Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ
3 hours ago, c.haslam said:

In Post 4,  I see _GDIPlus_GraphicsClear($ghImage) but the Help says that the parameter should be a graphics object. $ghImage is an image object.

Is this why the corner triangles are not black?

I have made some progress on auto-cropping, but have not tested it yet.

 

You are right, this line is obsolete and can be deleted. The line above (_GDIPlus_GraphicsClear($ghGfxClone)) clears the canvas so that the cornes get black. If you comment the line out you will see the difference.


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
SlackerAl
On 10/29/2017 at 6:48 PM, c.haslam said:

Post #2: I don't understand the code. Perhaps someone would help me by translating this into AutoIt code. Or perhaps other code in that thread would work.

 

I'm sorry, but I do not have time to look at this for some time, perhaps someone else can help? If not I will try to get to it, but it may be a few weeks.


Problem solving step 1: Write a simple, self-contained, running, replicator of your problem.

Share this post


Link to post
Share on other sites
c.haslam

SlackerAl,

I am not sure, but I do think, that translating the code in Post #2 may no longer be needed.

My current approach is:

  • Determine the formulae for the corners of the rotated image
  • Determine the equations for each of the sides of the rotated image
  • Determine the points where the sides of the rotated image intercept the sides of the frame (un-rotated image)
  • Crop the rotated image to be within horizontal and vertical lines drawn through these points, with the lines chosen to maximize the cropped image.

This is the outline of the approach. The devil is in the details! I have this working on paper (with manually drawn diagram/graph). I am still battling which intercept points between sides of the frame and sides of the rotated image are the correct pairs. I think I know, but getting the signs in the equations right is taking time. I am making stupid errors!


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
c.haslam

My code, based on UEZ's code, is below. It works!

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0=10,$gX1=580,$gY0,$gY1,$gForm1,$glblPic,$gCtlWid,$gCtlHt,$imgWid,$imgHt
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap

main()

Func main()
$gCtlWid = 893
$gCtlHt = 480
$gForm1 = GUICreate("Form1", $gCtlWid+50, 601, 192, 114)
$glblPic = GUICtrlCreateLabel("", 8, 8, $gCtlWid, $gCtlHt)
Local $btnRotate = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
Local $btnExit = GUICtrlCreateButton("Exit",600,560)
GUISetState(@SW_SHOW)

    Local $oldY0,$oldY1

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF999999,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('H:\b\pergola.jpg')
    Local $hnd = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($hnd)
    $gY0 = 400
    $gY1 = 400
    $imgWid = _GDIPlus_ImageGetWidth($ghImage)
    $imgHt = _GDIPlus_ImageGetHeight($ghImage)
    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($imgWid, $imgHt)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btnExit
                    ExitLoop
                Case $btnRotate
                    Local $hImageClone=_GDIPlus_BitmapCreateFromScan0($imgWid, $imgHt)
                    Local $hGfxClone=_GDIPlus_ImageGetGraphicsContext($hImageClone)
                    ; rotate about centre
                    Local $gMatrix = _GDIPlus_MatrixCreate()
                    _GDIPlus_MatrixTranslate($gMatrix, $imgWid/2, $imgHt/2)
                    Local $deg = Angle($gY1-$gY0, $gX1-$gX0)
                    _GDIPlus_MatrixRotate($gMatrix, -$deg)
                    _GDIPlus_MatrixTranslate($gMatrix, -$imgWid/2, -$imgHt/2)
                    _GDIPlus_GraphicsSetTransform($hGfxClone, $gMatrix)

                    _GDIPlus_GraphicsDrawImageRect($hGfxClone,$ghImage,0,0,$imgWid,$imgHt)
                    _GDIPlus_GraphicsDispose($hGfxClone)

                    $hGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    _GDIPlus_GraphicsClear($hGfxClone)
                    ; See deskew notes document
                    Local $ang = Abs($deg*3.14159/180)
                    Local $nsrcX = ($imgHt/2 - $imgWid/2*sin($ang) - $imgHt/2*cos($ang))*tan($ang) _
                        - $imgWid/2*cos($ang) + $imgHt/2*sin($ang) + $imgWid/2
                    Local $nsrcY = ($imgWid/2 + $imgWid/2*Cos($ang) - $imgHt/2*Sin($ang))*Tan($ang) _
                        - $imgWid/2*Sin($ang) - $imgHt/2*Cos($ang) + $imgHt/2
                    Local $nSrcWidth = $imgWid - 2*$nSrcX
                    Local $nSrcHeight = $imgHt - 2*$nSrcY
                    ; crop
                    _GDIPlus_GraphicsDrawImageRectRect($hGfxClone,$hImageClone, _
                        $nSrcX,$nSrcY,$nSrcWidth,$nSrcHeight,0,0,$nSrcWidth,$nSrcHeight)

                    GUICtrlDelete($glblPic)
                    _GDIPlus_GraphicsDispose($gGraphicPic)
                    $glblPic = GUICtrlCreateLabel("", 8, 8, $gCtlWid*$nSrcWidth/$imgWid,$gCtlHt*$nSrcHeight/$imgHt)
                    Local $hnd = GUICtrlGetHandle($glblPic)
                    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($hnd)
                    _GDIPlus_ImageDispose($hImageClone)
                    $gy0 = 400
                    $gy1 = 400
                    Paint()
                    Local $hImageClone2 = _GDIPlus_BitmapCloneArea($ghImage,0,0,$nSrcWidth,$nSrcHeight)
                    _GDIPlus_ImageSaveToFile($hImageClone2,'H:\b\1.jpg')
                    _GDIPlus_ImageDispose($hImageClone2)
           EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($gMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $MK_SHIFT=0x4,$MK_CONTROL= 0x8
    Local Const $kYmax=$gCtlHt-1,$kDelta=2

    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $gCtlWid, $gCtlHt)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $imgWid, $imgHt)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch True
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

I am attaching my derivation of the formulas used for cropping. Thank you to all who have posted GDI+ stuff on the forum.

I still do not fully understand how graphics objects / graphic contexts work, so helpful hints would be appreciated!

Suggestions for improvements are most welcome.

 

Deskew notes.pdf

Edited by c.haslam
Update Deskew notes.pdf

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
UEZ

@c.haslam now I got your point with the edges - probably my fault because of lack of language knowledge.

But I assumed already in post#11 what you want:

On 10/26/2017 at 2:51 PM, UEZ said:

What you have to do is to remove the cropping (zoom in to avoid the black corners).

Anyhow, good work: :thumbsup:


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
UEZ
12 hours ago, c.haslam said:

Suggestions for improvements are most welcome.

I wouldn't say it is an improvement rather another (brute-force) way to get the best crop area (the aspect ratio of the original image is kept!) for the image after rotation whereas the corners are black (0x00000000).

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

Global Const $MK_SHIFT = 0x4
Global Const $MK_CONTROL = 0x8
Global Const $fPi = ACos(-1), $fPi2 = $fPi / 2, $fRad = 180 / $fPi

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0,$gX1,$gY0,$gY1,$gForm1,$glblPic,$iW,$iH
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap,$ghMatrix,$ghImageClone,$ghGfxClone,$ghImageCropped
main()

Func main()
    Local $oldY0,$oldY1,$fAngle,$aPos

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFFFF0000,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('pergola.jpg')
    $iW = _GDIPlus_ImageGetWidth($ghImage)
    $iH = _GDIPlus_ImageGetHeight($ghImage)
    $gX0=10
    $gX1=$iW-10

    $gForm1 = GUICreate("Form1", $iW + 16, $iH + 50)
    $glblPic = GUICtrlCreateLabel("", 8, 8, $iW, $iH)
    Local $btn = GUICtrlCreateButton("Rotate", $iW - 100, $iH + 20, 65, 25)
    GUISetState(@SW_SHOW)

    Local $h = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h)
    $gY0 = $iH / 2 + 100
    $gY1 = $iH / 2 - 90

    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    $ghMatrix = _GDIPlus_MatrixCreate()
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE
                    ExitLoop
                Case $btn
                    $ghImageClone=_GDIPlus_BitmapCreateFromScan0($iW, $iH)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImageClone)
                    _GDIPlus_MatrixTranslate($ghMatrix, $iW/2, $iH/2)
                    _GDIPlus_MatrixRotate($ghMatrix, -Angle($gY1-$gY0, $gX1-$gX0))
                    _GDIPlus_MatrixTranslate($ghMatrix, -$iW/2, -$iH/2)
                    _GDIPlus_GraphicsSetTransform($ghGfxClone, $ghMatrix)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImage,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    _GDIPlus_GraphicsClear($ghGfxClone)
                    _GDIPlus_GraphicsClear($ghImage)
                    _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImageClone,0,0,$iW,$iH)
                    _GDIPlus_GraphicsDispose($ghGfxClone)
                    $gY0 = $iH / 2
                    $gY1 = $iH / 2
                    Paint()
                    $aPos = GetBestCropArea($ghImageClone)
                    $ghImageCropped=_GDIPlus_BitmapCloneArea($ghImageClone,$aPos[0],$aPos[1],$aPos[2],$aPos[3])
                    _GDIPlus_ImageDispose($ghImageClone)
                    _GDIPlus_ImageSaveToFile($ghImageCropped, @ScriptDir & "\pergola_RnC.jpg")
                    _GDIPlus_ImageDispose($ghImageCropped)
                    ShellExecute(@ScriptDir & "\pergola_RnC.jpg")
            EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($ghMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $kYmax=$iH-1,$kDelta=2
    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iW, $iH)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch $x
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

Func GetBestCropArea($hImage) ;not speed optimized!
    Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage), $fRatio = $iW / $iH, $fCenterX = $iW / 2, $fCenterY = $iH / 2
    Local $fPosX, $fPosY, $fW, $fH, $iPixel1, $iPixel2
    For $x = $iW To 0 Step -1
        $fPosX = $fCenterX - $x / 2
        $fPosY = $fCenterY - ($x / 2) / $fRatio
        $fW = $x
        $fH = $x / $fRatio
        $iPixel1 = _GDIPlus_BitmapGetPixel($hImage, $fPosX, $fPosY)
        $iPixel2 = _GDIPlus_BitmapGetPixel($hImage, $fPosX + $fW, $fPosY)
        If $iPixel1 And $iPixel2 Then ExitLoop
    Next
    If Not $x Then Return SetError(1, 0, 0)
    Local $aPos[4] = [$fPosX, $fPosY, $fW, $fH]
    Return $aPos
EndFunc

 

Edited by UEZ

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

Your approach is surprisingly performant, given that it has a for loop that is executed many times. It appears to me that it will fail if, in traversing the image, it simultaneously encounters two black pixels before reaching a corner triangle. I realize that this is unlikely.

In order to run your code, I ran it on a 1024x768 version of pergola.jpg; otherwise on my 1920x1024 monitor, the Rotate button was off screen.

I have revisited my code, improving the time it takes to do the cropping. While it was recreating the control, it now adds borders to the displayed version, the borders being the colour of the client-area background. What was taking about 130 msec snow  takes about 36. Also, there is now no flicker. The script, with the new code, is below:

#include <ButtonConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt('MustDeclareVars',1)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_PAINT,'WM_PAINT')

Global $gX0=10,$gX1=580,$gY0,$gY1,$gForm1,$glblPic,$gCtlWid,$gCtlHt,$imgWid,$imgHt
Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap

main()

Func main()
$gCtlWid = 893
$gCtlHt = 480
$gForm1 = GUICreate("Form1", $gCtlWid+50, 601, 192, 114)
$glblPic = GUICtrlCreateLabel("", 8, 8, $gCtlWid, $gCtlHt)
Local $btnRotate = GUICtrlCreateButton("Rotate", 472, 560, 65, 25)
Local $btnExit = GUICtrlCreateButton("  Exit  ",600,560)
GUISetState(@SW_SHOW)

    Local $oldY0,$oldY1

    _GDIPlus_Startup()

    $ghPen = _GDIPlus_PenCreate(0xFF999999,2)
    $ghImage = _GDIPlus_ImageLoadFromFile('H:\b\pergola.jpg')
    Local $hnd = GUICtrlGetHandle($glblPic)
    $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($hnd)
    $gY0 = 400
    $gY1 = 400
    $imgWid = _GDIPlus_ImageGetWidth($ghImage)
    $imgHt = _GDIPlus_ImageGetHeight($ghImage)
    $ghBitmap = _GDIPlus_BitmapCreateFromScan0($imgWid, $imgHt)
    $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap)
    ; Loop until the user exits.
    While True
        If $gY0<>$oldY0 Or $gY1<>$oldY1 Then
            Paint()
            $oldY0 = $gY0
            $oldY1 = $gY1
        Else
            Switch GUIGetMsg()
                Case $GUI_EVENT_CLOSE,$btnExit
                    ExitLoop
                Case $btnRotate
                    Local $hImageClone=_GDIPlus_BitmapCreateFromScan0($imgWid, $imgHt)
                    Local $hGfxClone=_GDIPlus_ImageGetGraphicsContext($hImageClone)
                    ; rotate about centre
                    Local $gMatrix = _GDIPlus_MatrixCreate()
                    _GDIPlus_MatrixTranslate($gMatrix, $imgWid/2, $imgHt/2)
                    Local $deg = Angle($gY1-$gY0, $gX1-$gX0)
                    _GDIPlus_MatrixRotate($gMatrix, -$deg)
                    _GDIPlus_MatrixTranslate($gMatrix, -$imgWid/2, -$imgHt/2)
                    _GDIPlus_GraphicsSetTransform($hGfxClone, $gMatrix)

                    _GDIPlus_GraphicsDrawImageRect($hGfxClone,$ghImage,0,0,$imgWid,$imgHt)
                    _GDIPlus_GraphicsDispose($hGfxClone)
                    $hGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage)
                    ; See deskew notes document
                    Local $ang = Abs($deg*3.14159/180)
                    Local $cos = cos($ang), $sin = sin($ang), $tan = tan($ang)
                    Local $w2cos = $imgWid/2*$cos, $w2sin =  $imgWid/2*$sin
                    Local $h2cos = $imgHt/2*$cos, $h2sin = $imgHt/2*$sin
                    Local $nsrcX = ($imgHt/2 - $w2sin - $h2cos)*$tan - $w2cos + $h2sin + $imgWid/2
                    Local $nsrcY = ($imgWid/2 + $w2cos - $h2sin)*$tan - $w2sin - $h2cos + $imgHt/2

                    Local $nSrcWidth = $imgWid - 2*$nSrcX
                    Local $nSrcHeight = $imgHt - 2*$nSrcY
                    ; crop to screen, centering within control
                    _GDIPlus_GraphicsClear($hGfxClone,0xFFD4D0C8)   ; client area background colour
                    Local $nDstX = ($imgWid-$nSrcWidth)/2
                    Local $nDstY = ($imgHt-$nSrcHeight)/2
                    ; draw a portion of image object $hImageClone on the image that $hGfxClone points to
                    _GDIPlus_GraphicsDrawImageRectRect($hGfxClone,$hImageClone, _
                        $nSrcX,$nSrcY,$nSrcWidth,$nSrcHeight,$nDstX,$nDstY,$nSrcWidth,$nSrcHeight)
                    _GDIPlus_ImageDispose($hImageClone)
                    $gy0 = 400
                    $gy1 = 400
                    Paint()
                    Local $hImageClone2 = _GDIPlus_BitmapCloneArea($ghImage,$nsrcX,$nsrcY,$nSrcWidth,$nSrcHeight)
                    _GDIPlus_ImageSaveToFile($hImageClone2,'H:\b\1.jpg')
                    _GDIPlus_ImageDispose($hImageClone2)
                    ShellExecute('H:\b\1.jpg')
           EndSwitch
        EndIf
    WEnd

    ; Clean up resources
    _GDIPlus_MatrixDispose($gMatrix)
    _GDIPlus_ImageDispose($ghCanvas)
    _GDIPlus_ImageDispose($ghImage)
    _GDIPlus_ImageDispose($ghBitmap)
    _GDIPlus_PenDispose($ghPen)
    _GDIPlus_GraphicsDispose($gGraphicPic)
    _GDIPlus_Shutdown()
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Local Const $MK_SHIFT=0x4,$MK_CONTROL= 0x8
    Local Const $kYmax=$gCtlHt-1,$kDelta=2

    Local $vec = GUIGetCursorInfo($gForm1)
    If $vec[4] = $vec[4]=$glblPic Then
        Local $iDelta = BitShift($wParam, 16)   ; positive = up
        Local $iKeys = _WinAPI_LoWord($wParam)
        If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                ; do nothing
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
            EndIf
        Else
            If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0  And $gY1<$kYmax Then $gY1 += $kDelta
            Else
                If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta
                If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta
                If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta
                If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta
            EndIf
        EndIf
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Func Paint()
    _GDIPlus_GraphicsClear($ghCanvas,0)
    _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $gCtlWid, $gCtlHt)
    _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen)
    _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $imgWid, $imgHt)
EndFunc

Func WM_PAINT()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW)
    Paint()
    _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE)
EndFunc

Func Angle($y, $x) ;return value is in degree
    Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi
    Switch True
        Case ($x > 0)
            Return ATan($y / $x) * $fRad
        Case ($x < 0 And $y >= 0)
            Return ATan($y / $x + $fPi) * $fRad
        Case ($x < 0 And $y < 0)
            Return ATan($y / $x - $fPi) * $fRad
        Case ($x = 0 And $y > 0)
            Return $fPi2 * $fRad
        Case ($x = 0 And $y < 0)
            Return -$fPi2 * $fRad
        Case ($x = 0 And $y = 0)
            Return 0
    EndSwitch
EndFunc

 


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

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

  • Similar Content

    • JoeWagner
      By JoeWagner
      I'm building a tool to remotely monitor CPU usage on my server.
      I have a working tool but I have a few issues I'd like some help with.
      1. The app uses more system memory on a continual growth rate...  It eventually starts displaying strange artifacts and the background flashes between black and and white behind the GDI+ elements.  I determined this couldn't be left to run for any amount of time (greater than 15-20 minutes) - Very frustrating.
      I suspect it's because it keeps drawing new GDI+ elements to replace the previous cycle ... the $bar1 = "" is enough to remove the image and allow the new image to be drawn there, but I don't have a handle for the original GDI+ element to throw it away... Not sure where they go...
      I also suspect there could be a better way to do what I'm doing here, but from a problem solving perspective - this is what I came up with - I will accept suggestions for how better to accomplish the same / better or acceptable results  
      I will not however accept corrections on grammar, punctuation or commenting - I didn't comment this as I was going, I use the variables that make sense to me (or as they were when I lifted them from the scraps I found on the internet) and you can never be too careful with punctuation.
      2. I have a WMI query that is used to remotely pull the CPU data from the server - if I supply the wrong credentials the app crashes... I tried to make it show an error and go back to allow me to try again ... doesn't work. Any help with catching that error and preventing the crash would be super helpful. (works great if the credentials are correct; domain or local)
       
      The whole thing below... 
      #include <Date.au3> #include <WindowsConstants.au3> #include <GuiConstantsEX.au3> #include <EditConstants.au3> #include <ButtonConstants.au3> #include <GDIPlus.au3> Global $__g_hGDIPDll Global $graph[21] Global $timer, $timeout = 500 Global $hFlag = 0 $timer = TimerInit() $main = GUICreate("CPU Graph", 125, 220, Default, Default, Default, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) $bar1 = GUICtrlCreatePic("", 10, 10, 5, 100) $bar2 = GUICtrlCreatePic("", 15, 10, 5, 100) $bar3 = GUICtrlCreatePic("", 20, 10, 5, 100) $bar4 = GUICtrlCreatePic("", 25, 10, 5, 100) $bar5 = GUICtrlCreatePic("", 30, 10, 5, 100) $bar6 = GUICtrlCreatePic("", 35, 10, 5, 100) $bar7 = GUICtrlCreatePic("", 40, 10, 5, 100) $bar8 = GUICtrlCreatePic("", 45, 10, 5, 100) $bar9 = GUICtrlCreatePic("", 50, 10, 5, 100) $bar10 = GUICtrlCreatePic("", 55, 10, 5, 100) $bar11 = GUICtrlCreatePic("", 60, 10, 5, 100) $bar12 = GUICtrlCreatePic("", 65, 10, 5, 100) $bar13 = GUICtrlCreatePic("", 70, 10, 5, 100) $bar14 = GUICtrlCreatePic("", 75, 10, 5, 100) $bar15 = GUICtrlCreatePic("", 80, 10, 5, 100) $bar16 = GUICtrlCreatePic("", 85, 10, 5, 100) $bar17 = GUICtrlCreatePic("", 90, 10, 5, 100) $bar18 = GUICtrlCreatePic("", 95, 10, 5, 100) $bar19 = GUICtrlCreatePic("", 100, 10, 5, 100) $bar20 = GUICtrlCreatePic("", 105, 10, 5, 100) $host = GUICtrlCreateInput("Host", 10, 115, 100, 20, $ES_AUTOHSCROLL) $user = GUICtrlCreateInput("User", 10, 140, 100, 20, $ES_AUTOHSCROLL) GUICtrlSetFont(-1, 8, 400) $pass = GUICtrlCreateInput("Pass", 10, 165, 100, 20, BitOR($ES_PASSWORD,$ES_AUTOHSCROLL)) GUICtrlSetFont(-1, 8, 400) $start = GUICtrlCreateButton("Start", 10, 190, 100, 20, $BS_DEFPUSHBUTTON) GUISetState() While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop If $msg = $start Then ConnectWMI() If $hFlag = 1 Then If TimerDiff($timer) > $timeout Then UpdateGraph() EndIf WEnd Func ConnectWMI() Global $hostname = GUICtrlRead($host) If Ping($hostname, 2000) = 0 Then Msgbox(0, "Error", "Unable to reach specified host") Return 0 EndIf Local $usr = GUICtrlRead($user) Local $pwd = GUICtrlRead($pass) Global $objSWbemLocator = ObjCreate("WbemScripting.SWbemLocator") Global $objWMIService = $objSWbemLocator.ConnectServer($hostname, "root\cimv2", $usr, $pwd) If @error Then Msgbox(0, "Error", "Unable to connect to the Host with the supplied credentials") Return 0 EndIf $hFlag = 1 UpdateGraph() EndFunc Func UpdateGraph() $usage = _Processor_Usage() For $i = 1 to 19 $graph[$i] = $graph[$i+1] Next $graph[20] = $usage GUICtrlSetImage($bar1, "") CreateBar($bar1, $graph[1]) GUICtrlSetImage($bar2, "") CreateBar($bar2, $graph[2]) GUICtrlSetImage($bar3, "") CreateBar($bar3, $graph[3]) GUICtrlSetImage($bar4, "") CreateBar($bar4, $graph[4]) GUICtrlSetImage($bar5, "") CreateBar($bar5, $graph[5]) GUICtrlSetImage($bar6, "") CreateBar($bar6, $graph[6]) GUICtrlSetImage($bar7, "") CreateBar($bar7, $graph[7]) GUICtrlSetImage($bar8, "") CreateBar($bar8, $graph[8]) GUICtrlSetImage($bar9, "") CreateBar($bar9, $graph[9]) GUICtrlSetImage($bar10, "") CreateBar($bar10, $graph[10]) GUICtrlSetImage($bar11, "") CreateBar($bar11, $graph[11]) GUICtrlSetImage($bar12, "") CreateBar($bar12, $graph[12]) GUICtrlSetImage($bar13, "") CreateBar($bar13, $graph[13]) GUICtrlSetImage($bar14, "") CreateBar($bar14, $graph[14]) GUICtrlSetImage($bar15, "") CreateBar($bar15, $graph[15]) GUICtrlSetImage($bar16, "") CreateBar($bar16, $graph[16]) GUICtrlSetImage($bar17, "") CreateBar($bar17, $graph[17]) GUICtrlSetImage($bar18, "") CreateBar($bar18, $graph[18]) GUICtrlSetImage($bar19, "") CreateBar($bar19, $graph[19]) GUICtrlSetImage($bar20, "") CreateBar($bar20, $graph[20]) $timer = TimerInit() EndFunc Func _Processor_Usage() Dim $Col_Items = $objWMIService.ExecQuery('SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor', 'WQL') Local $Obj_Item For $Obj_Item In $Col_Items Return $Obj_Item.PercentProcessorTime Next EndFunc Func CreateBar($target, $value) Local $width=5, $height=2 _GDIPlus_Startup() $hImage = DLL_BitmapCreate($width, $height*50) $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage) _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2) ;100 If $value > 98 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF00F2F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $width, $height, $hBrush) EndIf ;98 If $value > 96 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF0182C") _GDIPlus_GraphicsFillRect($hGraphic, 0, 2, $width, $height, $hBrush) EndIf ;96 If $value > 94 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF0212A") _GDIPlus_GraphicsFillRect($hGraphic, 0, 4, $width, $height, $hBrush) EndIf ;94 If $value > 92 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF02B28") _GDIPlus_GraphicsFillRect($hGraphic, 0, 6, $width, $height, $hBrush) EndIf ;92 If $value > 90 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF03426") _GDIPlus_GraphicsFillRect($hGraphic, 0, 8, $width, $height, $hBrush) EndIf ;90 If $value > 88 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF03E24") _GDIPlus_GraphicsFillRect($hGraphic, 0, 10, $width, $height, $hBrush) EndIf ;88 If $value > 86 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF04722") _GDIPlus_GraphicsFillRect($hGraphic, 0, 12, $width, $height, $hBrush) EndIf ;86 If $value > 84 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF05120") _GDIPlus_GraphicsFillRect($hGraphic, 0, 14, $width, $height, $hBrush) EndIf ;84 If $value > 82 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF05A1D") _GDIPlus_GraphicsFillRect($hGraphic, 0, 16, $width, $height, $hBrush) EndIf ;82 If $value > 80 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF0641B") _GDIPlus_GraphicsFillRect($hGraphic, 0, 18, $width, $height, $hBrush) EndIf ;80 If $value > 78 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF06D19") _GDIPlus_GraphicsFillRect($hGraphic, 0, 20, $width, $height, $hBrush) EndIf ;78 If $value > 76 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF07717") _GDIPlus_GraphicsFillRect($hGraphic, 0, 22, $width, $height, $hBrush) EndIf ;76 If $value > 74 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF08015") _GDIPlus_GraphicsFillRect($hGraphic, 0, 24, $width, $height, $hBrush) EndIf ;74 If $value > 72 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF08A13") _GDIPlus_GraphicsFillRect($hGraphic, 0, 26, $width, $height, $hBrush) EndIf ;72 If $value > 70 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF09311") _GDIPlus_GraphicsFillRect($hGraphic, 0, 28, $width, $height, $hBrush) EndIf ;70 If $value > 68 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF09311") _GDIPlus_GraphicsFillRect($hGraphic, 0, 30, $width, $height, $hBrush) EndIf ;68 If $value > 66 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFF09D0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 32, $width, $height, $hBrush) EndIf ;66 If $value > 64 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFECA20F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 34, $width, $height, $hBrush) EndIf ;64 If $value > 62 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFE8A80F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 36, $width, $height, $hBrush) EndIf ;62 If $value > 60 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFE5AD0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 38, $width, $height, $hBrush) EndIf ;60 If $value > 58 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFE1B30F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 40, $width, $height, $hBrush) EndIf ;58 If $value > 56 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFDEB80F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 42, $width, $height, $hBrush) EndIf ;56 If $value > 54 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFDABE0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 44, $width, $height, $hBrush) EndIf ;54 If $value > 52 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFD6C30F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 46, $width, $height, $hBrush) EndIf ;52 If $value > 50 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFCFCE0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 48, $width, $height, $hBrush) EndIf ;50 If $value > 48 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFCCD40F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 50, $width, $height, $hBrush) EndIf ;48 If $value > 46 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFC8D90F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 52, $width, $height, $hBrush) EndIf ;46 If $value > 44 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFC4DF0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 54, $width, $height, $hBrush) EndIf ;44 If $value > 42 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFC1E40F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 56, $width, $height, $hBrush) EndIf ;42 If $value > 40 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFBDEA0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 58, $width, $height, $hBrush) EndIf ;40 If $value > 38 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFBAF00F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 60, $width, $height, $hBrush) EndIf ;38 If $value > 36 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFBAF00F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 62, $width, $height, $hBrush) EndIf ;36 If $value > 34 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFADEF0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 64, $width, $height, $hBrush) EndIf ;34 If $value > 32 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFFA1EE0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 66, $width, $height, $hBrush) EndIf ;32 If $value > 30 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF94ED0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 68, $width, $height, $hBrush) EndIf ;30 If $value > 28 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF88ED0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 70, $width, $height, $hBrush) EndIf ;28 If $value > 26 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF7CEC0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 72, $width, $height, $hBrush) EndIf ;26 If $value > 24 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF6FEB0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 74, $width, $height, $hBrush) EndIf ;24 If $value > 22 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF63EA0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 76, $width, $height, $hBrush) EndIf ;22 If $value > 20 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF56EA0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 78, $width, $height, $hBrush) EndIf ;20 If $value > 18 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF56EA0F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 80, $width, $height, $hBrush) EndIf ;18 If $value > 16 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF4AE90F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 82, $width, $height, $hBrush) EndIf ;16 If $value > 14 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF3EE80F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 84, $width, $height, $hBrush) EndIf ;14 If $value > 12 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF31E70F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 86, $width, $height, $hBrush) EndIf ;12 If $value > 10 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF25E70F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 88, $width, $height, $hBrush) EndIf ;10 If $value > 8 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF18E60F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 90, $width, $height, $hBrush) EndIf ;8 If $value > 6 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF0CE50F") _GDIPlus_GraphicsFillRect($hGraphic, 0, 92, $width, $height, $hBrush) EndIf ;6 If $value > 4 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF00E510") _GDIPlus_GraphicsFillRect($hGraphic, 0, 94, $width, $height, $hBrush) EndIf ;4 If $value > 2 Then $hBrush = _GDIPlus_BrushCreateSolid("0xFF00E509") _GDIPlus_GraphicsFillRect($hGraphic, 0, 96, $width, $height, $hBrush) EndIf ;2 $hBrush = _GDIPlus_BrushCreateSolid("0xFF00E509") _GDIPlus_GraphicsFillRect($hGraphic, 0, 98, $width, $height, $hBrush) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) GUICtrlSendMsg($target, 0x172, 0, $hBitmap) _WinAPI_DeleteObject($hBitmap) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() EndFunc ;==>_CreateBar Func DLL_BitmapCreate($width, $height) Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $width, "int", $height, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0) Return $aResult[6] EndFunc ;==>DLL_BitmapCreate  
       
    • Pricehacker
      By Pricehacker
      Hello,
      I am making a program where the button is an image that "changes" when specific conditions are fullfilled. Problem is that these images have different dimensions and when a smaller picture is displayed over a bigger one both will be seen, therefore i would like the images to be hidden, invincible or, alternatively, deleted.
      I have tried using _GDIPlus_GraphicsClear() with no luck
      However that might just be me not using it right as im quite new to autoit
      Here is the code if you want to test run it:
      Thanks to everyone helping!
    • UEZ
      By UEZ
      AutoIt Windows Screenshooter
      Key Features:
      takes easily a screenshot from any visible window capture any region of the desktop incl. freehand capturing capture GUI controls and GUI menus separately capture a marked area every x seconds for a duration of y seconds create a GIF animation from saved frames (Vista or higher os required) capture to AVI file (without audio!) takes a screenshot from web sites (available only on Win7+ os and when Aero is enabled) put images to clipboard to paste to other applications easily color picker save image in different formats and also to PDF! add timestamp to saved images simple image editing options: greyscale, b&w, invert, rotate +-90° send image to printer and default email client preview of captured screens incl. zoom option multi monitor support display pixel color under mouse ruler basic image editor (paint, highlight, ellipse, rectangle, text and some graphic FX) watermark captured image no 3rd party tools or DLLs used - pure AutoIt! fully portable - no installation is needed multi language feature (Eng, Ger, Tur, Fra and Rus only) To do:
      capture content of scrollable window/control capture cascaded menus Due to DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0) limitation some windows cannot be captured properly (GDI+, ProgDVB, etc.) but can take screenshots of hidden windows. One workaround is to use full screen capturing (F11/F12) or "Grab Screen" function! Or try double click with rmb on listview items (beta).
      Download source code (6295 downloads previously):  AutoIt Windows Screenshooter v1.81 Build 2018-08-12.7z (version 3.3.12.0+ needed!)
      You are not allowed to sell this code or just parts of it in a commercial project or modify it and distribute it with a different name!
      Download compiled Exe only: 4shared / Media Fire / Softpedia (1.54mb)
      Distributing copies of the program in compiled format (exe) must be free of any fee!
      -----> click here to Donate!  
       
      (Current donators: 1. Cuong N.) 
      It is designed for Win7+ operating systems with AERO enabled! E.g. on WinXP machines some functions are not working properly and might crash the application!
      AV scanners may have a negative impact the execution of compiled exe and might report any malware. I guarantee that there is no malicious code in the source code / exe!!! 
      Main GUI:

       
       
      About Intro:

       
       
      Basic Image Editor:

       
       
      Watermark:

       
       
      Click link for an enhanced version of Watermark Image.
      Credits:
      main code by UEZ additional code (alphabetical order) by Authenticity, AutoItObject Team, Eemuli, Eukalyptus, funkey, _Kurt, martin, monoceres, ProgAndy, taietel, trancexx, Ward, wolf9228 and Yashied! mesale0077 for turkish translation wakillon for french translation AZJIO for russian translation Keys:
      Main GUI:
      User your mouse to scroll preview window or
      Numpad 8: Scroll preview window up
      Numpad 2: Scroll preview window down
      Numpad 4: Scroll preview window left
      Numpad 6: Scroll preview window right
      Numpad +: zoom in preview window or mousewheel down
      Numpad -: zoom out preview window or mousewheel up
      F1: capture again on last position
      F5: refresh Windows Name list
      PRINTSCREEN: take screenshot from whole screen
      ALT+PRINTSCR: take a screenshot from active window
      F10: Undo made changes with Image Editing function
      F11: take screenshot from whole screen incl mouse cursor
      F12: take screenshot from whole screen
      Ctrl+Alt+F9 start "Grab Screen" mode
      Ctrl+Alt+F12: take a screenshot from active window using alternative screenshot functionality (beta)!
      Ctrl+r: call ruler
      Ctrl+s: save current displayed image
      Ctrl+x: exit program
      ctrl+w: call web grab input field (availabe only when Aero is enabled)
      Ctrl+i: call image editor
      Ctrl+m: call watermark editor
      Ctrl+z: undo
      Only available on Vista+ os: double click with rmb on list items to use alternative screenshot functionality (beta)!
      When 'Grab Screen' is clicked you can hold down the ctrl key to switch to 'grab controls' mode. Control under mouse will be framed red.
      ctrl + shift will take the screenshot of appropriate control. To capture GUI menues you can press rmb which simulates the lmb. When a menu is opened press shift additionaly to capture it.
      Press and hold only the shift key to capture any region on the desktop using freehand capturing - release it so capture marked regions!
      Or just mark resizeable area which you want to grab. Press CTRL key to grab marked area or right mouse button to capture the marked area every x seconds for a duration of y seconds.
      When saving the image just enter the extension you whish to use (*.jpg;*.png;*.bmp;*.gif;*.tif;*.pdf). Big thanks to taietel for his PDF UDF!
      Image Editor:
      s: save
      c: copy
      n: send
      h: highlighter
      p: pen
      r: rectangle
      e: ellipse
      a: arrow
      o: color
      t: text
      g: text config
      Ctrl+z: undo
      Watermark editor:
      Ctrl+z: undo
       
      To start the app minimized just call it "Windows Screenshooter.exe /min"
      Maybe it is useful for someone...
      Any kind of comment is welcome.
      Br,
      UEZ
      Change log:
       
    • Sven-Seyfert
      By Sven-Seyfert
      Hi Community,

      I'm looking for a way to do a Video Overlay GUI or something like that. The idea is to create a GUI which plays a video loop (with transparency/alpha channel) in front of an other GUI. Before you asking why - because I don't believe that GDIPlus can do it out of the box. My skillset for that kind of graphical things isn't good enough to do that, but here are some specialist like @UEZ maybe who can help.

      Example alpha channel video (visualized as animated *.gif):

      I tried to do the light rays effect directly with GDIPlus, but honestly that's a bit too difficult for me. I would be very glad and grateful if there are some suggestions, ideas or recommendations.

      Code for the Video play:
       
      Example video "End.mpeg":
       
      The next challenge is that the overlay GUI should be not clickable. If I hover over the overlay area, I want to have the possibility to control the GUI or what ever, in the background. But if there is any chance to make it with GDIPlus as a Video Overlay for light rays, I would prefer that approach instead of my crazy work-around idea.

      Thanks for any suggestion - I'm grateful!
      Sven
    • c.haslam
      By c.haslam
      I had thought that _GDIPlus_ImageClone($hImage) removes all property items, but I now know that it copies property items.
      What is the easiest way of copying an image that has property items to another image that does not have property items?
×