Mit einzelnem Tortenstück aus der Funktion _GDIPlus_GraphicsFillPie() weiterarbeiten

  • Hi,


    ich stehe mal wieder im Wald und hoffe darauf, dass ihr nach dem gestrigen Trubel wieder nüchtern genug seid, um mir helfen zu können. ;)

    Nachstehendes Script bewirkt nach dem Laden eines Bildes (idealerweise nicht grösser als 500x500) und nach Drücken des Buttons „Color All But One“, dass aus dem zuvor aufgerufenen Bild ein Tortenstück „herausgeschnitten“ wird.

    Der grosse Rest der „Torte“ wird lediglich auf transparent geschaltet und ist dadurch nicht mehr sichtbar.

    Meine Frage nun:

    Wie kann ich mit dem sichtbaren „Tortenstück“ als separates Objekt weiterarbeiten, ohne jedesmal die gesamte „Torte“ zeichnen zu müssen?

    Also, wie könnte ich das sichtbare „Pie“ zum Beispiel kopieren und zusätzlich zum dem vorhandenen darstellen?

    [autoit]

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <GDIPlus.au3>

    [/autoit][autoit][/autoit][autoit]

    Opt('MustDeclareVars', 1)

    [/autoit][autoit][/autoit][autoit]

    Global $msg, $hGUI, $floor1, $loadPIC, $ColorAllButOnePie
    Global $hGraphics1, $hImage1, $PIC, $PICx, $PICy

    [/autoit][autoit][/autoit][autoit]

    Global $floor1x = 500
    Global $floor1y = 500

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $hGUI = GUICreate("", 600, 600)

    [/autoit][autoit][/autoit][autoit]

    $loadPIC = GUICtrlCreateButton("Bild Laden", 513, 100, 85)
    $ColorAllButOnePie = GUICtrlCreateButton("Color All But One", 513, 140, 85)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $floor1 = GUICtrlCreateGraphic(10, 10, $floor1x, $floor1y)
    GUICtrlSetBkColor($floor1, 0xFFece9d8) ;0xffffff)
    GUICtrlSetGraphic(-1, $GUI_GR_RECT, 0, 0, $floor1x, $floor1y)

    [/autoit][autoit][/autoit][autoit]

    GUISetState()

    [/autoit][autoit][/autoit][autoit]

    _GDIPlus_Startup()

    [/autoit][autoit][/autoit][autoit]

    While 1
    $msg = GUIGetMsg()

    [/autoit][autoit][/autoit][autoit]

    Select
    Case $msg = $GUI_EVENT_CLOSE
    ExitLoop

    [/autoit][autoit][/autoit][autoit]

    Case $msg = $loadPIC
    _loadPIC()

    [/autoit][autoit][/autoit][autoit]

    Case $msg = $ColorAllButOnePie
    _ColorAllButOnePie($floor1x, $floor1y, $hGraphics1, $PICx, $PICy, 0, 300)

    [/autoit][autoit][/autoit][autoit]

    EndSelect
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop

    [/autoit][autoit][/autoit][autoit]

    WEnd

    [/autoit][autoit][/autoit][autoit]

    _GDIPlus_GraphicsDispose($hGraphics1)
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_Shutdown()

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func _loadPIC()

    [/autoit][autoit][/autoit][autoit]

    $PIC = FileOpenDialog("Bitte Bild auswählen", "J:\_LW_K\__OwnProjects\_autoIt\LissajousUndAndere\tesselation\", "Bilder (*.jpg;*.bmp;*.png)", 1 + 4 )
    _GDIPlus_GraphicsClear($hGraphics1, 0xFFece9d8)

    [/autoit][autoit][/autoit][autoit]

    $hImage1 = _GDIPlus_ImageLoadFromFile($PIC)

    [/autoit][autoit][/autoit][autoit]

    $PICx = _GDIPlus_ImageGetWidth($hImage1)
    $PICy = _GDIPlus_ImageGetHeight($hImage1)
    $hGraphics1 = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($floor1))

    [/autoit][autoit][/autoit][autoit]

    _GDIPlus_GraphicsDrawImage ($hGraphics1, $hImage1, $floor1x/2-$PICx/2, $floor1y/2-$PICy/2)

    [/autoit][autoit][/autoit][autoit]

    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func _ColorAllButOnePie($hGuiX, $hGuiY, $hGraphic, $PICx, $PICy, $StartPie, $EndPie)
    Local $Diag = Sqrt(($PICx*$PICx) + ($PICy*$PICy)) ; Berechnung der Bilddiagonale
    Local $SegmentX = ($Diag-$PICx)/2 ; Berechnung des aus dem Kreis herausstehenden Segments zwischen Kreis und Rechteck des Bildes
    Local $SegmentY = ($Diag-$PICy)/2 ; " "

    [/autoit][autoit][/autoit][autoit]

    Local $MidX = $hGuiX/2-$PICx/2 ; Berechnung der Bildmitte
    Local $MidY = $hGuiY/2-$PICy/2 ; " "

    [/autoit][autoit][/autoit][autoit]

    Local $iTrans = 255 ;255

    [/autoit][autoit][/autoit][autoit]

    Local $hBrush = _GDIPlus_BrushCreateSolid("0x" & Hex($iTrans, 2) & "ece9d8")

    [/autoit][autoit][/autoit][autoit]

    _GDIPlus_GraphicsFillPie($hGraphic, $MidX-$SegmentX, $MidY-$SegmentY, $PICx+($Diag-$PICx), $PICy+$Diag-$PICy, $StartPie, $EndPie, $hBrush)
    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit]

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

    Einmal editiert, zuletzt von Peri Petie (30. April 2013 um 21:12)

  • Ich bin mir nicht sicher, ob das genau deinen Vorstellungen entspricht, aber ich denke _GDIPlus_TextureCreate und die anderen _Texture... Funktionen aus der GDIP.au3 könnten dir weiterhelfen.
    Ich hab damit vor Ewigkeiten ein kleines Testscript geschrieben, aber vielleicht findest du auch ein besseres Beispiel.

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $iGUIWidth = 400
    $iGUIHeight = 400
    $GUIColorBG = 0xFFFFFFFF

    [/autoit] [autoit][/autoit] [autoit]

    $iX = 0 ;X-Koordinate des rechteckigen Bitmap Ausschnitts
    $iY = 0 ;Y-Koordinate des rechteckigen Bitmap Ausschnitts
    $iX2 = 0 ;X-Koordinate der Ellipse
    $iY2 = 0 ;Y-Koordinate der Ellipse
    $iWidth = 300 ;Breite des rechteckigen Bitmap Ausschnitts
    $iHeight = 300 ;Höhe des rechteckigen Bitmap Ausschnitts
    $iWidth2 = 400 ;Breite der Ellipse
    $iHeight2 = 400 ;Höhe der Ellipse

    [/autoit] [autoit][/autoit] [autoit]

    $hWnd = GUICreate("Test", $iGUIWidth, $iGUIHeight)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iGUIWidth, $iGUIHeight, $hGraphic)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)
    _GDIPlus_GraphicsClear($hGraphic, $GUIColorBG)
    _GDIPlus_GraphicsClear($hBuffer, $GUIColorBG)

    [/autoit] [autoit][/autoit] [autoit]

    $hImage = _GDIPlus_ImageLoadFromFile(FileOpenDialog("Select Image", "", "Image Files(*.*)"))

    [/autoit] [autoit][/autoit] [autoit]

    $hTextureBrush = _GDIPlus_TextureCreate2($hImage, $iX, $iY, $iWidth, $iHeight)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsFillEllipse($hBuffer, $iX2, $iY2, $iWidth2, $iHeight2, $hTextureBrush)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iGUIWidth, $iGUIHeight)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_BrushDispose($hTextureBrush)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ;Funtionen aus der GDIP.au3:

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_TextureCreate
    ; Description ...: Creates a TextureBrush object based on an image and a wrap mode
    ; Syntax.........: _GDIPlus_TextureCreate($hImage[, $iWrapMode = 0])
    ; Parameters ....: $hImage - Pointer to an Image object
    ; $iWrapMode - Wrap mode that specifies how repeated copies of an image are used to tile an area when it is
    ; +painted with the texture brush:
    ; |0 - Tiling without flipping
    ; |1 - Tiles are flipped horizontally as you move from one tile to the next in a row
    ; |2 - Tiles are flipped vertically as you move from one tile to the next in a column
    ; |3 - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
    ; |4 - No tiling takes place
    ; Return values .: Success - Pointer to a new TextureBrush object
    ; Failure - 0 and either:
    ; |@error and @extended are set if DllCall failed
    ; |$GDIP_STATUS contains a non zero value specifying the error code
    ; Remarks .......: The size of the brush defaults to the size of the image, so the entire image is used by the brush
    ; After you are done with the object, call _GDIPlus_BrushDispose to release the object resources
    ; Related .......: _GDIPlus_BrushDispose
    ; Link ..........; @@MsdnLink@@ GdipCreateTexture
    ; Example .......; No
    ; ===============================================================================================================================
    Func _GDIPlus_TextureCreate($hImage, $iWrapMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateTexture", "hwnd", $hImage, "int", $iWrapMode, "int*", 0)

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(@error, @extended, 0)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[3]
    EndFunc ;==>_GDIPlus_TextureCreate

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_TextureCreate2
    ; Description ...: Creates a TextureBrush object based on an image, a wrap mode and a defining rectangle
    ; Syntax.........: _GDIPlus_TextureCreate2($hImage, $nX, $nY, $nWidth, $nHeight[, $iWrapMode = 0])
    ; Parameters ....: $hImage - Pointer to an Image object
    ; $nX - Leftmost coordinate of the image portion to be used by this brush
    ; $nY - Uppermost coordinate of the image portion to be used by this brush
    ; $nWidth - Width of the brush and width of the image portion to be used by the brush
    ; $nHeight - Height of the brush and height of the image portion to be used by the brush
    ; $iWrapMode - Wrap mode that specifies how repeated copies of an image are used to tile an area when it is
    ; +painted with the texture brush:
    ; |0 - Tiling without flipping
    ; |1 - Tiles are flipped horizontally as you move from one tile to the next in a row
    ; |2 - Tiles are flipped vertically as you move from one tile to the next in a column
    ; |3 - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
    ; |4 - No tiling takes place
    ; Return values .: Success - Pointer to a new TextureBrush object
    ; Failure - 0 and either:
    ; |@error and @extended are set if DllCall failed
    ; |$GDIP_STATUS contains a non zero value specifying the error code
    ; Remarks .......: After you are done with the object, call _GDIPlus_BrushDispose to release the object resources
    ; Related .......: _GDIPlus_BrushDispose
    ; Link ..........; @@MsdnLink@@ GdipCreateTexture2
    ; Example .......; No
    ; ===============================================================================================================================
    Func _GDIPlus_TextureCreate2($hImage, $nX, $nY, $nWidth, $nHeight, $iWrapMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateTexture2", "hwnd", $hImage, "int", $iWrapMode, "float", $nX, "float", $nY, "float", $nWidth, "float", $nHeight, "int*", 0)

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(@error, @extended, 0)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[7]
    EndFunc ;==>_GDIPlus_TextureCreate2

    [/autoit]
  • Hi name22,

    vielen Dank für Deine Hilfe. Das ist eine geile Funktion, die mir beim Stöbern im Forum schon aufgefallen ist.
    Leider kann ich sie für meinen Zweck nicht wirklich nutzen.

    Mir kommt es wirklich darauf an, mit dem aus der Funktion "_GDIPlus_GraphicsFillPie" freigestellten Tortenstück als separates Objekt weiterzuarbeiten, zumal ich hiermit auch die Möglichkeit habe, "schiefwinklige" Ausschnitte aus einem Bild erstellen zu können.

    Trotzdem noch einmal vielen Dank.

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • Wie genau willst du denn damit weiterarbeiten? Du kannst ja mit einfach ein Polygon erstellen, dass genau die Koordinaten deines übriggebliebenen Tortenstücks hat. Dafür verwendest du als Textur dann das Originalbild. Dadurch kannst du das hinzeichnen wo du willst. Ich verstehe nicht ganz wo jetzt die Einschränkung für dich liegt.

  • Wurde "gezwungen", erstmal Middach zu machen.
    So, und nun aber gestärkt in den Kampf. :D ;)

    Wozu ein Polygon erstellen? Meinst Du das in Bezug auf Deine Funktion? ?(

    Also, bevor wir aneinander vorbeireden, noch einmal meine Frage:
    Wie kann ich, bezugnehmend auf mein Script, das sichtbare Tortenstück kopieren und neben, über oder unter (egal) das bereits sichtbare Tortenstück plazieren (sorry, alte Rechtschreibung), ohne die gesamte Torte mittels der Funktion "_GDIPlus_GraphicsFillPie" zeichnen zu müssen?

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • Ja ich meinte das in Bezug auf die Funktion. Du musst auch nicht ein Polygon erstellen, das war wohl schlecht formuliert. Du kannst einfach weiterhin _GDIPlus_GraphicsFillPie nutzen, nur zeichnest du den Ausschnitt der übrig bleibt, statt alles zu zeichnen und dann zu übermalen.

    Wie willst du es denn sonst zeichnen? Mit einer anderen Funktion? ^^
    Wenn du das Originalbild als Textur verwendest, kannst du dieses Tortenstück das nach dem Übermalen übrig bleibt hinzeichnen wo du willst.Dafür brauchst du allerdings die Koordinaten dieses Resttortenstücks bzw. dessen Winkel (je nachdem mit welcher Funktion du arbeitest).

  • "Du kannst einfach weiterhin _GDIPlus_GraphicsFillPie nutzen, nur
    zeichnest du den Ausschnitt der übrig bleibt, statt alles zu zeichnen
    und dann zu übermalen.
    "

    ??? ?(
    Wenn ich "_GDIPlus_GraphicsFillPie" anwende, dann zeichne ich doch die gesamte Torte und nicht "nur den Ausschnitt, der übrig bleibt".
    Auch wenn ich den grössten Teil transparent male, so ist er immer noch vorhanden und ich muss ihn immer wieder mitzeichnen, das wollte ich ja vermeiden.

    Es gibt also keine Möglichkeit, in Bezug auf mein Script, ein einzelnes Pie, das sichtbar auf meiner Arbeitsfläche plaziert ist, als Bitmap-, Graphics-, Image- oder sonstiges Objekt neu zu deklarieren, um damit weiterarbeiten zu können?

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • Zitat

    Wenn ich "_GDIPlus_GraphicsFillPie" anwende, dann zeichne ich doch die gesamte Torte und nicht "nur den Ausschnitt, der übrig bleibt".


    Nein du zeichnest nur das Tortenstück, dass durch die beiden Winkelangaben spezifiziert ist. Du willst doch dieses Tortenstück, dass man in deinem Script sieht nachdem man auf "Color All but One" geklickt hat, direkt irgendwo hinzeichnen, ohne dazu das ganze Bild zeichnen zu müssen, oder? Und genau das kannst du auch machen, indem du von vornerein dieses Tortenstück das übrigbleibt (nicht das, dass du im Moment per _GDIPlus_GraphicsFillPie zeichnest) zeichnest. Die vorher geladene Textur kannst du dann als Füllfarbe für dieses "Objekt" verwenden.
    Probier es doch erstmal aus, so wie ich es eben beschrieben habe. Dann siehst du ja, ob es das ist was du meintest.

  • Bei einer Tasse Kaffee habe ich mein Konzept noch einmal überdacht und festgestellt, dass ich für weitere Operationen meines Programms den gesamten "Kuchen" benötige. Das zwischenzeitliche Separieren eines einzelnen Pies ist für mein Vorhaben unsinnig und hat sich somit erledigt.

    Meine grundsätzliche Frage, ob man mit einem einzelnen Pie als eigenständiges Objekt weiterarbeiten kann, bleibt allerdings leider unbeantwortet. :(
    Das muss auch anders funktionieren, als es erst in ein Objekt mit Textur umwandeln zu müssen.
    Eine Möglichkeit wäre vielleicht, die Grösse des angrenzenden Rechtecks zu ermitteln, in dem sich das Pie befindet, um dieses dann per "BitmapCloneArea" vom Kuchen abzuspalten. Halte ich auch für einen Umweg, aber wesentlich kürzer als Dein Ansatz.
    Aber egal, ich brauch's ja nun nicht mehr.

    Dennoch vielen Dank nochmals für Deine Mühe, name22.

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • "Jetzt bin ich echt nur noch verwirrt"
    ;)

    Das war nun wirklich nicht meine Absicht, zumal Du mir einen neuen Lösungsansatz aufgezeigt hast. Denn inzwischen habe ich mich endgültig von meiner Idee mit der Kuchenform verabschiedet, da sich hierbei doch immer wieder Bereiche überlappen, wo es störend ist. Habe mich nun doch entschlossen,
    mir die Dreiecke mit Polygonen selbst zu erstellen. Ist zwar mehr Arbeit (die Dreieckserstellung mit der „Pie-Funktion“ war so angenehm simpel :rofl: ), aber geometrische Berechnungen kriege ich schon hin. Ausserdem denke ich, dass ich damit später in meiner geplanten Anwendung wesentlich flexibler bin.

    Mit den TexturCreate-Funktionen habe ich zwischenzeitlich auch ein wenig rumgespielt. Im Grunde passen sie ja genau in die Schublade, in der ich gerade „wühle“.

    Was mich anfangs abgeschreckt hatte, war, dass sie lediglich vertikal und horizontal anzuwenden sind und nicht diagonal. Das hiesse also, dass ich mein Bild erst drehen müsste, um einen „schrägen“ Bildausschnitt zu erhalten. Aber mit Matrixfunktionen habe ich ein wenig Erfahrung und sollte kein grosses Problem sein. Ausserdem habe ich in der GDIP.au3 auch die Funktionen TextureScale- und TextureRotate-Transform entdeckt. Muss ich aber noch ausprobieren.

    Also, trotz Verwirrung habe ich durch Deine Tipps einen neuen Weg nach Rom gefunden.
    Mal sehen, ob ich auch in Rom ankomme. ;)

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • Zitat

    Was mich anfangs abgeschreckt hatte, war, dass sie lediglich vertikal und horizontal anzuwenden sind und nicht diagonal. Das hiesse also, dass ich mein Bild erst drehen müsste, um einen „schrägen“ Bildausschnitt zu erhalten. Aber mit Matrixfunktionen habe ich ein wenig Erfahrung und sollte kein grosses Problem sein. Ausserdem habe ich in der GDIP.au3 auch die Funktionen TextureScale- und TextureRotate-Transform entdeckt. Muss ich aber noch ausprobieren.


    Das hatte ich schon vermutet, aber ich konnte es nicht eindeutig aus deinen Beiträgen herauslesen ^^. Da versucht man das Thema möglichst simpel zu halten und dann ist das genau das Falsche... ;)

  • So falsch war das gar nicht. Ausserdem sollte ich mir meine eigenen Beiträge mal genauer durchlesen, dann hätte sich mein Problem mit dem Dreieck gleich erledigt.
    Bin nämlich zwischenzeitlich zu folgender Erkenntnis gelangt: :rofl:

    Legt man mehrere Skatkarten im Halbkreis angordnet übereinander (so, wie man sie während eines Spiels üblicherweise auch in der Hand hält), ergibt sich bei jeder unter einer anderen liegenden Karte automatisch ein Dreieck, na ja, ok, zumindest annähernd.
    Ergo: ich muss die Karte nicht erst zerschnippeln, um einen dreieckigen Ausschnit zu erhalten. Der Rotationswinkel des darüberliegenden Rechtecks ist entscheidend.

    Bei meiner Anwendung geht es zwar nicht um Spielkarten, aber die Anordnung der Bilder ist teilweise ähnlich.
    Kannst Du nicht nicht wissen. Ich bitte auch um Nachsicht wegen "nicht eindeutig", dafür habe ich aber meine Gründe. ;)
    Ich werde mich aber bemühen, soweit es geht, meine Fragen so konkret zu stellen, wie es möglich ist.

    Ausserdem ist meine Frage nach der Referenzierung eines einzelnen Tortenstücks anscheinend im Nirvana angelangt. Konkreter geht es doch wohl nicht. :P ;)

    So, und nun noch ein schönes Wochenende, auch an alle anderen Cracks hier im Forum. :thumbup:

    Auch wenn ich nichts weiß, muss ich nicht alles glauben

  • Habe mich nun eigenmächtig dazu entschlossen, dass Thema als gelöst zu markieren, auch wenn die eigentliche Frage nicht beantwortet wurde, das Problem aber anderweitig gelöst werden konnte.

    Meine Anwendung läuft bereits seit einiger Zeit ohne Flackern und ohne "schwarze Löcher".

    @ name22:
    Höre und staune: Kernstück der Anwendung ist "_GDIPlus_TextureCreate2" :thumbup:
    Danke. :)

    Auch wenn ich nichts weiß, muss ich nicht alles glauben