![]() |
Bildformat anhand Header erkennen
Hi ihr Programmierer,
Ich less mit über die neue Kontactstruktur von Vista das Kontaktbild von einem Kontakt als Stream heraus. Wenn es die Standartbilder sind geht Bitmap super. Wenn jemand aber ein PNG Image auswählt funkt dies nicht mehr. So jetzt wollt ich mal fragen, ob man anhand bestimmter Bytes in dem Stream, das Format erkennen kann. Hab schon gegooglet, aber nichts gefunden oder ich bin blind :shock: oder suche unter dem falschen Begriff. Gruss NickelM |
AW: Bildformat anhand Header erkennen
Wie lädst du denn das Bild?
Und hast du PNG überhaupt in dein Programm eingebunden? siehe Abschnitte "Dateikopf": ![]() ![]() |
AW: Bildformat anhand Header erkennen
Eingebunden ja.
Es ist ja so ich bekomm dne Stream. Ich will dann das Bild in eine ListBox zeichnen (mit einer TImageList. Funkt auch wenn ich das Format kenne. So wenn ich das jetzt richtig verstehe sind das also immer die ersten 2 Bytes die den Dateityp identifizieren. Danke ich guge mal ob ich es damit hinbekomme. EDIT: Habe es durch den Post herausgefunden. Es gibt ein Header Record names TBitmapFileHeader; Mit dem kann ich erkenne ob bitmap,gif und jpeg bis jetzt. Ich denk ich find dadruch auch die anderen raus. Danke |
AW: Bildformat anhand Header erkennen
Habe etwas experimentiert:
Delphi-Quellcode:
const
GIF_HEADER = AnsiChar($47) + AnsiChar($49) + AnsiChar($46); JPG_HEADER = AnsiChar($FF) + AnsiChar($D8) + AnsiChar($FF) + AnsiChar($E0); BMP_HEADER = AnsiChar($42) + AnsiChar($4D); PNG_HEADER = AnsiChar($89) + AnsiChar($50) + AnsiChar($4E) + AnsiChar($47); PSD_HEADER = AnsiChar($38) + AnsiChar($42) + AnsiChar($50) + AnsiChar($53); TIF_HEADER = AnsiChar($49) + AnsiChar($49) + AnsiChar($2A); TIF_HEADER2 = AnsiChar(77) + AnsiChar(77) + AnsiChar(00); WMF_HEADER = AnsiChar($D7) + AnsiChar($CD) + AnsiChar($C6) + AnsiChar($9A); MAX_SIGNATURES = 7; Signatures: array[0..MAX_SIGNATURES] of TImageSignature = ( (ImageType: ifGIF; Name: 'Image/GIF'; Signature: GIF_HEADER), (ImageType: ifJPG; Name: 'Image/JPEG'; Signature: JPG_HEADER), (ImageType: ifPNG; Name: 'Image/PNG'; Signature: PNG_HEADER), (ImageType: ifBMP; Name: 'Image/BMP'; Signature: BMP_HEADER), (ImageType: ifTIF; Name: 'Image/TIFF'; Signature: TIF_HEADER), (ImageType: ifTIF; Name: 'Image/TIFF'; Signature: TIF_HEADER2), (ImageType: ifWMF; Name: 'Image/WMF'; Signature: WMF_HEADER), (ImageType: ifPSD; Name: 'Image/PSD'; Signature: PSD_HEADER)); type TImageType = (ifUnknown, ifJPG, ifGIF, ifBMP, ifPNG, ifPSD, ifTIF, ifWMF); TImageSignature = record ImageType: TImageType; Name: string; Signature: AnsiString; end; function CheckImageSignature(AStream: TStream; Signature: AnsiString; Offset: Integer): Boolean; var Buffer: AnsiString; Count: Integer; BytesRead: Integer; begin Result := False; try Count := Length(Signature); AStream.Position := Offset; SetLength(Buffer, Count); BytesRead := AStream.Read(Buffer[1], Count); Result := (BytesRead = Count) and (Buffer = Signature); except end; end; function GetImageType(FileName: string): TImageSignature; var Stream: TFileStream; MemStr: TMemoryStream; i: Integer; begin Result.ImageType := ifUnknown; Stream := TFileStream.Create(FileName, fmOpenRead); try MemStr := TMemoryStream.Create; try MemStr.CopyFrom(Stream, 5); if MemStr.Size > 4 then begin Result.ImageType := ifUnknown; for i := Low(Signatures) to High(Signatures) do begin if CheckImageSignature(MemStr, Signatures[i].Signature, 0) then begin Result.ImageType := Signatures[i].ImageType; Result.Name := Signatures[i].Name; Break; end; end; end; finally MemStr.Free; end; finally Stream.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var FileName: string; ImgSig: TImageSignature; begin if OpenDialog1.Execute then begin FileName := OpenDialog1.FileName; ImgSig := GetImageType(FileName); Label1.Caption := ImgSig.Name; end; end; |
AW: Bildformat anhand Header erkennen
Und das ganze jetzt noch in einer schönen Klasse. :wink:
|
AW: Bildformat anhand Header erkennen
Zitat:
|
AW: Bildformat anhand Header erkennen
Mal sehen, ob ich morgen dazu komme.
|
AW: Bildformat anhand Header erkennen
Danke für den Schönen Code habe es aber schon hinbekommen.
Geht auch einfacher :
Delphi-Quellcode:
So das Funkt nur wenn die Windows Unit eingebunden ist für die Leute die Konsolenanwendungen schreiben :-D
const
GifType = 18759; //uses gifimg BitmapType = 19778; PngType = 20617; //uses pngimage JpegType = 55551; //uses jpeg var InfoHeader : TBitmapFileHeader; Stream : TMemoryStream; begin if Assigned(S) then begin S.Read(InfoHeader,SizeOf(TBitmapFileHeader)); S.Position := 0; case InfoHeader.bfType of PngType: begin end; JpegType: begin end; GifType: begin end; BitmapType: begin end; end; end; |
AW: Bildformat anhand Header erkennen
TBitmapFileHeader ist nur für Datein mit Typ "BM" gedacht. TBitmapFileHeader.bfType gibt auch nur immer 2 bytes zurück.
Die Signaturen von JPEG etc. sind jedoch länger und so werden die Dateien unter Umständen nicht korrekt erkannt. Somit bevorzuge ich meine Variante, auch wenn sie etwas länger ist. Anbei noch eine leicht abgeänderte Variante:
Delphi-Quellcode:
type
TImageType = (ifUnknown, ifJPG, ifGIF, ifBMP, ifPNG, ifPSD, ifTIF, ifWMF); type TImageSignature = record ImgType: TImageType; ImgName: string; ImgSig: AnsiString; end; function GetImageType(FileName: string): TImageSignature; const MAX_SIGNATURES = 8; Signatures: array[0..MAX_SIGNATURES] of TImageSignature = ( (ImgType: ifGIF; ImgName: 'Image/GIF'; ImgSig: #$47#$49#$46#$38), (ImgType: ifJPG; ImgName: 'Image/JPEG'; ImgSig: #$FF#$D8#$FF#$E0), (ImgType: ifJPG; ImgName: 'Image/JPEG'; ImgSig: #$FF#$D8#$FF#$E1), (ImgType: ifPNG; ImgName: 'Image/PNG'; ImgSig: #$89#$50#$4E#$47), (ImgType: ifBMP; ImgName: 'Image/BMP'; ImgSig: #$42#$4D), (ImgType: ifTIF; ImgName: 'Image/TIFF'; ImgSig: #$49#$49#$2A), (ImgType: ifTIF; ImgName: 'Image/TIFF'; ImgSig: #$4D#$4D#$00), (ImgType: ifWMF; ImgName: 'Image/WMF'; ImgSig: #$D7#$CD#$C6#$9A), (ImgType: ifPSD; ImgName: 'Image/PSD'; ImgSig: #$38#$42#$50#$53)); function CheckImageSignature(AStream: TStream; Signature: AnsiString; Offset: Integer): Boolean; var Buffer: AnsiString; Count: Integer; BytesRead: Integer; begin Result := False; try Count := Length(Signature); AStream.Position := Offset; SetLength(Buffer, Count); BytesRead := AStream.Read(Buffer[1], Count); Result := (BytesRead = Count) and (Buffer = Signature); except end; end; var Stream: TFileStream; MemStr: TMemoryStream; i: Integer; begin FillChar(Result, SizeOf(Result), 0); Result.ImgType := ifUnknown; Stream := TFileStream.Create(FileName, fmOpenRead); try MemStr := TMemoryStream.Create; try MemStr.CopyFrom(Stream, 5); if MemStr.Size > 4 then begin for i := Low(Signatures) to High(Signatures) do begin if CheckImageSignature(MemStr, Signatures[i].ImgSig, 0) then begin Result.ImgType := Signatures[i].ImgType; Result.ImgName := Signatures[i].ImgName; Result.ImgSig := Signatures[i].ImgSig; Break; end; end; end; finally MemStr.Free; end; finally Stream.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var FileName: string; ImgSig: TImageSignature; begin if OpenDialog1.Execute then begin FileName := OpenDialog1.FileName; ImgSig := GetImageType(FileName); case ImgSig.ImgType of ifPNG: begin //... end; ifJPG: begin //... end; ifGif: begin //... end; ifBMP: begin //... end; end; end; end; |
AW: Bildformat anhand Header erkennen
Bis auf eine kleine Änderung
Delphi-Quellcode:
hab' ich das gleich in meine FileUtils mit rein genommen. Danke für's zusammenstellen.
MAX_SIGNATURES = 9;
Signatures: array[0..(MAX_SIGNATURES -1)] of TImageSignature = Finde auch nicht, dass alles in eine Klasse gehört, selbst wenn es sich manchmal anbietet. Seit ich viel mit C# arbeite, bin ich sehr froh, das man in Delphi da freier ist. Passt zumindest bei mir als Funktion besser zu den anderen kleinen File-Funktionen. |
AW: Bildformat anhand Header erkennen
Würde es in meinem Fall auch nur die ersten 2 Bytes tun?
Weil die daten lade ich sowieso mit den entsprechenden TGraphic Klassen dann, Wie z.b. TJpegImage oder TPngImage. ob es dann die signatur von eine jpg oder jpeg hat ist doch in dem Fall egal oder nicht? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 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-2025 by Thomas Breitkreuz