Bilder trapezförmig skalieren und mit Text versehen

  • Hallo Leute,
    kennt jemand einen Weg ein vorhandenes Bild...
    1. mit einem beliebigen Text zu versehen (also als weiße Schrift zentriert mitten drauf). Der Text ist bei jedem Programmaufruf verschieden.
    2. dieses neue Bild dann für eine Animation trapezförmig zu skalieren (das ist auf dem Bild nicht gut erkennbar).

    Wäre super wenn jemand einen guten Ansatz dafür hätte.


    Ani.jpg

  • Ich weiß zwar nicht, wo in dem Bild ein Trapez sein soll, aber das Ganze lässt sich ganz gut in GDI+ realisieren.

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Das mit GDI+ war mir fast schon klar.

    UEZ:
    Ja, auf dem Bild ist das nicht gut erkennbar. Das ganze soll so aussehen, dass das ganze von oben heruntergeklappt kommt. Die Drehachse soll die vordere obere Kante sein und praktisch in der Bildschirmebene liegen . Von der Theorie her müsste die hintere Kante schmaler sein und daher kommt die Trapezform.

    Kennt jemand, bzw. könnte jemand mal die notwendigen Methoden aufschreiben, weil ich überhaupt keinen Ansatz habe, weder für den Text, noch für die Animation.

  • [autoit]


    $hImage=_GDIPlus_ImageLoadFromFile($sFileName) ;Bild laden
    _GDIPlus_ImageScale ( $hImage, $iScaleW, $iScaleH [, $iInterpolationMode = $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC] ) ;Bild skalieren
    _GDIPlus_ImageGetGraphicsContext ( $hImage ) ;Graphic um Text draufzumalen

    [/autoit]


    Und dann hat @chesstiger grad erst ein Tutorial zu GDI+ gemacht. Da steht, wie du auf ein Bild malst.
    Rundumschlag GDI+?

  • Ein Trapez mit dem Bild geht leider nicht, aber ein Parallelogramm schon! -> _GDIPlus_DrawImagePoints

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Ok schonmal danke. Das mit dem Text sollte jetzt laufen. Nur das Parallelogramm bringt mir nicht wirklich viel. Ich bin vorhin dann auf einen älteren Thread gestoßen (https://autoit.de/index.php/Thre…oints/?pageNo=1). Interessanter weise funktioniert nur das dort gepostete nicht wirklich. Aber vom Ansatz her wäre das vielleicht was.


    Ist zufällt mal jemandem aufgefallen, dass wenn man mit

    [autoit]

    _GDIPlus_GraphicsDrawStringEx(...)

    [/autoit]


    einen String ausgeben lässt, der bei größeren Schriftgrößen (>100) nicht mehr exakt bei der Koordinate beginnt, die man angegeben hat? Ich bekomme da immer eine Verschiebung von ca. 150 Pixeln(in Abhängigkeit von der Schriftgr.) nach rechts. Hat da jemand eine Idee wie man die weg bekommt?

    Einmal editiert, zuletzt von Thomas (7. April 2015 um 22:02)

  • Du kannst ja dies mal als Ansatz nehmen:

    Spoiler anzeigen
    [autoit]

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

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

    Global $sImageFile = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.bmp)")
    If @error Then Exit MsgBox(0, "Information", "Nothing selected - stopping script!", 30)
    _GDIPlus_Startup()
    Global $hBitmap = _GDIPlus_BitmapCreateFromFile($sImageFile)
    DrawTextOnBitmap($hBitmap, "This is a GDI+ demo", 50)
    Global Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Global Const $hGUI = GUICreate("GDI+ Test", $iW, $iH)
    GUISetBkColor(0)
    GUISetState()
    Global Const $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global Const $hBmp = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
    Global Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetPixelOffsetMode($hCtxt, 2)
    Global $fPosX = 0, $fPosY = 0
    AdlibRegister("Anim", 30)

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

    Do
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    AdlibUnRegister("Anim")
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_GraphicsDispose($hCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_Shutdown()
    GUIDelete()
    Exit
    EndSwitch
    Until False

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

    Func Anim()
    _GDIPlus_GraphicsClear($hCtxt)
    _GDIPlus_DrawImagePoints($hCtxt, $hBitmap, 0, 0, $iW, 0, $fPosX, $fPosY)
    _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBmp, 0, 0, $iW, $iH)
    Local Static $iX = 0, $fAmpl = 40
    $fPosY += ($fPosY <= $iH) ? 2 : 0
    If $fPosY <= $iH Then
    $fPosX = Cos($fPosY / 30) * $fAmpl
    $iX = $fPosY
    Else
    $fPosX = Cos($iX / 30) * $fAmpl
    $iX += 2
    $fAmpl -= $fAmpl > 0 ? 0.25 : 0
    If $fAmpl <= 0 Then AdlibUnRegister("Anim")
    EndIf
    EndFunc

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

    Func DrawTextOnBitmap(ByRef $hBitmap, $sText, $fFontSize, $sFontTyp = "Impact", $iInnerColor = 0xFFFFFFFF, $iBorderColor = 0xFF000000)
    Local Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGfx, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hGfx, 3)
    _GDIPlus_GraphicsSetPixelOffsetMode($hGfx, 2)
    Local Const $hBrush_Inner = _GDIPlus_BrushCreateSolid($iInnerColor), $hPen_Border = _GDIPlus_PenCreate($iBorderColor, 1.5)
    Local Const $hPath = _GDIPlus_PathCreate(), $hFamily = _GDIPlus_FontFamilyCreate($sFontTyp), $hFormat = _GDIPlus_StringFormatCreate()
    Local Const $tLayout = _GDIPlus_RectFCreate(0, 0, $iW, $iH)
    _GDIPlus_StringFormatSetAlign($hFormat, 1)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 1)
    _GDIPlus_PathAddString($hPath, $sText, $tLayout, $hFamily, 0, $fFontSize, $hFormat)
    _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush_Inner)
    _GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen_Border)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BrushDispose($hBrush_Inner)
    _GDIPlus_PenDispose($hPen_Border)
    _GDIPlus_PathDispose($hPath)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    EndFunc

    [/autoit]

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (8. April 2015 um 18:35)

  • Das sieht sehr sehr gut aus, vorallem läuft es flüssig.
    Es gibt nur zwei Dinge die man noch ändern müsse:
    - Das Schwenken von rechts nach links und umgekehrt könnte man ganz rausnehmen. Das ist für den Zweck etwas unangebracht. Schön wäre es, wenn man diesen Effekt nur einseitig hätte.
    - Gleichzeitig müsste es zeitlich etwas zusammenschrumpfen. Bei mir dauert aktuell das Programm mit einem BIld von 1444x777 Pixel mehr als 16 Sekunden. Zur Verfügung steht aber gerade einmal eine 3/4 Sekunde für die komplette Animation von Beginn bis Ende.

  • Den Ansatz hast du, haue rein, wie du es gerne hättest.

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (10. April 2015 um 08:33)

  • Was gibt es denn noch für Möglichkeiten das ganze zu verschnellern, außer den Zeilenabstand zu erhöhen? Der Code lässt sich ja auch nicht viel effizienter gestalten.

  • Probiere es mal damit:

    [autoit]

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

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

    Global $sImageFile = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.bmp)")
    If @error Then Exit MsgBox(0, "Information", "Nothing selected - stopping script!", 30)
    _GDIPlus_Startup()
    Global $hBitmap = _GDIPlus_BitmapCreateFromFile($sImageFile)
    DrawTextOnBitmap($hBitmap, "This is a GDI+ demo", 50)
    Global Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Global Const $hGUI = GUICreate("GDI+ Test", $iW, $iH)
    GUISetBkColor(0)
    GUISetState()
    Global Const $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global Const $hBmp = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
    Global Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetPixelOffsetMode($hCtxt, 2)
    Global $fPosX = 0, $fPosY = 0, $iSpeed = $iH / 20
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSpeed = ' & $iSpeed & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    AdlibRegister("Anim", 20)

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

    Do
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    AdlibUnRegister("Anim")
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_GraphicsDispose($hCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_Shutdown()
    GUIDelete()
    Exit
    EndSwitch
    Until False

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

    Func Anim()
    _GDIPlus_GraphicsClear($hCtxt)
    _GDIPlus_DrawImagePoints($hCtxt, $hBitmap, 0, 0, $iW, 0, $fPosX, $fPosY)
    _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBmp, 0, 0, $iW, $iH)
    $fPosY += ($fPosY < $iH) ? $iSpeed : AdlibUnRegister("Anim")
    EndFunc

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

    Func DrawTextOnBitmap(ByRef $hBitmap, $sText, $fFontSize, $sFontTyp = "Impact", $iInnerColor = 0xFFFFFFFF, $iBorderColor = 0xFF000000)
    Local Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGfx, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hGfx, 3)
    _GDIPlus_GraphicsSetPixelOffsetMode($hGfx, 2)
    Local Const $hBrush_Inner = _GDIPlus_BrushCreateSolid($iInnerColor), $hPen_Border = _GDIPlus_PenCreate($iBorderColor, 1.5)
    Local Const $hPath = _GDIPlus_PathCreate(), $hFamily = _GDIPlus_FontFamilyCreate($sFontTyp), $hFormat = _GDIPlus_StringFormatCreate()
    Local Const $tLayout = _GDIPlus_RectFCreate(0, 0, $iW, $iH)
    _GDIPlus_StringFormatSetAlign($hFormat, 1)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 1)
    _GDIPlus_PathAddString($hPath, $sText, $tLayout, $hFamily, 0, $fFontSize, $hFormat)
    _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush_Inner)
    _GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen_Border)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BrushDispose($hBrush_Inner)
    _GDIPlus_PenDispose($hPen_Border)
    _GDIPlus_PathDispose($hPath)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    EndFunc

    [/autoit]

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (10. April 2015 um 21:17)

  • Das geht auch. D.h. anstelle die Grafik zu löschen, muss du das vorige Bild in die Grafik kopieren.

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Ok ist auch fast erledigt ;)
    Aber eine Frage habe ich dann doch noch:
    Wenn ich einen beliebig lagen Text (meistens nur ein bis wenige Wörter) in einer Variable $text habe, wie kann ich für die oben gegebene Funktion

    [autoit]

    Func DrawTextOnBitmap(...)

    [/autoit]


    die größtmögliche Schritftgröße in Abhängigkeit von den maximalen Breite (@DesktopWidth-50) und Höhe (2/3*@DesktopWidth) errechnen?

  • Du kannst die Größe zb. so anpassen:

    [autoit]


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

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

    Global $sImageFile = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.bmp)")
    If @error Then Exit MsgBox(0, "Information", "Nothing selected - stopping script!", 30)
    _GDIPlus_Startup()
    Global $hBitmap = _GDIPlus_BitmapCreateFromFile($sImageFile)
    DrawTextOnBitmap($hBitmap, "This is a GDI+ demo")
    Global Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Global Const $hGUI = GUICreate("GDI+ Test", $iW, $iH)
    GUISetBkColor(0)
    GUISetState()
    Global Const $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global Const $hBmp = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
    Global Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBmp)
    _GDIPlus_GraphicsSetPixelOffsetMode($hCtxt, 2)
    Global $fPosX = 0, $fPosY = 0, $iSpeed = $iH / 20
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSpeed = ' & $iSpeed & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    AdlibRegister("Anim", 20)

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

    Do
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    AdlibUnRegister("Anim")
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_GraphicsDispose($hCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBmp)
    _GDIPlus_Shutdown()
    GUIDelete()
    Exit
    EndSwitch
    Until False

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

    Func Anim()
    _GDIPlus_GraphicsClear($hCtxt)
    _GDIPlus_DrawImagePoints($hCtxt, $hBitmap, 0, 0, $iW, 0, $fPosX, $fPosY)
    _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBmp, 0, 0, $iW, $iH)
    $fPosY += ($fPosY < $iH) ? $iSpeed : AdlibUnRegister("Anim")
    EndFunc ;==>Anim

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

    Func DrawTextOnBitmap(ByRef $hBitmap, $sText, $iBorder = 10, $sFontTyp = "Impact", $iInnerColor = 0xFFFFFFFF, $iBorderColor = 0xFF000000)
    Local Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGfx, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hGfx, 3)
    _GDIPlus_GraphicsSetPixelOffsetMode($hGfx, 2)
    Local Const $hBrush_Inner = _GDIPlus_BrushCreateSolid($iInnerColor), $hPen_Border = _GDIPlus_PenCreate($iBorderColor, 1.5)
    Local Const $hPath = _GDIPlus_PathCreate(), $hFamily = _GDIPlus_FontFamilyCreate($sFontTyp), $hFormat = _GDIPlus_StringFormatCreate()
    Local Const $tLayout = _GDIPlus_RectFCreate(0, 0, $iW, $iH)
    ;_GDIPlus_StringFormatSetAlign($hFormat, 1)
    ;_GDIPlus_StringFormatSetLineAlign($hFormat, 1)
    _GDIPlus_PathAddString($hPath, $sText, $tLayout, $hFamily, 0, 10, $hFormat)

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

    Local $aBounds = _GDIPlus_PathGetWorldBounds($hPath)
    Local $fScale = ($iW - $iBorder * 2) / $aBounds[2]
    If ($iH - $iBorder * 2) / $aBounds[3] < $fScale Then $fScale = ($iH - $iBorder * 2) / $aBounds[3]
    Local $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixTranslate($hMatrix, -($aBounds[0] + $aBounds[2] * 0.5), -($aBounds[1] + $aBounds[3] * 0.5))
    _GDIPlus_MatrixScale($hMatrix, $fScale, $fScale, True)
    _GDIPlus_MatrixTranslate($hMatrix, $iW * 0.5, $iH * 0.5, True)
    _GDIPlus_PathTransform($hPath, $hMatrix)
    _GDIPlus_MatrixDispose($hMatrix)

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

    _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush_Inner)
    _GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen_Border)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BrushDispose($hBrush_Inner)
    _GDIPlus_PenDispose($hPen_Border)
    _GDIPlus_PathDispose($hPath)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    EndFunc ;==>DrawTextOnBitmap

    [/autoit]
  • Funktioniert jetzt auch :D


    Kann man die Funktion auch so schreiben, dass...
    1. man einen Bereich vorgibt wo die Schrift steht, also eine Position und eine Breite bzw. Höhe des "Rahmens" und
    (konkret heißt das, dass man eine xund eine y Position und dazu noch die Width und die High)


    2. sie automatisch einen Zeilenumbruch macht, wenn der Text insgesamt mit Zeilenumbruch größer wäre als ohne?
    (Beispiel: Der Text "Landwirtschaft nimmt wieder stark zu" wäre in eine Zeile gequetscht ziemlich klein. Hier wäre ein Zeilenumbruch wie z.B. "Landwirtschaft nimmt / wieder stark zu" sinnvoll und die Schrift wäre insgesamt dadurch größer. Zeilenumbrüche sollten aber nur eingefügt werden, wenn ein Leerzeichen vorhanden sind. Worttrennungen sind also nicht nötig.)


    Der rote Kasten entspricht den Vorgaben unter Punkt 1.
    Ich habe auch dafür keinen Ansatz parat.

  • Dies sollte deine 2 Fragen beantworten:


    1. $fDX und $fDY
    2. $fFontSize

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Prizipiell schon gut, nur kann ich die FontSize manuell nicht anpassen. Das muss die Funktion anhand des übergeben Textes selber machen inkl. die Aufteilung in die Zeilen. Die Funktion von eukalyptus macht soetwas ja schon, es fehlt da halt nur die beiden Punkte, die ich oben notiert hatte.

    • Offizieller Beitrag

    Hallo,

    für das automatische einfügen von Zeilenumbrüchen hatte mal eine Funktion geschriebe, vielleicht kannst damit ja was anfangen!

  • Prizipiell schon gut, nur kann ich die FontSize manuell nicht anpassen. Das muss die Funktion anhand des übergeben Textes selber machen inkl. die Aufteilung in die Zeilen. Die Funktion von eukalyptus macht soetwas ja schon, es fehlt da halt nur die beiden Punkte, die ich oben notiert hatte.


    Ich verstehe dich nicht ganz. Die Funktion bricht doch automatisch den Text um, wenn der Text nicht in eine Zeile passt. Oder willst du an Hand des Textes die maximale Größe des Textes haben?

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯