Animation GDI+ oder Programm?

  • Hallo allerseits!

    Ich habe folgendes Problem: Auf einer Hintergrundgrafik soll sich ein Objekt bewegen, die Richtung sollte frei wählbar sein. Dabei sollten dann alle 2 Pixel Bewegung Bilder abgespeichert werden, damit sich zusammengesetzt als Film, eine "flüssige" Bewegung gibt. Sollte ich (und wenn ja, wie) mit GDI + machen, oder kann mir jemand ein Programm empfehlen (geht das vllt. mit GIMP o.ä.?), ich möchte aber 100 Einzelbilder, deshalb lieber nicht per Hand...

    Habe es schon mit einer "GIMP-Automation" versucht, aber das ist mir etwas zu unsicher, da GIMP keine eindeutigen Controls hat (bzw. Classes, die ich noch nie gesehen habe: InputFeld = ChildGUI oder so in die Richtung...) ?(

    Kann mir da jemand helfen?

  • Mit GDI+ sollte das zu schaffen sein ;) Speichere erst mal 2 Bilder: das Hintergrundbild und das zum draufzeichnen. Dann erzeugts du ein neues GDI+-Bitmap, zeichnest erst den Hintergrund, dann das Objekt und speicherst dann ab. Das wiederholst du, so oft du willst. Beispiel:

    Spoiler anzeigen
    [autoit]

    #include<GDIPlus.au3>

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

    _GDIPlus_Startup()
    $hImgBack = _GDIPlus_ImageLoadFromFile("AutoIt.jpg")

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

    $hGraphics = _GDIPlus_ImageGetGraphicsContext($hImgBack)
    $hBmpDraw = _GDIPlus_BitmapCreateFromGraphics( _GDIPlus_ImageGetWidth($hImgBack), _GDIPlus_ImageGetHeight($hImgBack), $hGraphics)
    _GDIPlus_GraphicsDispose($hGraphics)
    $hGraphicsDraw = _GDIPlus_ImageGetGraphicsContext($hBmpDraw)

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

    $hImgFore = _GDIPlus_ImageLoadFromFile("AU3.png")

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

    DirCreate(@DesktopDir & "\GDIpAni")
    For $i = 1 To 100
    _GDIPlus_GraphicsDrawImage($hGraphicsDraw, $hImgBack, 0, 0)
    _GDIPlus_GraphicsDrawImage($hGraphicsDraw, $hImgFore, $i, $i)
    _GDIPlus_ImageSaveToFile($hBmpDraw, @DesktopDir & "\GDIpAni\" & StringFormat("%03i.jpg",$i))
    If Mod($i,10)=0 Then Sleep(10)
    Next

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

    _GDIPlus_GraphicsDispose($hGraphicsDraw)
    _GDIPlus_BitmapDispose($hBmpDraw)
    _GDIPlus_ImageDispose($hImgBack)
    _GDIPlus_ImageDispose($hImgFore)

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

    _GDIPlus_Shutdown()

    [/autoit]

    2 Mal editiert, zuletzt von progandy (1. Mai 2009 um 13:38)

  • Danke! Das funktioniert an sich schon ganz gut, nur ein Problem habe ich immer noch: Die Qualität des neuen Bildes, das, welches bewegt wird, lässt sehr nach und es wird kleiner?

  • Wie meinst du, es wird kleiner? GDIPlus berechnet in die Größe irgendwie die DPI-Werte mit ein, die im Bild gespeichert sind.

  • Ich kann ja mal die Bilder einstellen: Das M ist das, was hin und her bewegt wird:

    So sollte es eigentlich aussehen:
    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.
    Das ist das M:
    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.
    Und so sieht es aber nachher aus:
    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.

    Edit: Und kann ich auch als PNG abspeichern?

    Einmal editiert, zuletzt von MatthiasG. (1. Mai 2009 um 15:34)

  • Ja, du kannst als PNG abspeichern ;) Einfach die Endung ändern. Und du musst beide Bilder in der gleichen Auflösung speichern, z.B. 72 dpi.

    Spoiler anzeigen
    [autoit]

    #include<GDIPlus.au3>

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

    _GDIPlus_Startup()
    $hImgBack = _GDIPlus_ImageLoadFromFile("102.png")

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

    $hGraphics = _GDIPlus_ImageGetGraphicsContext($hImgBack)
    $hBmpDraw = _GDIPlus_BitmapCreateFromGraphics( _GDIPlus_ImageGetWidth($hImgBack), _GDIPlus_ImageGetHeight($hImgBack), $hGraphics)
    _GDIPlus_GraphicsDispose($hGraphics)
    $hGraphicsDraw = _GDIPlus_ImageGetGraphicsContext($hBmpDraw)

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

    $hImgFore = _GDIPlus_ImageLoadFromFile("m.png")

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

    DirCreate(@DesktopDir & "\GDIpAni")
    For $i = 1 To 100
    _GDIPlus_GraphicsDrawImage($hGraphicsDraw, $hImgBack, 0, 0)
    _GDIPlus_GraphicsDrawImage($hGraphicsDraw, $hImgFore, $i, $i)
    _GDIPlus_ImageSaveToFile($hBmpDraw, @DesktopDir & "\GDIpAni\" & StringFormat("%03i.png",$i))
    If Mod($i,10)=0 Then Sleep(10)
    Next

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

    _GDIPlus_GraphicsDispose($hGraphicsDraw)
    _GDIPlus_BitmapDispose($hBmpDraw)
    _GDIPlus_ImageDispose($hImgBack)
    _GDIPlus_ImageDispose($hImgFore)

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

    _GDIPlus_Shutdown()

    [/autoit]
  • Das ist genial!
    Danke! :)

    Kann man solche Bilder auch mit Alphakanal erstellen, also einen Einblende-Effekt hinzufügen? :D

  • Oh... Dann versuche ich es doch noch mal mit GIMP. ;)

    Jetzt ernsthaft, was ist ColorMatrix genau, ich kann mir unter dem Artikel nicht viel vorstellen...

    Und wie übersetzt man sowas überhaupt?

  • ColorMatrix versteh ich auch nicht so ganz.
    Die Links mit den Pfilen geben nur Infos an, wo du die Daten zu DLLCall und DLLStructCreate für die Funktionen aus dem Artikel bekommst.
    Zum Übersetzen: Du schaust dir den Code an, suchst die passenden Funktionen aus der Übersicht, dir ich dir gepostet habe und machst daraus den DLLCall. Da muss man öfters einige Zeit suchen, da die Flat-API-Funktionen nicht genau so wie die Funktionen in den C++-Objekten heißen :(

  • Also, nur um zu gucken, ob ich es richtig verstanden hab:

    Code
    Image img1("Flower1.jpg");
    Image img2("Flower2.jpg");


    Ist ja ziemlich simpel über

    [autoit]

    _GDIPlus_ImageLoadFromFile

    [/autoit]


    möglich.

    Code
    ColorMatrix ClrMatrix =         { 
                1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
                0.0f, 0.0f, 0.0f, 0.0f, 1.0f
    };


    Hier ließe sich ein 2D-Array deklarieren, oder?

    Code
    ImageAttributes ImgAttr;
    
    
    ImgAttr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault, 
                            ColorAdjustTypeBitmap);


    Da wird ja transparent gemalt, aber wie?

    Code
    g.DrawImage(&img1, 0,0,img1.Width,img1.Height);


    Wieder relativ leicht über

    [autoit]

    _GDIPlus_GraphicsDrawImage()

    [/autoit]
    Code
    g.DrawImage(&img2, RectF destination(0,0, img2.Width,img2.Height), 0,0, 
                      img2.Width,img2.Height,UnitPixel,&ImgAttr);


    Das gleiche...


    Ist das so weit richtig, was muss ich nun tun?

  • Ich breche hier ab, das wird glaube ich zu tiefgreifend für mich... Ich konnte GIMP über Send und MouseClick so weitgehend "automatisieren", dass ich es dennoch hingekriegt habe.

    Trotzdem danke für deinbe Bemühungen Progandy! :thumbup: Du hast mir echt weitergeholfen!

  • Ich hab mich mal damit beschäftigt und ich hab es so weit geschafft. Die Transparenz funktioniert. Mit der ColorMatrix kann man auch farben invertieren, verändern usw ;)

    Spoiler anzeigen
    [autoit]

    #include<GDIplus.au3>

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

    ; Constants
    Global Const $ColorAdjustTypeDefault = 0
    Global Const $ColorAdjustTypeBitmap = 1
    Global Const $ColorAdjustTypeBrush = 2
    Global Const $ColorAdjustTypePen = 3
    Global Const $ColorAdjustTypeText = 4
    Global Const $ColorAdjustTypeCount = 5
    Global Const $ColorAdjustTypeAny = 6

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

    Global Const $ColorMatrixFlagsDefault = 0
    Global Const $ColorMatrixFlagsSkipGrays = 1
    Global Const $ColorMatrixFlagsAltGray = 2

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

    Global Const $UnitWorld = 0
    Global Const $UnitDisplay = 1
    Global Const $UnitPixel = 2
    Global Const $UnitPoint = 3
    Global Const $UnitInch = 4
    Global Const $UnitDocument = 5
    Global Const $UnitMillimeter = 6

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

    ; Structures and creation functions
    Global Const $tagColorMatrix = "float m1[5]; float m2[5]; float m3[5]; float m4[5]; float m5[5];"

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

    Func _GDIPlus_ColorMatrix( $m1_1, $m1_2, $m1_3, $m1_4, $m1_5, _
    $m2_1, $m2_2, $m2_3, $m2_4, $m2_5, _
    $m3_1, $m3_2, $m3_3, $m3_4, $m3_5, _
    $m4_1, $m4_2, $m4_3, $m4_4, $m4_5, _
    $m5_1, $m5_2, $m5_3, $m5_4, $m5_5 )
    ; Prog@ndy
    ; creates a GDIplus color Matrix
    Local $ColorMatrix = DllStructCreate($tagColorMatrix)
    For $r = 1 To 5
    For $c = 1 To 5
    DllStructSetData($ColorMatrix, $r, Eval("m" & $r & "_" & $c),$c)
    Next
    Next
    Return $ColorMatrix
    EndFunc

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

    Global Const $tagPointF = "float x; float y;"

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_PointFParallelogramm
    ; Description ...:
    ; Syntax.........: _GDIPlus_PointFParallelogramm($nULX, $nULY, $nURX, $nURY, $nLLX, $nLLY)
    ; Parameters ....: $nULX - The X coordinate of the upper left corner of the source image
    ; $nULY - The Y coordinate of the upper left corner of the source image
    ; $nURX - The X coordinate of the upper right corner of the source image
    ; $nURY - The Y coordinate of the upper right corner of the source image
    ; $nLLX - The X coordinate of the lower left corner of the source image
    ; $nLLY - The Y coordinate of the lower left corner of the source image
    ; Return values .: Success -
    ; Failure - 0
    ; Author ........: Malkey
    ; Modified ......: Prog@ndy
    ; Remarks .......:
    ; Related .......:
    ; Link ..........; @@MsdnLink@@
    ; Example .......;
    ; ===============================================================================================================================
    Func _GDIPlus_PointFParallelogramm($nULX, $nULY, $nURX, $nURY, $nLLX, $nLLY)

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

    Local $tPoint = DllStructCreate("float X;float Y;float X2;float Y2;float X3;float Y3")
    DllStructSetData($tPoint, "X", $nULX)
    DllStructSetData($tPoint, "Y", $nULY)
    DllStructSetData($tPoint, "X2", $nURX)
    DllStructSetData($tPoint, "Y2", $nURY)
    DllStructSetData($tPoint, "X3", $nLLX)
    DllStructSetData($tPoint, "Y3", $nLLY)
    Return $tPoint
    EndFunc

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_PointLParallelogramm
    ; Description ...:
    ; Syntax.........: _GDIPlus_PointLParallelogramm($nULX, $nULY, $nURX, $nURY, $nLLX, $nLLY)
    ; Parameters ....: $nULX - The X coordinate of the upper left corner of the source image
    ; $nULY - The Y coordinate of the upper left corner of the source image
    ; $nURX - The X coordinate of the upper right corner of the source image
    ; $nURY - The Y coordinate of the upper right corner of the source image
    ; $nLLX - The X coordinate of the lower left corner of the source image
    ; $nLLY - The Y coordinate of the lower left corner of the source image
    ; $count - Specifies the number of points (x,y)'s in the structure.
    ; Return values .: Success -
    ; Failure - 0
    ; Author ........: Malkey
    ; Modified ......: Prog@ndy
    ; Remarks .......:
    ; Related .......:
    ; Link ..........; @@MsdnLink@@
    ; Example .......;
    ; ===============================================================================================================================
    Func _GDIPlus_PointLParallelogramm($nULX, $nULY, $nURX, $nURY, $nLLX, $nLLY)
    Local $tPoint = DllStructCreate("int X;int Y;int X2;int Y2;int X3;int Y3")
    DllStructSetData($tPoint, "X", $nULX)
    DllStructSetData($tPoint, "Y", $nULY)
    DllStructSetData($tPoint, "X2", $nURX)
    DllStructSetData($tPoint, "Y2", $nURY)
    DllStructSetData($tPoint, "X3", $nLLX)
    DllStructSetData($tPoint, "Y3", $nLLY)
    Return $tPoint
    EndFunc

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

    ; Functions
    Func _GDIPlus_ImageAttributesCreate()
    ; Prog@ndy
    Local $aResult = DllCall($ghGDIpDLL, "int", "GdipCreateImageAttributes", "ptr*", 0)
    If @error Then Return SetError(1,@error,0)
    Return SetError($aResult[0],0,$aResult[1])
    EndFunc

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

    Func _GDIPlus_ImageAttributesDispose($pImageAttributes)
    ; Prog@ndy
    Local $aResult = DllCall($ghGDIpDLL, "int", "GdipDisposeImageAttributes", "ptr", $pImageAttributes)
    If @error Then Return SetError(1,@error,0)
    Return SetError($aResult[0],0,$aResult[0]=0)
    EndFunc
    Func _GDIPlus_ImageAttributesSetColorMatrix($pImageAttributes, $type, $enableFlag, $colorMatrix, $grayMatrix, $flags)
    ; Prog@ndy
    Local $aResult = DllCall($ghGDIpDLL, "int", "GdipSetImageAttributesColorMatrix", "ptr", $pImageAttributes, "int", $type, "int", $enableFlag, "ptr", $colorMatrix, "ptr", $grayMatrix,"int", $flags)
    If @error Then Return SetError(1,@error,0)
    Return SetError($aResult[0],0,$aResult[0]=0)
    EndFunc

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

    Func _GDIPlus_DrawImagePointsRect($graphics, $image, $points, $count, $srcx, $srcy, $srcwidth, $srcheight, $srcUnit, $imageAttributes, $callback=0, $callbackData=0)
    ; Prog@ndy
    Local $aResult = DllCall($ghGDIpDLL, "int", "GdipDrawImagePointsRect", "ptr", $graphics, "ptr", $image,"ptr", $points, "INT", $count, _
    "float", $srcx, "float", $srcy, "float", $srcwidth, "float", $srcheight, "int", $srcUnit, "ptr", $imageAttributes, "ptr", $callback, "ptr", $callbackData)
    If @error Then Return SetError(1,@error,0)
    Return SetError($aResult[0],0,$aResult[0]=0)
    EndFunc

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

    Func _GDIPlus_DrawImagePointsRectI($graphics, $image, $points, $count, $srcx, $srcy, $srcwidth, $srcheight, $srcUnit, $imageAttributes, $callback=0, $callbackData=0)
    ; Prog@ndy
    Local $aResult = DllCall($ghGDIpDLL, "int", "GdipDrawImagePointsRectI", "ptr", $graphics, "ptr", $image,"ptr", $points, "INT", $count, _
    "int", $srcx, "int", $srcy, "int", $srcwidth, "int", $srcheight, "int", $srcUnit, "ptr", $imageAttributes, "ptr", $callback, "ptr", $callbackData)
    If @error Then Return SetError(1,@error,0)
    Return SetError($aResult[0],0,$aResult[0]=0)
    EndFunc

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

    ; Author ........: Paul Campbell (PaulIA)
    ; Modified.......: Gary Frost, Prog@ndy
    Func _GDIPlus_GraphicsDrawImageRectRectAttr($hGraphics, $hImage, $iSrcX, $iSrcY, $iSrcWidth, $iSrcHeight, $iDstX, $iDstY, $iDstWidth, $iDstHeight, $iUnit = 2, $pImageAttributes=0)
    Local $aResult

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

    $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRectRectI", "ptr", $hGraphics, "ptr", $hImage, "int", $iDstX, "int", _
    $iDstY, "int", $iDstWidth, "int", $iDstHeight, "int", $iSrcX, "int", $iSrcY, "int", $iSrcWidth, "int", _
    $iSrcHeight, "int", $iUnit, "ptr", $pImageAttributes, "ptr", 0, "ptr", 0)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
    EndFunc ;==>_GDIPlus_GraphicsDrawImageRectRectAttr

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

    ;---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

    ; Example

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

    _GDIPlus_Startup()

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

    $hImg1 = _GDIPlus_ImageLoadFromFile("HINTERGRUNDBILD.jpg")
    $hImg2 = _GDIPlus_ImageLoadFromFile("TRANSPARENTER_VORDERGRUND.JPG")

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

    $hGraphics = _GDIPlus_ImageGetGraphicsContext($hImg1)

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

    $ImageAttributes = _GDIPlus_ImageAttributesCreate()

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

    $ColorMatrix = _GDIPlus_ColorMatrix( _
    1.0, 0.0, 0.0, 0.0, 0.0, _
    0.0, 1.0, 0.0, 0.0, 0.0, _
    0.0, 0.0, 1.0, 0.0, 0.0, _
    0.0, 0.0, 0.0, 0.5, 0.0, _ ; --> die 0.5 gibt die Transparenz an (0.5 = 50% sichtbar, 0.3= 30% sichtbar ...)
    0.0, 0.0, 0.0, 0.0, 1.0 _
    )

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

    _GDIPlus_ImageAttributesSetColorMatrix($ImageAttributes, $ColorAdjustTypeBitmap, 1, DllStructGetPtr($ColorMatrix), 0, $ColorMatrixFlagsDefault)

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

    _DrawImage($hGraphics, $hImg2, 10,10,$ImageAttributes)
    ;~ _DrawImage($hGraphics, $hImg2, 0,0,0)

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

    _GDIPlus_ImageSaveToFile($hImg1, @DesktopDir & "\test.jpg")

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

    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_ImageDispose($hImg1)
    _GDIPlus_ImageDispose($hImg2)

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

    $x2 = _GDIPlus_ImageAttributesDispose($ImageAttributes)

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

    Func _DrawImage($hGraphics, $hImage, $X, $Y, $pImageAttributes)
    ; Prog@ndy
    Local $H = _GDIPlus_ImageGetHeight($hImage)
    Local $W = _GDIPlus_ImageGetWidth($hImage)
    ;~ Local $tPoint = _GDIPlus_PointFParallelogramm($X, $Y, $X+$W, $Y, $X, $Y+$H)
    ;~ Local $Result = _GDIPlus_DrawImagePointsRect($hGraphics, $hImage, DllStructGetPtr($tPoint), 3, 0, 0, $W, $H, 2, $pImageAttributes)
    Local $Result = _GDIPlus_GraphicsDrawImageRectRectAttr($hGraphics, $hImage, 0, 0, $W, $H, $X, $Y, $W, $H, 2, $pImageAttributes)
    Return SetError(@error,0,$Result)
    EndFunc

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

    _GDIPlus_Shutdown()

    [/autoit]


    //Edit: Man, jetzt hab ich noch mal im engl. Forum gesucht und das gefunden: http://www.autoitscript.com/forum/index.php?showtopic=71513&hl=colormatrix

    Einmal editiert, zuletzt von progandy (8. Mai 2009 um 14:39)

  • Du musst bei den beiden _GDIPlus_ImageLoadFromFile den Pfad zu zwei Bildern eintragen ;)
    das ergebnis wird hier als test.jpg auf dem Desktop gespeichert.