AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Bildformat anhand Header erkennen
Thema durchsuchen
Ansicht
Themen-Optionen

Bildformat anhand Header erkennen

Ein Thema von NickelM · begonnen am 29. Okt 2010 · letzter Beitrag vom 31. Okt 2010
Antwort Antwort
Seite 1 von 2  1 2      
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#1

Bildformat anhand Header erkennen

  Alt 29. Okt 2010, 17:43
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 oder suche unter dem falschen Begriff.

Gruss NickelM
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: Bildformat anhand Header erkennen

  Alt 29. Okt 2010, 18:36
Wie lädst du denn das Bild?
Und hast du PNG überhaupt in dein Programm eingebunden?

siehe Abschnitte "Dateikopf":
http://de.wikipedia.org/wiki/Portable_Network_Graphics
http://de.wikipedia.org/wiki/Windows_Bitmap
$2B or not $2B
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#3

AW: Bildformat anhand Header erkennen

  Alt 29. Okt 2010, 22:45
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
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.

Geändert von NickelM (29. Okt 2010 um 23:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#4

AW: Bildformat anhand Header erkennen

  Alt 30. Okt 2010, 01:05
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;
Thomas

Geändert von toms (30. Okt 2010 um 01:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Bildformat anhand Header erkennen

  Alt 30. Okt 2010, 01:15
Und das ganze jetzt noch in einer schönen Klasse.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#6

AW: Bildformat anhand Header erkennen

  Alt 30. Okt 2010, 01:23
Und das ganze jetzt noch in einer schönen Klasse.
Das sei dem Coder überlassen was aus dem "Rohcode" angestellt wird...
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

AW: Bildformat anhand Header erkennen

  Alt 30. Okt 2010, 01:29
Mal sehen, ob ich morgen dazu komme.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#8

AW: Bildformat anhand Header erkennen

  Alt 31. Okt 2010, 01:35
Danke für den Schönen Code habe es aber schon hinbekommen.
Geht auch einfacher :

Delphi-Quellcode:
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;
So das Funkt nur wenn die Windows Unit eingebunden ist für die Leute die Konsolenanwendungen schreiben
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#9

AW: Bildformat anhand Header erkennen

  Alt 31. Okt 2010, 07:00
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;
Thomas

Geändert von toms (31. Okt 2010 um 07:40 Uhr)
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#10

AW: Bildformat anhand Header erkennen

  Alt 31. Okt 2010, 10:14
Bis auf eine kleine Änderung
Delphi-Quellcode:
  MAX_SIGNATURES = 9;
  Signatures: array[0..(MAX_SIGNATURES -1)] of TImageSignature =
hab' ich das gleich in meine FileUtils mit rein genommen. Danke für's zusammenstellen.

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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz