![]() |
Erste Bytes einer Datei vergleichen?
Ich versuche, RAW-Dateien der diversen Kamerahersteller anhand ihrer Signaturen zu identifizieren. Hierbei gibt es die extrem nützliche Seite
![]() ![]() ![]() Zur einfachen Identifizierung von JPG-Dateien anhand der charakteristischen ersten beiden Bytes habe ich folgende Prozedur verwendet:
Delphi-Quellcode:
Jetzt sind die Signaturen der RAW-Dateien aber deutlich länger, die einer CRW-Datei von Canon lautet zum Beispiel
function JPGHeaderOK(const Dateiname:string):Boolean;
var Datei:File; Buf:TBytes; begin {$I-} Try Buf := [0,0]; Try AssignFile(Datei,Dateiname); Reset(Datei, 1); BlockRead(Datei, Buf[0], 2); Result := ((Buf[0] = $FF) and (Buf[1] = $D8)); Except Result := False; End; Finally CloseFile(Datei); SetLength(Buf,0); End; {$I+} end;
Delphi-Quellcode:
.
49 49 1A 00 00 00 48 45 41 50 43 43 44 52 02 00
Wie macht man das am besten? Der Einzelvergleich Buf[0]..Buf[15] kann es doch wohl kaum sein. |
AW: Erste Bytes einer Datei vergleichen?
Guten Abend,
darfst Du keine Exif-Bibliothek nutzen? Das Kamera-Model ist auch in den Exif-Daten vermerkt. Grüße Klaus |
AW: Erste Bytes einer Datei vergleichen?
|
AW: Erste Bytes einer Datei vergleichen?
Kaum fragt man, schon fallen einem die richtigen Suchbegriffe für Google ein.
Ein Machbarkeitskonzept auf der Basis einer Antwort auf ![]()
Delphi-Quellcode:
@Klaus01: Es ging um RAW-Dateien. Da gibt es kein normales EXIF und es hätte auch nichts genützt, da ich die Dateien ja anhand ihrer Signatur und nicht anhand ihrer Dateierweiterung identifizieren wollte.
function IstRAWFormat(const Dateiname:string):Boolean;
var Datei:File; Buf:array [0..19] of Byte; BufCRW:TBytes; //------------------------------------------------------------------------------------------------------------------------------------------ function ByteArrayPos(const SearchArr : array of byte; const CompArr : array of byte):integer; var Comp,Search : AnsiString; begin SetString(Comp, PAnsiChar(@CompArr[0]), Length(CompArr)); SetString(Search, PAnsiChar(@SearchArr[0]), Length(SearchArr)); Result := Pos(Search,Comp) - 1; end; //------------------------------------------------------------------------------------------------------------------------------------------ begin {$I-} Result := False; Try Try AssignFile(Datei,Dateiname); Reset(Datei, 1); BlockRead(Datei, Buf[0], 20); Except exit; End; BufCRW := [$49,$49,$1A,$00,$00,$00,$48,$45,$41,$50,$43,$43,$44,$52,$02,$00]; If ByteArrayPos(BufCRW,Buf) = 0 then Result := True; Finally CloseFile(Datei); SetLength(BufCRW,0); End; {$I+} end; @t.roller: Danke für den Hinweis! Die Liste erscheint aber nicht vollständig, so habe ich z.B. die ARW-Dateien von Sony nicht gefunden. |
AW: Erste Bytes einer Datei vergleichen?
|
AW: Erste Bytes einer Datei vergleichen?
Tja, hätte man darauf nicht selbst kommen können? Ehrlich gesagt, auf die Konstruktion mit
Delphi-Quellcode:
vermutlich nicht, obwohl sie mir geläufig ist. Also dann:
PAnsiChar(@BufCRW[0])
Delphi-Quellcode:
Übrigens, ist das
function IstRAWFormat(const Dateiname:string):Boolean;
var Datei:File; Buf:array [0..19] of Byte; BufCRW,BufARW,BufCR2:TBytes; begin {$I-} Try Try AssignFile(Datei,Dateiname); Reset(Datei, 1); BlockRead(Datei, Buf[0], 20); Except exit(False); End; BufCRW := [$49,$49,$1A,$00,$00,$00,$48,$45,$41,$50,$43,$43,$44,$52,$02,$00]; BufCR2 := [$49,$49,$2A,$00,$10,$00,$00,$00,$43,$52]; BufARW := [$49,$49,$2A,$00]; Result := CompareMem(PAnsiChar(@BufCRW[0]),PAnsiChar(@Buf[0]),Length(BufCRW)) or CompareMem(PAnsiChar(@BufCR2[0]),PAnsiChar(@Buf[0]),Length(BufCR2)) or CompareMem(PAnsiChar(@BufARW[0]),PAnsiChar(@Buf[0]),Length(BufARW)); Finally CloseFile(Datei); SetLength(BufCRW,0); SetLength(BufCR2,0); SetLength(BufARW,0); End; {$I+} end;
Delphi-Quellcode:
eigentlich nötig? (Auch das habe ich ziemlich oft gelesen, ich glaube daher, nicht).
SetLength(BufCRW,0);
|
AW: Erste Bytes einer Datei vergleichen?
Das ist genauso "nötig", wie das PAnsiChar(...) :angle2:
|
AW: Erste Bytes einer Datei vergleichen?
Wird ja immer kürzer.
Delphi-Quellcode:
Gibt es sonst noch was? Vielleicht die Steinzeitroutine
function IstRAWFormat(const Dateiname:string):Boolean;
var Datei:File; Buf:array [0..19] of Byte; BufCRW,BufARW,BufCR2,BufRW2,BufNEF,BufORF,BufPEF,BufRAF,BufRWL,BufSRW,BufX3F, BufERF,BufFFF,BufMEF,BufMRW,BufNRW,BufDCR,BufSRF:TBytes; begin Result := False; If FileExists(Dateiname) then begin AssignFile(Datei,Dateiname); {$I-} Reset(Datei, 1); BlockRead(Datei, Buf[0], 20); {$I+} If IOResult <> 0 then exit; BufCRW := [$49,$49,$1A,$00,$00,$00,$48,$45,$41,$50,$43,$43,$44,$52,$02,$00]; // Canon, veraltet BufCR2 := [$49,$49,$2A,$00,$10,$00,$00,$00,$43,$52]; // Canon BufARW := [$49,$49,$2A,$00]; // Sony, auch SR2 (Sony), 3FR (Hasselblad), IIQ (PhaseOne) BufRW2 := [$49,$49,$55,$00,$18,$00,$00,$00,$88,$E7,$74,$D8,$F8,$25,$1D,$4D]; // Panasonic BufNEF := [$4D,$4D,$00,$2A,$00,$00,$00,$08,$00]; // Nikon BufORF := [$49,$49,$52]; // Olympus BufPEF := [$4D,$4D,$00,$2A,$00]; // Pentax BufRAF := [$46,$55,$4A,$49,$46,$49,$4C,$4D,$43,$43,$44,$2D,$52,$41,$57,$20]; // Fujifilm BufRWL := [$49,$49,$55,$00]; // Leica BufSRW := [$4D,$4D,$00,$2A,$00,$00,$00,$08,$00,$06,$01,$0F,$00,$02,$00,$00]; // Samsung BufX3F := [$46,$4F,$56,$62]; // Sigma // veraltet BufDCR := [$44,$53,$43,$2D,$49,$6D,$61,$67,$65]; // Kodak, veraltet BufERF := [$43,$6F,$6D,$70,$75,$63,$6F,$6E,$20,$45,$4F,$53,$20,$44,$65,$73]; // Epson, veraltet BufFFF := [$4D,$4D,$00,$2A]; // Hasselblad, veraltet BufMEF := [$4D,$52,$00,$00,$00,$00,$00,$00,$00,$00,$1C,$0E]; // Mamiya, veraltet BufMRW := [$00,$4D,$52,$4D]; // Minolta, veraltet BufNRW := [$4E,$4F,$4B,$49,$41,$52,$41,$57]; // Nokia, veraltet BufSRF := [$4C,$53]; // Sony, veraltet, DSC-F828 von 2004 Result := CompareMem(@BufCRW[0],@Buf[0],Length(BufCRW)) or CompareMem(@BufCR2[0],@Buf[0],Length(BufCR2)) or CompareMem(@BufARW[0],@Buf[0],Length(BufARW)) or CompareMem(@BufRW2[0],@Buf[0],Length(BufRW2)) or CompareMem(@BufNEF[0],@Buf[0],Length(BufNEF)) or CompareMem(@BufORF[0],@Buf[0],Length(BufORF)) or CompareMem(@BufPEF[0],@Buf[0],Length(BufPEF)) or CompareMem(@BufRAF[0],@Buf[0],Length(BufRAF)) or CompareMem(@BufRWL[0],@Buf[0],Length(BufRWL)) or CompareMem(@BufSRW[0],@Buf[0],Length(BufSRW)) or CompareMem(@BufX3F[0],@Buf[0],Length(BufX3F)) // veraltet or CompareMem(@BufDCR[0],@Buf[0],Length(BufDCR)) or CompareMem(@BufERF[0],@Buf[0],Length(BufERF)) or CompareMem(@BufFFF[0],@Buf[0],Length(BufFFF)) or CompareMem(@BufMEF[0],@Buf[0],Length(BufMEF)) or CompareMem(@BufMRW[0],@Buf[0],Length(BufMRW)) or CompareMem(@BufNRW[0],@Buf[0],Length(BufNRW)) or CompareMem(@BufSRF[0],@Buf[0],Length(BufSRF)); CloseFile(Datei); end; end;
Delphi-Quellcode:
? Ich dachte, es ist ja nicht nötig, mit einem FileStream die ganze Datei einzulesen. Außerdem habe ich das
AssignFile
Delphi-Quellcode:
durch ein
Try..Except
Delphi-Quellcode:
ersetzt.
IOResult
|
AW: Erste Bytes einer Datei vergleichen?
Du denkst doch nicht etwa, dass man mit dem FileStream nur ganze Dateien einlesen kann?
Das ganze noch in eine Konstante oder Variable (Array of Array) und dann das Vergleichen in eine Schleife. TFileStream statt BlockRead nur ein Read und man braucht weder Try-Except noch IOResult. PS: Das AssignFile gehörte vor das erste Try. Da in Finally auf die Variable zugegriffen wird, gehört die Initialisierung vor das Try, damit es auch "immer" richtig initialisiert wird. Und durch das
Delphi-Quellcode:
war die Exceptionbehandluch sowieso falsch, da diese Dateifunktionen dort mit Fehlercodes (IOResult) und nicht mit Exceptions gearbeitet hatte.
{$I-}
|
AW: Erste Bytes einer Datei vergleichen?
Ich weiß zwar nicht, ob das für diesen Anwendungsfall relevant ist, aber ich baue sowas gerne hierarchisch auf:
Delphi-Quellcode:
Sinnvollerweise packt man das noch als statische Methoden in einen passenden Namespace (Record oder Klasse). Statt des Boolschen Results würde sich auch ein Aufzählungstyp für die verschiedenen Formate anbieten, falls man abhängig vom Format unterschiedlich reagieren möchte.
function IstRAWFormat(const Buf: TBytes):Boolean; overload;
const cRawHeader: TArray<TBytes> = [ [$49,$49,$1A,$00,$00,$00,$48,$45,$41,$50,$43,$43,$44,$52,$02,$00], // Canon, veraltet [$49,$49,$2A,$00,$10,$00,$00,$00,$43,$52], // Canon [$49,$49,$2A,$00], // Sony, auch SR2 (Sony), 3FR (Hasselblad), IIQ (PhaseOne) [$49,$49,$55,$00,$18,$00,$00,$00,$88,$E7,$74,$D8,$F8,$25,$1D,$4D], // Panasonic [$4D,$4D,$00,$2A,$00,$00,$00,$08,$00], // Nikon [$49,$49,$52], // Olympus [$4D,$4D,$00,$2A,$00], // Pentax [$46,$55,$4A,$49,$46,$49,$4C,$4D,$43,$43,$44,$2D,$52,$41,$57,$20], // Fujifilm [$49,$49,$55,$00], // Leica [$4D,$4D,$00,$2A,$00,$00,$00,$08,$00,$06,$01,$0F,$00,$02,$00,$00], // Samsung [$46,$4F,$56,$62], // Sigma // veraltet [$44,$53,$43,$2D,$49,$6D,$61,$67,$65], // Kodak, veraltet [$43,$6F,$6D,$70,$75,$63,$6F,$6E,$20,$45,$4F,$53,$20,$44,$65,$73], // Epson, veraltet [$4D,$4D,$00,$2A], // Hasselblad, veraltet [$4D,$52,$00,$00,$00,$00,$00,$00,$00,$00,$1C,$0E], // Mamiya, veraltet [$00,$4D,$52,$4D], // Minolta, veraltet [$4E,$4F,$4B,$49,$41,$52,$41,$57], // Nokia, veraltet [$4C,$53] // Sony, veraltet, DSC-F828 von 2004 ]; var rawHeader: TBytes; begin for rawHeader in cRawHeader do begin if CompareMem(@rawHeader[0], @Buf[0], Length(rawHeader)) then Exit(true); end; Result := false; end; function IstRAWFormat(Stream: TStream):Boolean; overload; var buf: TBytes; savePos: Int64; begin SetLength(buf, 20); savePos := Stream.Position; try Stream.ReadData(buf, Length(buf)); finally Stream.Position := savePos; end; Result := IstRAWFormat(buf); end; function IstRAWFormat(const Dateiname: string):Boolean; overload; var stream: TFileStream; begin stream := TFileStream.Create(Dateiname, fmOpenRead); try result := IstRAWFormat(stream); finally stream.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:17 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz