Was mich anfänglich erstaunte war die Fähigkeit dieser Applikation einen Grafikformattyp auch dann noch erkennen zu können, wenn das falsche oder auch gar kein Suffix vorhanden war. Bekannterweise weigert sich Windows beim Entfernen einer Dateinamenserweiterung eine Applikations- oder Dateitypzuordnung durchzuführen. Wieso also macht ACDSee was Windows nicht kann.
Die Antwort ist ganz einfach: Jedes Bildformat verfügt über eindeutige Zeichenfolgen, die eine nachträgliche Zuordnung/Erkennung ermöglichen. Hierzu ist jedoch jede einzelne Datei zu öffnen und gezielt zu verarbeiten. In den meisten Fällen befinden sich diese Kennungen direkt am Dateianfang. Die einzelnen Formate unterscheiden sich letztlich nur darin, ob spezielle Bytefolgen oder klartextliche Kennungen zum Einsatz kommen. Im heutigen Blogeintrag zeige ich, mit welch einfachen Mitteln wir aus einer Datei ihren Bildformattyp auslesen können. Der Mustercode ist natürlich nicht allumfassend, dafür gibt es einfach zu viele Bildformate.
Ein Hinweis noch zum PCX Format das bereits zu DOS Zeiten von der Firma ZSoft entwickelt wurde. Die drei Bytes welche eine Erkennung ermöglichen, lassen sich bspw. auch mit Hilfe der INLIST() Funktion herausfinden. Ich habe mich jedoch dazu entschlossen, die Überprüfung auf Basis eines regulären Ausdrucks durchzuführen. Die daraus entstandenen Funktionen lassen sich in der Folge einfacher erweitern als dies bei komplizierten INLIST Konstrukten der Fall wäre. Gleiches gilt im Übrigen für das TGA Format.
lcPic = GETFILE()
IF FILE(lcPic)
CLEAR
* // Übergabe als Dateiname
?GetGraphicsFormat(lcPic)
* // Übergabe als Datenstrom
?GetGraphicsFormat(FILETOSTR(lcPic))
ENDIF
FUNCTION GetGraphicsFormat as String
LPARAMETERS vData as String
* // Übergabe eines Bildes wahlweise als Datenstrom oder als Dateiname
* // Derzeit erkannte Formate:
* // JPG, GIF, EMF, WMF, TIF, PNG, BMP, SWF, PDF, PCX, TGA
LOCAL lcReturn as String
lcReturn = [---]
* // Wenn kein Datenstrom sondern ein Dateiname übergeben wurde,
* // dann lesen wir diesen noch schnell in eine Variable ein
IF FILE(vData)
vData = FILETOSTR(vData)
ENDIF
IF !EMPTY(vData)
DO CASE
CASE LEN(vData) < 4
lcReturn = [---]
* // Joint Pictures Experts Group Format
* // JPGs erkennbar an den ersten drei Bytes: ÿØÿ
CASE LEFT(vData,3) = CHR(0xFF) + CHR(0xD8) + CHR(0xFF)
lcReturn = [JPG]
* // Graphics Interchange Format
* // GIFs erkennbar an den ersten drei Bytes: GIF
CASE LEFT(vData,3) = [GIF]
lcReturn = [GIF]
* // Enhanced Windows Metafile
* // EMFs erkennbar an Bytes 42-44: EMF
CASE SUBSTR(vData,42,3)= [EMF]
lcReturn = [EMF]
* // Windows Metafile Format
* // WMFs erkennbar an den ersten vier Bytes: ×ÍÆš
CASE LEFT(vData,4) = CHR(0xD7) + CHR(0xCD) + CHR(0xC6) + CHR(0x9A)
lcReturn = [WMF]
* // Tagged Image File Format
* // TIFFs erkennbat an den ersten vier Bytes: MM *
CASE LEFT(vData,4) = CHR(0x4D) + CHR(0x4D) + CHR(0x00) + CHR(0x2A)
lcReturn = [TIF]
* // Portable Network Graphics Format
* // PNGs erkennbar an den ersten vier Bytes: ‰PNG
CASE LEFT(vData,4) = CHR(0x89) + [PNG]
lcReturn = [PNG]
* // Windows Bitmap Graphic Format
* // BMPs erkennbar an den ersten zwei Bytes: BM
CASE LEFT(vData,2) = [BM]
lcReturn = [BMP]
* // Komprimierte Shockwave/Flash Datei
* // SWFs erkennbar an den ersten vier Bytes: CWS?
CASE LEFT(vData,3) = [CWS] AND ASC(SUBSTR(lcContents,4,1)) < 16
lcReturn = [SWF]
* // Unkomprimierte Shockwave/Flash Datei
* // SWFs erkennbar an den ersten vier Bytes: FWS?
CASE LEFT(vData,3) = [FWS] AND ASC(SUBSTR(lcContents,4,1)) < 16
lcReturn = [SWF]
* // Adobe Portable Document File
* // PDFs erkennbar an den ersten vier Bytes: %PDF
CASE LEFT(vData,4) = CHR(0x37) + [PDF]
lcReturn = [PDF]
* // Picture Exchange Format
* // PCX erkennbar an den ersten drei Bytes beginnend mit 0x0A
CASE IsPCX(LEFT(vData,3))
lcReturn = [PCX]
* // TrueVision Targa Format
* // TGA erkennbar an Bytes 2 und 3
CASE IsTGA(SUBSTR(vData,2,2))
lcReturn = [TGA]
ENDCASE
ENDIF
RETURN lcReturn
ENDFUNC
FUNCTION IsPCX as Boolean
LPARAMETERS vStream as String
* // Zusammenstellung des Abfragemusters.
* // Byte Definition ASCII Code + Beschreibung
* // 1 Ersteller 10 = ZSoft .pcx (Konstante)
* // 2 Version 0 = Version 2.5 of PC Paintbrush
* // 2 = Version 2.8 mit Paletteninfo
* // 3 = Version 2.8 ohne Paletteninfo
* // 4 = PC Paintbrush for Windows
* // 5 = Version 3.0 und größer von
* // - PC Paintbrush
* // - PC Paintbrush +
* // - Publisher's Paintbrush
* // - inkl. 24-bit .PCX Dateien
* // 3 Encoding 0 = ohne Verschlüsselung
* // 1 = mit Verschlüsselung
lcPattern = "^[" + CHR(10) + "]" ;
+ "[" + CHR(0) + CHR(2) + CHR(3) + CHR(4) + CHR(5) + "]" ;
+ "[" + CHR(0) + CHR(1) + "]$"
RETURN CheckPattern(vStream, lcPattern)
ENDFUNC
FUNCTION IsTGA as Boolean
LPARAMETERS vStream as String
* // Zusammenstellung des Abfragemusters.
* // Byte Definition ASCII Code + Beschreibung
* // 1 Farbkarte 0 o. 1
* // 2 Bildtyp 0 = keine Bilddaten enthalten
* // 1 = unkomprimiert, Farbkarte
* // 2 = unkomprimiert, RGB
* // 3 = unkomprimiert, schwarz/weiss
* // 9 = verschlüsselte Farbkarte
* // 10 = verschlüsselte RGB
* // 11 = komprimiert, s/w
* // 32 = komprimiert, farbig, verschl.
* // 33 = komprimiert, farbig, verschl.2
lcPattern = "^[" + CHR(0) + CHR(1) + "]" ;
+ "[" + CHR(0) + CHR(1) + CHR(2) + CHR(3) + CHR(9) + CHR(10) + CHR(11) + CHR(32) + CHR(33) + "]$"
RETURN CheckPattern(vStream, lcPattern)
ENDFUNC
FUNCTION CheckPattern as Boolean
LPARAMETERS vString as String, vPattern as String
LOCAL liReturn as Integer
* // Bedarfweise Deklaration der Klassenbibliothek für Reguläre Ausdrücke
IF AT(UPPER(HOME()+ [ffc\_regexp.vcx]),SET([Classlib])) = 0
SET CLASSLIB TO HOME()+ [ffc\_regexp.vcx] ADDITIVE
ENDIF
* // Objekt erzeugen, initialisieren, Muster zuweisen und abarbeiten
oexp = CREATEOBJECT([_regexp])
oexp.clear
oexp.pattern = vPattern
liReturn = oexp.execute(vString)
RETURN CAST(liReturn as L)
ENDFUNC
Keine Kommentare:
Kommentar veröffentlichen