VB 5/6-Tipp 0454: Informationen über GIF-Dateien auslesen
von Michael Gieser
Beschreibung
Dieser Code kann einige nützliche Informationen über eine Gif-Datei liefern. Wie z.B. Farbanzahl, Index ...
Schwierigkeitsgrad: | Verwendete API-Aufrufe: | Download: |
'Dieser Quellcode stammt von http://www.activevb.de 'und kann frei verwendet werden. Für eventuelle Schäden 'wird nicht gehaftet. 'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. 'Ansonsten viel Spaß und Erfolg mit diesem Source! '------------- Anfang Projektdatei Projekt1.vbp ------------- '--------- Anfang Formular "Form1" alias Form1.frm --------- ' Steuerelement: Schaltfläche "cmdLoad" ' Steuerelement: Beschriftungsfeld "lblInfo" Option Explicit Private Sub cmdLoad_Click() Dim Pfad As String, gi As GIFData Pfad = InputBox("Pfad vom GIF:", "GIF", App.Path & "\ANT.gif") GetGifInfo Pfad, gi lblInfo.Caption = "Datei: " & gi.DateiName & vbNewLine _ & "Größe: " & Int(gi.DateiGröße / 102.4) / 10 & " KB" & vbNewLine _ & "Breite: " & gi.Breite & vbNewLine & "Höhe: " & gi.Höhe & vbNewLine _ & "Farben: " & gi.AnzahlFarben & vbNewLine _ & "Transparent: " & gi.Transparent & vbNewLine _ & "Transparet Index: " & gi.TransIndex ';) '# End Sub '---------- Ende Formular "Form1" alias Form1.frm ---------- '---- Anfang Modul "basGetGIFInfo" alias GetGIFinfo.bas ---- Option Explicit Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" ( _ pDst As Any, _ pSrc As Any, _ ByVal ByteLen As Long) Public Type GIFData DateiName As String DateiGröße As Long Version As String Breite As Integer Höhe As Integer AnzahlFarben As Long Palette() As Byte Transparent As Boolean TransIndex As Long End Type Public Sub GetGifInfo(ByVal DateiPfad As String, ZielInfo As GIFData) Dim NextFFile As Integer, I As Long Dim tmpByte As Byte, tmpSizeByte(1) As Byte, tmpPalByte(2) As Byte Dim Header As String, tmpCol(2) As Byte ' RGB If Dir(DateiPfad) = "" Then MsgBox "Unglültige Date! Bitte Pfad " & _ "prüfen.", vbCritical, "Error": Exit Sub NextFFile = FreeFile Open DateiPfad For Binary As #NextFFile ' Die GIF-Beschreibung ist in den ersten 6 Bytes For I = 0 To 5 Get #NextFFile, , tmpByte Header = Header & Chr(tmpByte) Next I ' Prüfen, ob es sich um ein GIF handelt If Left(Header, 3) <> "GIF" Then MsgBox "Keine gültige Gif-Datei.", vbCritical, "Error" Close #NextFFile Exit Sub End If ZielInfo.DateiGröße = LOF(NextFFile) ZielInfo.DateiName = DateiPfad ' Die Version steht in den letzten 3 Bytes ZielInfo.Version = Right(Header, 3) ' Dann kommt die Breite als Integer (2 Byte) Get #NextFFile, 7, tmpSizeByte CopyMemory ZielInfo.Breite, tmpSizeByte(0), 2 ' Höhe ... Get #NextFFile, 9, tmpSizeByte CopyMemory ZielInfo.Höhe, tmpSizeByte(0), 2 ' Ab jetzt wirds problematisch. Ich hab nicht genau herausgefunden wie ' die 'FarbAnzahl' liegt. Doch das ist wichtig um die Pallette zu füllen. ' Der Code hier funktioniert NICHT!!! Get #NextFFile, 11, tmpPalByte CopyMemory ZielInfo.AnzahlFarben, tmpPalByte(0), 3 If tmpPalByte(0) = 179 Then ZielInfo.AnzahlFarben = 16 If ZielInfo.AnzahlFarben = 247 Then ZielInfo.AnzahlFarben = 256 ZielInfo.AnzahlFarben = 256 ' Kann weg, wenn jemand herausbekommt wie ' man an die Farbanzahl kommt ' Der Rest der Daten ist jetzt auch falsch... ' Und nun die Pallete füllen ReDim ZielInfo.Palette(ZielInfo.AnzahlFarben - 1, 2) As Byte For I = 0 To ZielInfo.AnzahlFarben - 1 Get #NextFFile, (I * 3) + 12, tmpByte ZielInfo.Palette(I, 0) = tmpByte Get #NextFFile, (I * 3) + 13, tmpByte ZielInfo.Palette(I, 1) = tmpByte Get #NextFFile, (I * 3) + 14, tmpByte ZielInfo.Palette(I, 2) = tmpByte Next I ' Tranparent Get #NextFFile, 17 + (3 * ZielInfo.AnzahlFarben), tmpByte If tmpByte = 1 Or tmpByte = 5 Then ZielInfo.Transparent = True Else ZielInfo.Transparent = False End If ' Index der Transparent-Farbe If ZielInfo.Transparent = True Then Get #NextFFile, 20 + (3 * ZielInfo.AnzahlFarben), tmpByte ZielInfo.TransIndex = tmpByte End If Close #NextFFile End Sub '----- Ende Modul "basGetGIFInfo" alias GetGIFinfo.bas ----- '-------------- Ende Projektdatei Projekt1.vbp --------------
Tipp-Kompatibilität:
Windows/VB-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | |||||||
VB5 | |||||||
VB6 |
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 1 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von Götz Kircher am 14.01.2004 um 15:31
Betr.: der unvollständige Tipp 454
Hallo, Ihr Leute von activeVB
Der Aufbau einer GIF ist etwas komplexer als der Tipp 454 vermuten läßt. Die dort aufgeworfene Frage nach der Größe der Farbtabelle habe ich im folgenden beantwortet. Vielleicht wollt Ihr den Tipp durch diesen Code hier ersetzen.
Zumindest stelle ich ihn zur Verfügung.
Public Function GetTransparenteAustauschFarbe(ByVal LwpD As String, _
ByRef TransparenteAustauschfarbe As Long _
) As Boolean
'
'Die Funktion holt aus der mit LwpD (LaufwerkPfadDateiname) angegebenen
'GIF- Datei die transparente Farbe und weitere Infomationen heraus.
'
'Ist die GIF transparent, gibt die Funktion TRUE zurück, die
'TransATF-Werte sind zugewiesen.
'
'Ist die Datei keine GIF-Datei oder die GIF ist nicht transparent,
'oder sonst ein Fehler ist aufgetreten, gibt die Funktion FALSE zurück.
'
'Sind mehrere Bilder in der GIF enthalten, werden die Daten für das
'erste Bild zurückgegeben.
'
'
'Diese Function basiert auf den Angaben von Compuserve.
'Nachzulesen unter: http://256.com/gray/docs/gifspecs/general.html
'
'Programmiert Jan. 2004 von Götz Kircher, goetzkircher@web.de
'Die Source darf frei verwendet werden.
'Für Richtigkeit und Funktionsfähigkeit keine Gewähr und Haftung.
'(siehe auch die Anmerkung zu: If FoundHintergrundfarbe Then
'weiter unten im Code)
'
'---------------------------------------------------------------
'die folgende Typdeklaration muß im Modulkopf stehen:
'
'Type GIFHeaderType
' Signatur As String * 6
' LogicalScreenWidth As Integer 'Pixel
' LogicalScreenHeight As Integer
' 'Das ist die Größe des Bereichs, in dem die Bilder
' 'ausgegeben werden. Er kann größer sein als das
' 'Bild oder die Bilder.
' '(Die Bilder können unterschiedlich groß sein und
' 'an unterschiedlicher Position ausgegeben werden.)
' DiverseBitDaten As Byte 'Bit 7 = true: globale Farbtabelle folgt
'Bit 3 = true: Farbtabelle ist sortiert
'Die häufigst vorkommende Farbe zuerst.
'Bit 0 bis 3: Größe der Farbtabelle
'= 2 ^ (Wert+1)
' HintergrundFarbeIndex As Byte
' 'das ist nicht der Index auf die transparente Farbe,
' 'sondern der Index auf die Hintergrundfarbe.
' 'Der durch LogicalScreenWidth und LogicalScreenHeight definierte Bereich
' 'kann mit einer eigenen Hintergrundfarbe ausgefüllt sein.
' Pixelabstandverhältnis As Byte
'End Type
'
'Type GIFFarbwertType
' Rot As Byte
' Grün As Byte
' Blau As Byte
'End Type
'
'Type GIFImageDescriptorType 'je Bild ist genau einer vorhanden.
' ImgLeft As Integer 'Left und Top innerhalb der Logical
' ImgTop As Integer 'ScreenWidth und ...Top
' ImgWidth As Integer 'Das sind jetzt die Bildabmessungen
' ImgHeight As Integer 'des jeweiligen Bildes in Pixel
' DiverseBitDaten As Byte 'Bit 7 = true: lokale Farbtabelle folgt
'Bit 6 = true: interleaced GIF
'Bit 5 = true: Farbtabelle ist sortiert
'Bit 0 bis 2: Größe der Farbtabelle
'End Type
'
'Type GIFGraphCtrlExtType
' BlockSize As Byte
' DiverseBitDaten As Byte 'Bit 0 = True: GIF ist transparent
' 'Bit 1 = True: animierte GIF
' 'Weiterschaltung nach Tastendruck
' 'oder Mausklick.
' DelayTime As Integer 'wenn > 0: animierte GIF. Wartezeit
' 'zum Weiterschalten in 1/100 Sek.
' transpFarbeIdx As Byte
' BlockTerminator As Byte
'End Type
'
Dim GIFheader As GIFHeaderType
Dim GIFFarbwert() As GIFFarbwertType
Dim GIFImageDescriptor As GIFImageDescriptorType
Dim GIFGraphCtrlExt As GIFGraphCtrlExtType
Dim weglesen1Byte As Byte
Dim weglesen12Byte As String * 12
Dim weglesen13Byte As String * 13
Dim Weglesen() As Byte
Dim AnzByteWeglesen As Byte
Dim FileLänge As Long
Dim GIFHdl As Integer
Dim GrößeFarbtabelle As Integer
Dim Separator As Byte
Dim ExitFlag As Boolean
Dim FoundHintergrundfarbe As Boolean
Dim Hintergrundfarbe As Long
On Error Goto errhdl
'
If Dir(LwpD) = "" Then
'die Datei ist nicht vorhanden
GetTransparenteAustauschFarbe = False
Exit Function
End If
If Right(LCase(LwpD), 4) <> ".gif" Then
'keine GIF
GetTransparenteAustauschFarbe = False
Exit Function
End If
'
FileLänge = FileLen(LwpD)
If FileLänge < Len(GIFheader) Then
'Datei zu kurz ==> keine GIF
GetTransparenteAustauschFarbe = False
Exit Function
End If
'
'den Header einlesen
GIFHdl = FreeFile
Open LwpD For Binary As GIFHdl
Get #GIFHdl, , GIFheader
'
If GIFheader.Signatur <> "GIF89a" And GIFheader.Signatur <> "GIF87a" Then
'keine GIF.
GetTransparenteAustauschFarbe = False
Close GIFHdl
Exit Function
'wird nur die Infomation der transparenten Farbe benötigt, kann die
'Abfrage auch lauten: If GIFheader.Signatur <> "GIF89a" then
'denn GIF87a unterstützt keine Transparenz.
End If
If GIFheader.DiverseBitDaten And 128 Then
'wenn das höchstwertige Bit gesetzt ist, gibt es eine globale
'Farbtabelle. Die Größe der Farbtabelle ist in den drei
'niederwertigsten Bits verpackt.
GrößeFarbtabelle = 2 ^ ((GIFheader.DiverseBitDaten And 7) + 1)
'
'Die Tabelle mit den Farbwerten dimensionieren...
'(der Index ist nullbasiert)
ReDim GIFFarbwert(0 To GrößeFarbtabelle - 1) As GIFFarbwertType
'
'und einlesen
Get #GIFHdl, , GIFFarbwert
'
'Beim Austesten bin ich auf GIFs gestoßen, da zeigte der (nicht benötigte)
'Index auf 0xFF außerhalb des Indexbereiches der globalen Farbtabelle.
'deshalb die folgende Abfrage.
If GIFheader.HintergrundFarbeIndex < GrößeFarbtabelle Then
Hintergrundfarbe = RGB(GIFFarbwert(GIFheader.HintergrundFarbeIndex).Rot, _
GIFFarbwert(GIFheader.HintergrundFarbeIndex).Grün, _
GIFFarbwert(GIFheader.HintergrundFarbeIndex).Blau)
FoundHintergrundfarbe = True
'Eine Hintergrundfarbe kann nur zusammen mit einer globalen Farbtabelle
'auftreten.
End If
End If
'
ExitFlag = False 'Default
Do 'ab jetzt ist die Reihenfolge nicht mehr zwingend vorgeschrieben.
'==> Schleifen bis zum ersten GIFImageDescriptor.
'
'das nächste Byte ist ein Seperator. Diesen einlesen...
Get #GIFHdl, , Separator
'...und auswerten
If Separator = &H2C Then 'Es folgt ein GIFImage- Descriptor
'diesen einlesen...
Get #GIFHdl, , GIFImageDescriptor
'... und auswerten
If GIFImageDescriptor.DiverseBitDaten And 128 Then
'wenn das höchstwertige Bit gesetzt ist, folgt eine lokale
'Farbtabelle (sie gilt für das nächste Bild in einer Gif mit
'mehreren Bildern) Die eventuell oben eingelesene globale
'Farbtabelle wird jetzt durch die lokale Farbtabelle
'überschrieben. (falls sie gebraucht wird, muß sie
'hier zuerst gesichert werden.)
GrößeFarbtabelle = 2 ^ ((GIFImageDescriptor.DiverseBitDaten And 7) + 1)
ReDim GIFFarbwert(0 To GrößeFarbtabelle - 1) As GIFFarbwertType
Get #GIFHdl, , GIFFarbwert
End If
ExitFlag = True 'im Anschluß folgen die ersten Bilddaten. D.h. es
'sind alle von dieser Funktion benötigten Daten
'zusammen ==> Ende einlesen.
ElseIf Separator = &H21 Then 'das ist der Extensions-Introducer
Get #GIFHdl, , Separator 'Das nächste Byte besagt,
'was für eine Extension
If Separator = &H1 Then 'Plain Text Extension (Text anstatt Bild)
'interessiert hier nicht ==> weglesen
Get #GIFHdl, , weglesen13Byte
Do
Get #GIFHdl, , weglesen1Byte
Loop Until weglesen1Byte = 0
ElseIf Separator = &HFF Then ' Applikations Extension (Copyright)
'interessiert hier nicht ==> weglesen
Get #GIFHdl, , weglesen12Byte
Get #GIFHdl, , AnzByteWeglesen
If AnzByteWeglesen > 0 Then
ReDim Weglesen(1 To AnzByteWeglesen) As Byte
Get #GIFHdl, , Weglesen
End If
Get #GIFHdl, , weglesen1Byte
ElseIf Separator = &HFE Then 'Kommentar Extension
'interessiert auch nicht ==> weglesen
Do
Get #GIFHdl, , weglesen1Byte
Loop Until weglesen1Byte = 0
ElseIf Separator = &HF9 Then ' Graphic Control Extension
'das wird gebraucht. Hier steht ob und wie transparent.
Get #GIFHdl, , GIFGraphCtrlExt
End If
End If
Loop While Not ExitFlag
'
'
If GrößeFarbtabelle = 0 Then 'keine Farbtabelle gefunden
'Das ist laut Definition erlaubt. Es gilt dann die zuletzt geladene
'Farbtabelle. Ist diese nicht vorhanden, eine Standartfarbtabelle.
'Dieser Sonderfall aus der Zeit als Speicherplatz und Übertragungs-
'zeiten noch sehr teuer waren, wird hier nicht behandelt.
'
'Gibt es noch solche GIFs?
GetTransparenteAustauschFarbe = False
Close #GIFHdl
Exit Function
End If
'Die Farbtabelle steht jetzt zur Verfügung in
'GIFFarbwert(0 to Größefarbtabelle -1).Rot | .Grün | .Blau
'Der Wert "Größefarbtabelle" gibt keinen Aufschluß über die Anzahl der
'verwendeten Farben, da die Tabelle nicht kontinuierlich zunimmt, sondern
'in Stufen 2 ^(N+1), wobei N den Wert 0 bis 7 annehmen kann.
'Um die Anzahl verwendeter Farben festzustellen, muß die Farbtabelle
'selber ausgewertet werden, was hier nicht geschieht.
'
'Prüfen, ob eine transparente Austauschfarbe vorhanden ist.
If GIFGraphCtrlExt.DiverseBitDaten And 1 Then 'ja, vorhanden
TransparenteAustauschfarbe = RGB( _
GIFFarbwert(GIFGraphCtrlExt.transpFarbeIdx).Rot, _
GIFFarbwert(GIFGraphCtrlExt.transpFarbeIdx).Grün, _
GIFFarbwert(GIFGraphCtrlExt.transpFarbeIdx).Blau)
'
GetTransparenteAustauschFarbe = True
'
'jetzt muß noch ein Sonderfall abgefangen werden.
If FoundHintergrundfarbe Then
If TransparenteAustauschfarbe <> Hintergrundfarbe Then
'sind mehrere Bilder vorhanden?
If GIFGraphCtrlExt.DelayTime > 0 Or _
GIFGraphCtrlExt.DiverseBitDaten And 2 Then 'ja
'dann bezieht sich die Transparenz auf die in
'der GIF vorgegebene Hintergrundfarbe, auf die
'Bilder gesetzt werden.
GetTransparenteAustauschFarbe = False
End If
End If
End If
'Achtung: Die letzte Regel ist nicht immer richtig.
'Es gibt GIFs in denen sie angewendet werden muß und
'welche, wo sie nicht angewendet werden darf.
'von der Logik her müßte es heißen:
'If FoundHintergrundfarbe Then
'If TransparenteAustauschfarbe <> Hintergrundfarbe Then
'GetTransparenteAustauschFarbe = False
'Endif
'endif
'Nach dieser Regel kopiert werden die GIFs in der Picturebox
'auch nicht immer richtig angezeigt.
'Es liegt der Verdacht nahe, daß die Picturebox sich beim
'Laden der GIF nicht ganz korrekt verhält und hieraus
'der Fehler resultiert.
'Wer die richtige Regel findet, teilt sie mir bitte mit.
'
Else
'nicht transparent oder kein GIFGraphCtrlExt- Block gefunden
'(in nicht transparenten GIFs muß er nicht vorhanden sein,
'in der GIF87a- Version gibt es den Block nicht.)
GetTransparenteAustauschFarbe = False
End If
'
Close #GIFHdl
Exit Function
'
errhdl: 'Fehlerbehandlung
'Es können zwei Fehler auftreten:
'1.) Der Dateiaufbau ist nicht korrekt, weshalb ein Lesezugriff
' über das Dateiende hinaus erfolgen könnte.
'2.) Der Index auf die transparente Austauschfarbe ist falsch
' angegeben und zeigt auf einen Eintrag außerhalb der Farbtabelle.
'In beiden Fällen gibt die Funktion FALSE zurück
Close #GIFHdl
GetTransparenteAustauschFarbe = False
End Function