animierte GIF-Bildfolge wiederholt sich nicht

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von tron25.

    animierte GIF-Bildfolge wiederholt sich nicht

    ausgelagert aus Tutorial: Animated Gif erstellen ~VaporiZed

    Hallo,
    vielen Dank für den Code. Ich habe ihn an meine Software angepaßt. Alles funktioniert prima. Allerdings wiederholt sich die Animation nicht selbständig. Was kann ich da tun? Die Animationen aus der Beispieldatei "Gifanimator.zip" werden automatisch wiederholt.
    Bilder
    • pferd.gif

      6,86 kB, 96×64, 366 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Hi
    Auch wenn die animierte GIF, wie im Tutorial gezeigt wird, funktioniert, ist es so nicht korrekt. Im Tutorial werden einfach Bilder hintereinander in eine GIF geschrieben. Normalerweise gehören zu jedem Bild in der GIF und für die animierte GIF selber zusätzliche Informationen (Blocks/Extension/Descriptor) die diverse Sachen Beschreiben. zB. wie lange ein Bild angezeigt werden soll, wie oft die Animation wiedergegeben werden soll bzw ob eine Endloswiedergabe erfolgen soll, Position und Größe der einzelnen Bilder, wie die Bilder gezeichnet werden sollen (nächstes Bild komplett anzeigen oder auf das alte Bild drüber zeichnen usw) und weitere Informationen. Du kannst natürlich entsprechende Informationen mit in den Stream schreiben. Eventuell sind auch entsprechende Funktionen im Namespace System.Windows.Media dafür vorhanden (glaub da wird ja die "Windows Imaging Component" verwendet). Du könntest ja mal in diesem Namespace nach einem MetadataQueryWriter suchen. Ansonsten hätte ich nur ein VB6 Beispiel wie man mit der "Windows Imaging Component" ein animiertes GIF erzeugt. Hier findes Du eine Beschreibung wie eine animierte GIF aufgebaut ist: w3.org/Graphics/GIF/spec-gif89a.txt Ansonsten dürftest Du auch in der MS-Doku oder Internet etwas finden wie man eine animierte GIF mit der "Windows Imaging Component" bzw über den Namespace System.Windows.Media erstellt.
    Mfg -Franky-
    @-Franky- Genau genommen gibt es mindestens 3 Sorten von GIF-Dateien, die mehr oder weniger Animierungs-Information enthalten.
    Der komplementäre Aufwand muss dann beim Einbetten von GIFs betrieben werden.
    @tron25 Im IrfanView wiehert das Pferd pausenlos.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Es könnte durchaus sein, das mit Deinem Code Standard-Blocks geschrieben werden. Dazu müsste man sich die GIF im HexEditor ansehen. Es wäre auch denkbar das der Browser oder auch andere Programme hier einfach die Standardwerte nehmen falls keine in der GIF vorhanden sind. Ich kenne das halt nur über den MetadataQueryWriter bzw man schreibt selbst die Daten in den Stream. Wie hier auch zu sehen: pixcl.com/oldsite/WIC-and-Animated-GIF-Files.htm

    Edit: Warum verwendest Du keinen PixelFormat-Konverter in Deinem Code? Was ich mein ist, WIC konvertiert das Quell-PixelFormat automatisch zum Ziel-PixelFormat GIF (8bppIndexed = 256Farben). Allerdings wird dabei eine Standard- oder Halftone256 Palette verwendet. TrueColor Bilder sehen dann als GIF nicht besonders schön aus. Wenn Du bessere Ergebnisse erzeugen möchtest, konvertierst Du das Quellbild vor dem hinzufügen zum GIF-Encoder mit einem PixelFormatConverter wobei Du den PaletteTypeOptimal verwendest. PaletteTypeErrorDiffusion ginge auch, ist aber Geschmackssache. Quellbilder im (P)ARGB Format ist wieder eine andere Geschichte da nur eine Farbe aus der GIF-Palette transparent sein kann (pro GIF-Bild in der animierten GIF).

    @tron25 Es gibt immer noch den "Microsoft GIF Animator 1.0" zum Download. Den kannst Du verwenden um animierte GIFs zu erstellen oder auch um animierte GIFs zu bearbeiten. Schau doch damit mal Deine GIF an und prüfe dort welcher Wert für den Loop eingestellt ist.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „-Franky-“ ()

    -Franky- schrieb:

    mit Deinem Code
    Das ist ja nun schon ein paar Tage her, ich wollte das einfach mal probieren und habe später die anderen Möglichkeiten kennen gelernt.
    Da ich üblicherweise nichts mit animierten GIFs zu tun habe, habe ich da aufgehört.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke, erst einmal für eure Tipps und Infos.

    Ich habe mir den Microsoft GIF Animator heruntergeladen und darin meine GIF geöffnet. Leider ist das Programm nicht ganz barrierefrei. Daher habe ich etwas gebraucht, bis ich die Datei öffnen konnte. Weil Ich stark sehbehindert bin, arbeite ich daher mit einem Screenreader. Bei dem Programm sind die Schalter für Öffnen und Speichern nicht mit der TAB-Taste erreichbar.

    "Loop" war nicht angehakt. Ich habe es aktiviert und als Anzahl "Forever" ausgewählt. Nach dem Speichern rennt das Pferd auch ohne Ende.

    Was die Qualität angeht, muß sie nicht sehr gut sein, da die Grafik nur zweifarbig ist und aus Punkten besteht.

    Ich habe eine Software geschrieben, mit der herkömmliche Grafiken in Braille für Blinde umgewandelt werden. Diese können dann entweder mit speziellen Braillezeilen bzw. Brailledisplays abgetastet werden oder über einen Brailledrucker in Blindenschrift ausgedruckt werden. Ich habe eine Möglichkeit gefunden, bewegte Bilder zum Tasten zu erstellen. Nun wollte ich ein solches Bild zum Versenden per beispielsweise Mail in eine GIF exportieren. Damit kann ich weitere Animationen an sehende Kollegen schicken, die mein Programm nicht installiert haben.

    Was die zusätzlichen Informationen im Stream angeht, habe ich folgende Funktion gefunden:

    VB.NET-Quellcode

    1. System.Windows.Media.Animation.RepeatBehavior


    Leider stehe ich da ein wenig auf dem Schlauch, wie ich das dem Stream hinzufügen kann.

    Ich habe mir auch die Beschreibung angeschaut, auf die -Franky- verwiesen hat. Ich werde mal im Netz nach "Windows Media" und "Animationen" suchen.

    Ihr findet unten drei weitere Grafiken und ihr dürft mal raten, was das sein soll.
    Bilder
    • Grafik 1.gif

      963,57 kB, 992×1.424, 36 mal angesehen
    • Grafik 2.gif

      239,9 kB, 408×592, 27 mal angesehen
    • Grafik 3.gif

      229,02 kB, 376×592, 23 mal angesehen

    tron25 schrieb:

    was das sein soll.


    Sind verbrennungsprozesse von Motoren dargestellt. Da auf Bild 2 und 3 keine Zündkerze zu erkennen ist, glaube ich du zeigst den Unterschied zwischen Benzin und Dieselmotor, sollte dem so sein, könntest du auch noch einen Wankelmotor hinzufügen.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    tron25 schrieb:

    Ich habe mir den Microsoft GIF Animator heruntergeladen und darin meine GIF geöffnet. Leider ist das Programm nicht ganz barrierefrei.

    Das Programm ist schon sehr alt und da hat man noch nicht auf Barrierefreiheit geachtet. Dafür läuft das Programm heute noch. System.Windows.Media.Animation.RepeatBehavior dürfte nicht das richtige sein. Was einem WIC MetadataQueryWriter am nächsten kommt, könnte im Namespace System.Windows.Media.Imaging der InPlaceBitmapMetadataWriter, BitmapMetadata oder BitmapMetadataBlob sein. Wenn ich das richtig im Hinterkopf habe, ist der Namespace System.Windows.Media.Imaging Teil von WPF (nutzt ebenfalls WIC). Da könnten Dir evtl auch WPF Experten was zu sagen können wie das mit dem schreiben entsprechender Metadaten für animierte GIFs funktioniert bzw das man auch nach WPF Beispielen zum Erstellen von animierten GIFs ausschau halten müsste.

    Alternativ wäre es auch möglich WIC direkt zu verwenden. WIC stellt neben den ganzen COM-Interfaces zum Teil auch entsprechende Proxy-APIs bereit. Ist dann allerdings etwas aufwendiger zu programmieren. Grob überschlagen, ca 15 - 20 APIs + ein paar Const, Enums und Structs. Eventuell gibt es auch ein passendes Nuget-Paket zur "Windows Imaging Component".
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Vielen Dank für die Hinweise, aber ganz ehrlich gesagt, klingt das sehr kompliziert. Da muß ich mich erst einmal ordentlich hineinlesen.

    Ja, es sind Verbrennungsprozesse. Den Wankelmotor werde ich auch noch erstellen. Allerdings muß ich ihn erst selbst so verstehen, dass ich mir im Geist ein Bild davon machen kann. Ich habe mir Erklärungen angehört und in der Theorie ist mir das schon klar, aber das Visuelle bereitet mir noch ein paar Schwierigkeiten.

    Ich denke aber, das dieses Thema nicht in dieses Forum paßt.
    Eigentlich wollte ich das nicht, weil ich gerne selbst meinen Code erarbeite, aber ich habe doch mal ChatGPT befragt.
    Zum Thema "Animiertes PNG" sollte ich u.a. die APNG-Bibliothek meinem Projekt hinzufügen. Diese konnte ich aber nirgends finden, weder über Google, noch über den Verweismanager in VS.

    Zu "Animierte GIF" habe ich folgenden Code bekommen:

    ----------

    Um in Visual Basic .NET Bilder zu einer animierten GIF zu exportieren, kannst du die `System.Drawing`-Bibliothek verwenden. Hier ist ein grundlegendes Beispiel, wie du dies erreichen kannst:

    1. **Bilder laden**: Lade die Bilder, die du animieren möchtest.
    2. **GIF erstellen**: Verwende die `Image`-Klasse und `FrameDimension`-Klasse, um die Bilder zu einer GIF-Datei zu kombinieren.

    Hier ist ein Beispielcode:

    VB.NET-Quellcode

    1. Imports System.Drawing
    2. Imports System.Drawing.Imaging
    3. Module Module1
    4. Sub Main()
    5. ' Bilder laden
    6. Dim images As New List(Of Image) From {
    7. Image.FromFile("bild1.png"),
    8. Image.FromFile("bild2.png"),
    9. Image.FromFile("bild3.png")
    10. }
    11. ' Erste Bild als Basis für die GIF-Datei verwenden
    12. Dim gif As Image = images(0)
    13. Dim encoder As ImageCodecInfo = GetEncoder(ImageFormat.Gif)
    14. Dim encoderParams As New EncoderParameters(1)
    15. encoderParams.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.MultiFrame))
    16. ' GIF-Datei erstellen
    17. gif.Save("animiert.gif", encoder, encoderParams)
    18. ' Weitere Bilder hinzufügen
    19. encoderParams.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.FrameDimensionTime))
    20. For i As Integer = 1 To images.Count - 1
    21. gif.SaveAdd(images(i), encoderParams)
    22. Next
    23. ' GIF-Datei abschließen
    24. encoderParams.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.Flush))
    25. gif.SaveAdd(encoderParams)
    26. End Sub
    27. Private Function GetEncoder(format As ImageFormat) As ImageCodecInfo
    28. Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageDecoders()
    29. For Each codec As ImageCodecInfo In codecs
    30. If codec.FormatID = format.Guid Then
    31. Return codec
    32. End If
    33. Next
    34. Return Nothing
    35. End Function
    36. End Module


    ----------

    Leider bekomme ich in der Zeile

    encoderParams.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.MultiFrame))

    den folgenden Fehler:

    "SaveFlag" ist kein Member von "ImageCodecInfo".

    Leider finde ich keine andere Eigenschaft von "encoder", die passen könnte.

    Hat jemand von euch eine Idee, woran das liegt?

    CodeTags gesetzt ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    tron25 schrieb:

    Zum Thema "Animiertes PNG" sollte ich u.a. die APNG-Bibliothek meinem Projekt hinzufügen. Diese konnte ich aber nirgends finden, weder über Google, noch über den Verweismanager in VS.
    Wenn du bei Google nach APNG nuget suchst, bekommst du eine ganze Auswahl an Bibliotheken, die du testen kannst.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Da Du Encoder als Variablenname verwendest, kann der Compiler nicht mehr erkennen, was Du meinst. Syntaktisch richtig wäre also nicht Encoder.SaveFlag, sondern System.Drawing.Imaging.Encoder.SaveFlag
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @tron25 APNG (animierte PNG) ist aber was anderes als eine animierte GIF. Da du sowieso nur 2 Farben (schwarz und weiß) verwendest, macht APNG wenig Sinn. APNG macht Sinn wenn Du Bilder im TrueColor-Format bzw mit mehr als 256 Farben animieren möchtest. APNG wird auch nicht von einigen Programmen oder Browser unterstützt. Zu Deinem Code bzw. zu dem was ChatGPT sich da zusammengesponnen hat: GDI+ bzw. der Namespace System.Drawing kann keine animierte GIFs erstellen. Nur lesen. EncoderValue.MultiFrame ist nur zum erstellen von Multiframe-TIFFs gedacht.
    Mfg -Franky-
    So, nun habe ich folgenden Code:

    VB.NET-Quellcode

    1. Try
    2. ' Bilder laden
    3. Dim images As New List(Of system.Drawing.Image)
    4. For Each Bild As String In Directory.GetFiles(Verzeichnis)
    5. images.Add(System.Drawing.Image.FromFile(Bild))
    6. Next
    7. ' Erste Bild als Basis für die GIF-Datei verwenden
    8. Dim gif As System.Drawing.Image = images(0)
    9. Dim encoder As ImageCodecInfo = GetEncoder(System.Drawing.Imaging.ImageFormat.Gif)
    10. Dim encoderParams As New EncoderParameters(1)
    11. encoderParams.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, CLng(EncoderValue.MultiFrame))
    12. ' GIF-Datei erstellen
    13. gif.Save(DateiSpeichernDialog.FileName, encoder, encoderParams)
    14. ' Weitere Bilder hinzufügen
    15. encoderParams.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, CLng(EncoderValue.FrameDimensionTime))
    16. For i As Integer = 1 To images.Count - 1
    17. gif.SaveAdd(images(i), encoderParams)
    18. Next
    19. ' GIF-Datei abschließen
    20. encoderParams.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, CLng(EncoderValue.Flush))
    21. gif.SaveAdd(encoderParams)
    22. Catch Fehler As Exception
    23. InfoFormular.Text = My.Resources.Fehler
    24. InfoFormular.InfoLabel.Text = My.Resources.GIF_zu_gross
    25. InfoFormular.ShowDialog()
    26. End Try

    Bei mir läuft die Animation nur einmal durch.
    Wenn die Bilder sehr groß sind, bekomme ich den Fehler, daß der Speicher zu klein sei. Diesen Fehler habe ich mit einem TRY-CATCH abgefangen.
    Bilder
    • Motor.gif

      6,91 kB, 376×592, 148 mal angesehen
    @tron25 Wenn Du Dir Deine GIF mal im HexEditor anschaust, dann wirst Du feststellen das am Anfang "GIF87a" oder "GIF89a" steht. Kurz danach sollte "NETSCAPE2.0" stehen und dahinter kommt der Block, der eine GIF zu einer animierten GIF macht. Wenn nicht, ist das keine konforme bzw. valide animierte GIF. Ich habe mal auf die schnelle, daher sehr wüst und verbesserbar, fix was mit WIC zusammen gebastelt bzw aus meinem VB6 Programm dazu übersetzt. Ich nutze hier GDI+ Funktionen, die nicht in .NET vorhanden sind, um ein Bild in ein 8bppIndexed-Format zu konvertieren. Das ersparrt Dir noch mehr WIC APIs zum konvertieren. Außerdem habe ich mich auf die schnelle für die WIC-Proxy-APIs entschieden da diese nur mit den Pointer auf die Interfaces arbeiten und so nicht extra Objekte erzeugt und entsorgt werden müssen. Mit den COM-Interfaces wäre es zwar übersichtlicher, das Ergebnis wäre aber das gleiche. Hoffe, wegen der schnelle, das der LoopCount so korrekt ist. Hab das nicht weiter ausprobiert da LoopCount = 0 eine Endloswiedergabe macht.

    Als erstes benötigst Du ein Modul "BitmapExtensions"
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Reflection
    2. Imports System.Drawing.Imaging
    3. Imports System.Runtime.CompilerServices
    4. Imports System.Runtime.InteropServices
    5. Module BitmapExtensions
    6. #Region "APIs"
    7. <DllImport("gdiplus.dll", EntryPoint:="GdipInitializePalette")>
    8. Private Function GdipInitializePalette(<[In]> pPalette As Integer(),
    9. <[In]> ePaletteType As PaletteType,
    10. <[In]> optimalColors As Integer,
    11. <[In], MarshalAs(UnmanagedType.Bool)> useTransparentColor As Boolean,
    12. <[In]> pBitmap As IntPtr) As Integer
    13. End Function
    14. <DllImport("gdiplus.dll", EntryPoint:="GdipBitmapConvertFormat")>
    15. Private Function GdipBitmapConvertFormat(<[In]> pInBitmap As IntPtr,
    16. <[In]> ePixelFormat As PixelFormat,
    17. <[In]> eDitherType As DitherType,
    18. <[In]> ePaletteType As PaletteType,
    19. <[In]> pPalette As Integer(),
    20. <[In]> alphaThresholdPercent As Single) As Integer
    21. End Function
    22. #End Region
    23. #Region "Const"
    24. Private Const Gdip_OK As Integer = &H0
    25. #End Region
    26. #Region "Enums"
    27. Private Enum DitherType As Integer
    28. DitherTypeNone = 0
    29. DitherTypeSolid = 1
    30. DitherTypeOrdered4x4 = 2
    31. DitherTypeOrdered8x8 = 3
    32. DitherTypeOrdered16x16 = 4
    33. DitherTypeSpiral4x4 = 5
    34. DitherTypeSpiral8x8 = 6
    35. DitherTypeDualSpiral4x4 = 7
    36. DitherTypeDualSpiral8x8 = 8
    37. DitherTypeErrorDiffusion = 9
    38. End Enum
    39. Private Enum PaletteType As Integer
    40. PaletteTypeCustom = 0
    41. PaletteTypeOptimal = 1
    42. PaletteTypeFixedBW = 2
    43. PaletteTypeFixedHalftone8 = 3
    44. PaletteTypeFixedHalftone27 = 4
    45. PaletteTypeFixedHalftone64 = 5
    46. PaletteTypeFixedHalftone125 = 5
    47. PaletteTypeFixedHalftone216 = 7
    48. PaletteTypeFixedHalftone252 = 8
    49. PaletteTypeFixedHalftone256 = 9
    50. End Enum
    51. #End Region
    52. #Region "Functions"
    53. Private Function CreateGdipPalette(flag As PaletteFlags,
    54. entries As Integer) As Integer()
    55. Dim Ret As Integer() = New Integer(entries + 2 - 1) {}
    56. Ret(0) = flag
    57. Ret(1) = entries
    58. Return Ret
    59. End Function
    60. #End Region
    61. #Region "Extensions"
    62. <Extension>
    63. Private Function NativeHandle(bitmap As Bitmap) As IntPtr
    64. Return bitmap.GetPrivateField(Of IntPtr)("nativeImage")
    65. End Function
    66. <Extension>
    67. Private Function GetPrivateField(Of TResult)(Obj As Object, FieldName As String) As TResult
    68. Dim Ret As TResult = Nothing
    69. If Obj IsNot Nothing Then
    70. Dim FieldInfo As FieldInfo = Obj.GetType.GetField(FieldName,
    71. BindingFlags.GetField Or
    72. BindingFlags.Instance Or
    73. BindingFlags.NonPublic)
    74. If FieldInfo IsNot Nothing Then
    75. Ret = DirectCast(FieldInfo.GetValue(Obj), TResult)
    76. End If
    77. End If
    78. Return Ret
    79. End Function
    80. <Extension>
    81. Public Sub ConvertTo8bppIndexed(bitmap As Bitmap)
    82. If bitmap IsNot Nothing Then
    83. Dim pBitmap As IntPtr = bitmap.NativeHandle
    84. Dim entries As Integer = 256
    85. Dim paletteType As PaletteType = PaletteType.PaletteTypeOptimal
    86. Dim ditherType As DitherType = DitherType.DitherTypeErrorDiffusion
    87. Dim palette As Integer() = CreateGdipPalette(PaletteFlags.GrayScale, entries)
    88. If GdipInitializePalette(palette, paletteType, entries, False, pBitmap) = Gdip_OK Then
    89. If GdipBitmapConvertFormat(pBitmap, PixelFormat.Format8bppIndexed,
    90. ditherType, paletteType, palette, 50) = Gdip_OK Then
    91. End If
    92. End If
    93. End If
    94. End Sub
    95. #End Region
    96. End Module



    Dann benötigst Du eine Klasse "AnimGifCreator"
    Spoiler anzeigen

    Quellcode

    1. Imports System.IO
    2. Imports System.Text
    3. Imports System.Runtime.InteropServices
    4. Public Class AnimGifCreator
    5. Implements IDisposable
    6. #Region "APIs"
    7. <DllImport("Shlwapi.dll", EntryPoint:="SHCreateStreamOnFileEx")>
    8. <PreserveSig> Private Shared Function CreateStreamOnFile(<[In], MarshalAs(UnmanagedType.LPWStr)> pszFile As String,
    9. <[In]> grfMode As STGM,
    10. <[In]> dwAttributes As Integer,
    11. <[In], MarshalAs(UnmanagedType.Bool)> fCreate As Boolean,
    12. <[In]> pstmTemplate As IntPtr,
    13. <Out> ByRef ppstm As IntPtr) As Integer
    14. End Function
    15. <DllImport("Windowscodecs.dll", EntryPoint:="WICCreateImagingFactory_Proxy")>
    16. <PreserveSig> Private Shared Function CreateWicImagingFactory(<[In]> SDKVersion As UInteger,
    17. <Out> ByRef ppIImagingFactory As IntPtr) As Integer
    18. End Function
    19. <DllImport("Windowscodecs.dll", EntryPoint:="IWICImagingFactory_CreateBitmapFromHBITMAP_Proxy")>
    20. <PreserveSig> Private Shared Function CreateWicBitmapFromHBITMAP(<[In]> pIImagingFactory As IntPtr,
    21. <[In]> hBitmap As IntPtr,
    22. <[In]> hPalette As IntPtr,
    23. <[In]> options As WICBitmapAlphaChannelOption,
    24. <Out> ByRef ppIBitmap As IntPtr) As Integer
    25. End Function
    26. <DllImport("Windowscodecs.dll", EntryPoint:="IWICImagingFactory_CreateEncoder_Proxy")>
    27. <PreserveSig> Private Shared Function CreateWicEncoder(<[In]> pIImagingFactory As IntPtr,
    28. <[In]> ByRef guidContainerFormat As Guid,
    29. <[In]> pguidVendor As IntPtr,
    30. <Out> ByRef ppIEncoder As IntPtr) As Integer
    31. End Function
    32. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapEncoder_Initialize_Proxy")>
    33. <PreserveSig> Private Shared Function InitializeWicEncoder(<[In]> pIEncoder As IntPtr,
    34. <[In]> pIStream As IntPtr,
    35. <[In]> cacheOption As WICBitmapEncoderCacheOption) As Integer
    36. End Function
    37. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapEncoder_CreateNewFrame_Proxy")>
    38. <PreserveSig> Private Shared Function CreateNewWicFrameEncode(<[In]> pIEncoder As IntPtr,
    39. <Out> ByRef ppIFrameEncode As IntPtr,
    40. <Out> ByRef ppIEncoderOptions As IntPtr) As Integer
    41. End Function
    42. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapFrameEncode_Initialize_Proxy")>
    43. <PreserveSig> Private Shared Function InitializeWicFrameEncode(<[In]> pIFrameEncode As IntPtr,
    44. <[In]> pIEncoderOptions As IntPtr) As Integer
    45. End Function
    46. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapFrameEncode_WriteSource_Proxy")>
    47. <PreserveSig> Private Shared Function WriteWicBitmapToFrameEncode(<[In]> pIFrameEncode As IntPtr,
    48. <[In]> pIBitmapSource As IntPtr,
    49. <[In]> prc As IntPtr) As Integer
    50. End Function
    51. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapFrameEncode_SetSize_Proxy")>
    52. <PreserveSig> Private Shared Function SetWicBitmapFrameEncodeSize(<[In]> pIFrameEncode As IntPtr,
    53. <[In]> uiWidth As Integer,
    54. <[In]> uiHeight As Integer) As Integer
    55. End Function
    56. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapFrameEncode_Commit_Proxy")>
    57. <PreserveSig> Private Shared Function CommitWicFrameEncode(<[In]> pIFrameEncode As IntPtr) As Integer
    58. End Function
    59. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapEncoder_Commit_Proxy")>
    60. <PreserveSig> Private Shared Function CommitWicEncoder(<[In]> pIEncoder As IntPtr) As Integer
    61. End Function
    62. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapEncoder_GetMetadataQueryWriter_Proxy")>
    63. <PreserveSig> Private Shared Function GetWicMetadataQueryWriter(<[In]> pIEncoder As IntPtr,
    64. <Out> ByRef ppIMetadataQueryWriter As IntPtr) As Integer
    65. End Function
    66. <DllImport("Windowscodecs.dll", EntryPoint:="IWICBitmapFrameEncode_GetMetadataQueryWriter_Proxy")>
    67. <PreserveSig> Private Shared Function GetWicBitmapFrameEncodeMetadataQueryWriter(<[In]> pIFrameEncode As IntPtr,
    68. <Out> ByRef ppIMetadataQueryWriter As IntPtr) As Integer
    69. End Function
    70. <DllImport("Windowscodecs.dll", EntryPoint:="IWICMetadataQueryWriter_SetMetadataByName_Proxy")>
    71. <PreserveSig> Private Shared Function SetWicMetadataByName(<[In]> pIMetadataQueryWriter As IntPtr,
    72. <[In], MarshalAs(UnmanagedType.LPWStr)> wzName As String,
    73. <[In]> ByRef pvarValue As PROPVARIANT) As Integer
    74. End Function
    75. #End Region
    76. #Region "Const"
    77. Private Const S_OK As Integer = &H0
    78. Private Const WINCODEC_SDK_VERSION2 As UInteger = &H237
    79. Private Const GUID_ContainerFormatGif As String = "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5"
    80. #End Region
    81. #Region "Enums"
    82. Private Enum STGM As Integer
    83. STGM_FAILIFTHERE = &H0
    84. STGM_DIRECT = &H0
    85. STGM_READ = &H0
    86. STGM_WRITE = &H1
    87. STGM_READWRITE = &H2
    88. STGM_SHARE_EXCLUSIVE = &H10
    89. STGM_SHARE_DENY_WRITE = &H20
    90. STGM_SHARE_DENY_READ = &H30
    91. STGM_SHARE_DENY_NONE = &H40
    92. STGM_CREATE = &H1000
    93. STGM_TRANSACTED = &H10000
    94. STGM_CONVERT = &H20000
    95. STGM_PRIORITY = &H40000
    96. STGM_NOSCRATCH = &H100000
    97. STGM_NOSNAPSHOT = &H200000
    98. STGM_DIRECT_SWMR = &H400000
    99. STGM_SIMPLE = &H8000000
    100. STGM_DELETEONRELEASE = &H4000000
    101. End Enum
    102. Private Enum WICBitmapAlphaChannelOption As Integer
    103. WICBitmapUseAlpha = &H0
    104. WICBitmapUsePremultipliedAlpha = &H1
    105. WICBitmapIgnoreAlpha = &H2
    106. End Enum
    107. Private Enum WICBitmapEncoderCacheOption As Integer
    108. WICBitmapEncoderCacheInMemory = &H0
    109. WICBitmapEncoderCacheTempFile = &H1
    110. WICBitmapEncoderNoCache = &H2
    111. End Enum
    112. Private Enum VARENUM As UShort
    113. VT_EMPTY = 0
    114. VT_NULL = 1
    115. VT_I2 = 2
    116. VT_I4 = 3
    117. VT_R4 = 4
    118. VT_R8 = 5
    119. VT_CY = 6
    120. VT_DATE = 7
    121. VT_BSTR = 8
    122. VT_DISPATCH = 9
    123. VT_ERROR = 10
    124. VT_BOOL = 11
    125. VT_VARIANT = 12
    126. VT_UNKNOWN = 13
    127. VT_DECIMAL = 14
    128. VT_I1 = 16
    129. VT_UI1 = 17
    130. VT_UI2 = 18
    131. VT_UI4 = 19
    132. VT_I8 = 20
    133. VT_UI8 = 21
    134. VT_INT = 22
    135. VT_UINT = 23
    136. VT_VOID = 24
    137. VT_HRESULT = 25
    138. VT_PTR = 26
    139. VT_SAFEARRAY = 27
    140. VT_CARRAY = 28
    141. VT_USERDEFINED = 29
    142. VT_LPSTR = 30
    143. VT_LPWSTR = 31
    144. VT_RECORD = 36
    145. VT_FILETIME = 64
    146. VT_BLOB = 65
    147. VT_STREAM = 66
    148. VT_STORAGE = 67
    149. VT_STREAMED_OBJECT = 68
    150. VT_STORED_OBJECT = 69
    151. VT_BLOB_OBJECT = 70
    152. VT_CF = 71
    153. VT_CLSID = 72
    154. VT_TYPEMASK = 4095
    155. VT_ILLEGALMASKED = 4095
    156. VT_VECTOR = 4096
    157. VT_ARRAY = 8192
    158. VT_BYREF = 16384
    159. VT_RESERVED = 32768
    160. VT_ILLEGAL = 65535
    161. End Enum
    162. #End Region
    163. #Region "Class"
    164. Public Sub New()
    165. If CreateWicImagingFactory(WINCODEC_SDK_VERSION2,
    166. m_pIWicImagingFactory) <> S_OK Then
    167. ' Error
    168. End If
    169. End Sub
    170. #End Region
    171. #Region "Structs"
    172. Private Structure CArray
    173. Dim cElems As Integer
    174. Dim pElems As IntPtr
    175. End Structure
    176. <StructLayout(LayoutKind.Explicit, Size:=16)>
    177. Private Structure PROPVARIANT
    178. <FieldOffset(0)> Dim vt As VARENUM
    179. <FieldOffset(2)> Dim wReserved1 As UShort
    180. <FieldOffset(4)> Dim wReserved2 As UShort
    181. <FieldOffset(6)> Dim wReserved3 As UShort
    182. <FieldOffset(8)> Dim ui2 As UShort
    183. <FieldOffset(8)> Dim array As CArray
    184. End Structure
    185. #End Region
    186. #Region "Variable"
    187. Private m_DisposedValue As Boolean
    188. Private ReadOnly m_pIWicImagingFactory As IntPtr
    189. Private ReadOnly m_Bitmaps As New List(Of Bitmap)
    190. #End Region
    191. #Region "Functions"
    192. Public Function CreateAnimGif(animGifFile As String) As Boolean
    193. Dim Ret As Boolean
    194. If Not String.IsNullOrEmpty(animGifFile) AndAlso m_pIWicImagingFactory <> IntPtr.Zero AndAlso m_Bitmaps.Count > 0 Then
    195. Dim pIStream As IntPtr
    196. Dim pIWicEncoder As IntPtr = CreateGifEncoder(animGifFile, pIStream)
    197. If pIStream <> IntPtr.Zero Then
    198. If pIWicEncoder <> IntPtr.Zero Then
    199. ' optional
    200. ' Signatur = GIF87a oder GIF89a
    201. ' Standard wird GIF89a geschrieben, auch ohne diese Funktion.
    202. WriteGifSignature(pIWicEncoder)
    203. ' erforderlich!!!
    204. ' Metadaten für den Application Extension Block und LoopCount schreiben
    205. ' Loop = 0 (endlos Loop), max = 65535
    206. WriteGifAppExtAndLoopCount(pIWicEncoder, 0)
    207. For Each bitmap In m_Bitmaps
    208. Dim pIPropertyBag2 As IntPtr
    209. Dim pIWicFrameEncode As IntPtr
    210. If CreateNewWicFrameEncode(pIWicEncoder,
    211. pIWicFrameEncode,
    212. pIPropertyBag2) = S_OK Then
    213. If InitializeWicFrameEncode(pIWicFrameEncode,
    214. pIPropertyBag2) = S_OK Then
    215. If SetWicBitmapFrameEncodeSize(pIWicFrameEncode,
    216. bitmap.Width,
    217. bitmap.Height) = S_OK Then
    218. ' FrameDelay, 0 = Standard 100ms, min = 1 (10ms), max = 65535 (655350ms)
    219. WriteGifFrameDelay(pIWicFrameEncode, 0)
    220. Dim pIBitmap As IntPtr
    221. If CreateWicBitmapFromHBITMAP(m_pIWicImagingFactory,
    222. bitmap.GetHbitmap,
    223. Nothing,
    224. WICBitmapAlphaChannelOption.WICBitmapIgnoreAlpha,
    225. pIBitmap) = S_OK Then
    226. If WriteWicBitmapToFrameEncode(pIWicFrameEncode, pIBitmap, Nothing) = S_OK Then
    227. Ret = True
    228. Else
    229. Ret = False
    230. End If
    231. Marshal.Release(pIBitmap)
    232. End If
    233. End If
    234. CommitWicFrameEncode(pIWicFrameEncode)
    235. Marshal.Release(pIWicFrameEncode)
    236. Marshal.Release(pIPropertyBag2)
    237. End If
    238. End If
    239. If Ret = False Then Exit For
    240. Next
    241. CommitWicEncoder(pIWicEncoder)
    242. Marshal.Release(pIWicEncoder)
    243. End If
    244. Marshal.Release(pIStream)
    245. End If
    246. End If
    247. If Not Ret AndAlso File.Exists(animGifFile) Then
    248. File.Delete(animGifFile)
    249. End If
    250. Return Ret
    251. End Function
    252. Private Function CreateGifEncoder(animGifFile As String, ByRef pIStream As IntPtr) As IntPtr
    253. Dim Ret As IntPtr
    254. If CreateStreamOnFile(animGifFile,
    255. STGM.STGM_CREATE Or STGM.STGM_WRITE,
    256. 0, False, Nothing, pIStream) = S_OK Then
    257. Dim pIWicEncoder As IntPtr
    258. If CreateWicEncoder(m_pIWicImagingFactory,
    259. New Guid(GUID_ContainerFormatGif),
    260. Nothing, pIWicEncoder) = S_OK Then
    261. If InitializeWicEncoder(pIWicEncoder, pIStream,
    262. WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache) = S_OK Then
    263. Ret = pIWicEncoder
    264. End If
    265. End If
    266. End If
    267. Return Ret
    268. End Function
    269. Private Function WriteGifSignature(pIWicEncoder As IntPtr) As Boolean
    270. Dim Ret As Boolean
    271. If pIWicEncoder <> IntPtr.Zero Then
    272. Dim pIWicMetadataQueryWriter As IntPtr
    273. If GetWicMetadataQueryWriter(pIWicEncoder, pIWicMetadataQueryWriter) = S_OK Then
    274. Dim metaName As String = "/logscrdesc/Signature"
    275. Dim metaBytes() = Encoding.ASCII.GetBytes("GIF87a")
    276. Dim propVariant As New PROPVARIANT
    277. Dim pinnedArray As GCHandle = GCHandle.Alloc(metaBytes, GCHandleType.Pinned)
    278. With propVariant
    279. .vt = VARENUM.VT_UI1 Or VARENUM.VT_VECTOR
    280. .array.cElems = metaBytes.Length
    281. .array.pElems = pinnedArray.AddrOfPinnedObject
    282. End With
    283. If SetWicMetadataByName(pIWicMetadataQueryWriter, metaName, propVariant) = S_OK Then
    284. Ret = True
    285. End If
    286. pinnedArray.Free()
    287. Marshal.Release(pIWicMetadataQueryWriter)
    288. End If
    289. End If
    290. Return Ret
    291. End Function
    292. Private Function WriteGifAppExtAndLoopCount(pIWicEncoder As IntPtr,
    293. Optional LoopCount As UShort = 0) As Boolean
    294. Dim Ret As Boolean
    295. If pIWicEncoder <> IntPtr.Zero Then
    296. Dim pIWicMetadataQueryWriter As IntPtr
    297. If GetWicMetadataQueryWriter(pIWicEncoder, pIWicMetadataQueryWriter) = S_OK Then
    298. Dim metaName As String = "/appext/Application"
    299. Dim metaBytes() = Encoding.ASCII.GetBytes("NETSCAPE2.0")
    300. Dim propVariant As New PROPVARIANT
    301. Dim pinnedArray As GCHandle = GCHandle.Alloc(metaBytes, GCHandleType.Pinned)
    302. With propVariant
    303. .vt = VARENUM.VT_UI1 Or VARENUM.VT_VECTOR
    304. .array.cElems = metaBytes.Length
    305. .array.pElems = pinnedArray.AddrOfPinnedObject
    306. End With
    307. If SetWicMetadataByName(pIWicMetadataQueryWriter, metaName, propVariant) = S_OK Then
    308. Ret = True
    309. End If
    310. pinnedArray.Free()
    311. If LoopCount < 0 Then LoopCount = 0
    312. If LoopCount > 65535 Then LoopCount = 65535
    313. Dim LoopBytes() = BitConverter.GetBytes(LoopCount)
    314. metaName = "/appext/Data"
    315. metaBytes = New Byte(4) {}
    316. metaBytes(0) = 3
    317. metaBytes(1) = 1
    318. metaBytes(2) = LoopBytes(0)
    319. metaBytes(3) = LoopBytes(1)
    320. metaBytes(4) = 0
    321. pinnedArray = GCHandle.Alloc(metaBytes, GCHandleType.Pinned)
    322. With propVariant
    323. .vt = VARENUM.VT_UI1 Or VARENUM.VT_VECTOR
    324. .array.cElems = metaBytes.Length
    325. .array.pElems = pinnedArray.AddrOfPinnedObject
    326. End With
    327. If SetWicMetadataByName(pIWicMetadataQueryWriter, metaName, propVariant) = S_OK Then
    328. Ret = True
    329. End If
    330. pinnedArray.Free()
    331. Marshal.Release(pIWicMetadataQueryWriter)
    332. End If
    333. End If
    334. Return Ret
    335. End Function
    336. Private Function WriteGifFrameDelay(pIWicFrameEncode As IntPtr,
    337. Optional Delay As UShort = 10) As Boolean
    338. Dim Ret As Boolean
    339. If pIWicFrameEncode <> IntPtr.Zero Then
    340. Dim pIWicMetadataQueryWriter As IntPtr
    341. If GetWicBitmapFrameEncodeMetadataQueryWriter(pIWicFrameEncode, pIWicMetadataQueryWriter) = S_OK Then
    342. Dim metaName As String = "/grctlext/Delay"
    343. Dim propVariant As New PROPVARIANT
    344. If Delay <= 0 Then Delay = 10
    345. If Delay > 65535 Then Delay = 65535
    346. With propVariant
    347. .vt = VARENUM.VT_UI2
    348. .ui2 = Delay
    349. End With
    350. If SetWicMetadataByName(pIWicMetadataQueryWriter, metaName, propVariant) = S_OK Then
    351. Ret = True
    352. End If
    353. Marshal.Release(pIWicMetadataQueryWriter)
    354. End If
    355. End If
    356. Return Ret
    357. End Function
    358. #End Region
    359. #Region "Properties"
    360. Public WriteOnly Property AddImage As String
    361. Set(ImageFile As String)
    362. If File.Exists(ImageFile) Then
    363. Using tempBitmap As New Bitmap(ImageFile)
    364. Dim bitmap As New Bitmap(tempBitmap)
    365. bitmap.ConvertTo8bppIndexed
    366. m_Bitmaps.Add(bitmap)
    367. End Using
    368. End If
    369. End Set
    370. End Property
    371. Public ReadOnly Property RemoveImage(Index As Integer) As Boolean
    372. Get
    373. Dim Ret As Boolean
    374. If Index >= 0 AndAlso Index < m_Bitmaps.Count Then
    375. Dim currentCount As Integer = m_Bitmaps.Count
    376. m_Bitmaps.ElementAt(Index).Dispose()
    377. m_Bitmaps.RemoveAt(Index)
    378. If m_Bitmaps.Count < currentCount Then Ret = True
    379. End If
    380. Return Ret
    381. End Get
    382. End Property
    383. Public ReadOnly Property RemoveAllImages As Boolean
    384. Get
    385. Dim Ret As Boolean
    386. If m_Bitmaps.Count > 0 Then
    387. For Each bitmap In m_Bitmaps
    388. bitmap.Dispose()
    389. Next
    390. m_Bitmaps.Clear()
    391. If m_Bitmaps.Count = 0 Then Ret = True
    392. End If
    393. Return Ret
    394. End Get
    395. End Property
    396. Public ReadOnly Property ImageCount As Integer
    397. Get
    398. Return m_Bitmaps.Count
    399. End Get
    400. End Property
    401. #End Region
    402. #Region "IDisposable"
    403. Protected Overridable Sub Dispose(disposing As Boolean)
    404. If Not m_DisposedValue Then
    405. If disposing Then
    406. If m_Bitmaps.Count > 0 Then
    407. For Each bitmap In m_Bitmaps
    408. bitmap.Dispose()
    409. Next
    410. m_Bitmaps.Clear()
    411. End If
    412. End If
    413. Marshal.Release(m_pIWicImagingFactory)
    414. m_DisposedValue = True
    415. End If
    416. End Sub
    417. Public Sub Dispose() Implements IDisposable.Dispose
    418. Dispose(disposing:=True)
    419. GC.SuppressFinalize(Me)
    420. End Sub
    421. #End Region
    422. End Class



    und als letztes eine Form mit einem Button drauf

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Using animGifCreator As New AnimGifCreator
    4. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_000.png"
    5. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_001.png"
    6. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_002.png"
    7. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_003.png"
    8. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_004.png"
    9. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_005.png"
    10. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_006.png"
    11. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_007.png"
    12. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_008.png"
    13. animGifCreator.AddImage = "D:\Downloads\VBC_Prog\VBC_WIC\VBC_WIC_Image2AnimGIF\Images\frame_009.png"
    14. If animGifCreator.ImageCount > 0 Then
    15. If animGifCreator.CreateAnimGif("D:\test.gif") Then
    16. Debug.Print("Fertig.")
    17. Else
    18. Debug.Print("Es ist ein Fehler beim erstellen der animierten GIF aufgetreten!")
    19. End If
    20. End If
    21. End Using
    22. End Sub
    23. End Class


    In diesem Code fehlen noch weitere WriteGifxxx-Funktionen für bestimmte GIF-Blöcke die aber für Dich nicht so wichtig sind.

    Edit: Oha, Enum PaletteFlags im Modul vergessen. Naja, die gibt es hier: learn.microsoft.com/en-us/wind…pixelformats-paletteflags

    Edit 2: So, nachdem Du Meinen WIC Code gesehen hast und welche WriteGifxxx- Funktion wann aufgerufen wird, sollte das hier learn.microsoft.com/en-us/dotn…r?view=windowsdesktop-8.0 -> SetQuery im Zusammenhang mit dem Code von @RodFromGermany klar sein, wo Du entsprechende Blocks schreiben musst.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „-Franky-“ ()

    Der Vollstädigkeit halber. Das aufgeräumte Projekt zum Download. Wie immer: Keine zusätzlichen Referenzen oder Github-Pakete. Nur WIC- und GDI+ APIs. Erstellt halt eine animierte GIF aus Einzelbildern. Pfade zu den Bildern müsste Ihr entsprechend abändern. Bei Fragen: Bitte die "Windows Imaging Componet" in der MS-Doku aufsuchen. ;) Hier gibt es das komplette Projekt: Animierte Gif per Windows Imaging Component erstellen
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Vielen Dank -Franky-.
    Ich habe versucht, den Code nachzuvollziehen, aber ehrlich gesagt, ist das etwas zu viel für mich.
    Ich habe eine Schleife gebastelt, um die Pferdebilder einzulesen. Das funktioniert auch, und die Grafik wird endlos abgespielt. Allerdings verwandelt sich das Pferd in einen Tausendfüßler. Irgendwie verschwinden die Punkte der vorherigen Grafik nicht und es kommen immer mehr Beine dazu. Außerdem wird der Kopf immer dicker.

    Zudem habe ich noch eine Frage:
    Kann ich die Anzeigedauer eines Bildes verändern? Ich habe im Code eine "Delay"-Variable gefunden, über die das funktionieren könnte. Allerdings weis ich nicht, wie ich diesen Wert der Funktion im Button mitgeben kann.
    Hast du da eine Idee?

    Ansonsten:
    Vielen Dank für deine Mühe!
    Bilder
    • Pferd.gif

      7,88 kB, 96×64, 117 mal angesehen
    Ich sehe nur weiße Punkte auf weißem Hintergrund. ;)

    tron25 schrieb:

    Allerdings verwandelt sich das Pferd in einen Tausendfüßler. Irgendwie verschwinden die Punkte der vorherigen Grafik nicht und es kommen immer mehr Beine dazu. Außerdem wird der Kopf immer dicker.

    Schätze das Du den TransparencyFlag mal auf False setzen musst. Mit True und dem zweiten Parameter 0 (Index zu Palette), wird schwarz transparent weswegen die weißen Punkte vom vorhergehenden Bild nicht gelöscht werden. Dann gibt es noch die DisposalMethod wo Du einstellen kannst, wie die Bilder übereinander gezeichnet werden. Bei Deinen Bildern die nur die Farben Schwarz und Weiß enthalten, sollte es reichen den TransparencyFlag auf False zu setzen.

    tron25 schrieb:

    Kann ich die Anzeigedauer eines Bildes verändern? Ich habe im Code eine "Delay"-Variable gefunden, über die das funktionieren könnte. Allerdings weis ich nicht, wie ich diesen Wert der Funktion im Button mitgeben kann.

    Mein Code zeigt nur das Grundprinzip wie es funktioniert. Was Du möchtest lässt sich aber leicht implementieren. Erstell Dir eine Public Struct, die den Dateinamen und den Delay aufnehmen kann und eine Private Struct, die dann die Bitmap und den Delay aufnehmen kann. Bau AddImage entsprechend um das es die Public Struct annimmt und die Bitmap und den Delay in die Private Struct übergibt. Bau die List(Of Bitmap) auf List(Of Private Struct) um. Bau entsprechend alles andere, wo jetzt auf die List(Of Bitmap) zugegriffen wird, auf List(Of Private Struct) um. Speziell die For Each Schleifen. Denn da kommst ja wieder an die Daten der Privaten Struct und kannst so beim schreiben der Bitmap in den FrameEncode auch das Delay für dieses Bitmap schreiben.

    tron25 schrieb:

    Ich habe versucht, den Code nachzuvollziehen, aber ehrlich gesagt, ist das etwas zu viel für mich.

    Ja, es ist viel Code. Du musst Dir halt vorstellen, das genau das im Hintergrund passiert, wenn Du eine entsprechende Referenz/Namespace nutzt, der ebenfalls WIC zum schreiben von animierten GIFs verwendet. Nur das Du das bei entsprechenden Referenzen/Namespaces nicht den ganzen Code siehst. Ich habe zumindest versucht meinen Code ein wenig zu kommentieren damit man nicht ganz im Dunkeln steht. Den Rest müsste man sich ergoogeln um zu verstehen, was da genau passiert.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „-Franky-“ ()