Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#21

AW: wie art der daten in blob erkennen?

  Alt 1. Sep 2023, 13:00
@himitsu, ich kam mit Deiner Art leider nicht ganz zurecht aber habe es recht gut optimiert finde ich
Delphi-Quellcode:
program Project12;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Classes;

{$SCOPEDENUMS ON}
type
  TImageFormat = (Unknown, BMP, GIF, TIFF, JPEG, PNG, ICO);
{$SCOPEDENUMS OFF}

type
  TSignature = packed record
    Format: Integer;
    Offset: Integer;
    Signature: array of Integer;
  end;
  TSignatures = array of TSignature;

function GetSignatureList: TSignatures;
begin
  SetLength(Result, 14);
  Result[0].Format := Ord(TImageFormat.JPEG);
  Result[0].Offset := 0;
  Result[0].Signature := [$FF, $D8, $FF, $DB];
  Result[1].Format := Ord(TImageFormat.JPEG);
  Result[1].Offset := 0;
  Result[1].Signature := [$FF, $D8, $FF, $E0, $00, $10, $4A, $46];
  Result[2].Format := Ord(TImageFormat.JPEG);
  Result[2].Offset := 0;
  Result[2].Signature := [$49, $46, $00, $01];
  Result[3].Format := Ord(TImageFormat.JPEG);
  Result[3].Offset := 0;
  Result[3].Signature := [$FF, $D8, $FF, $EE];
  Result[4].Format := Ord(TImageFormat.JPEG);
  Result[4].Offset := 0;
  Result[4].Signature := [$FF, $D8, $FF, $E1, -1, -1, $45, $78];
  Result[5].Format := Ord(TImageFormat.JPEG);
  Result[5].Offset := 0;
  Result[5].Signature := [$69, $66, $00, $00];
  Result[6].Format := Ord(TImageFormat.JPEG);
  Result[6].Offset := 0;
  Result[6].Signature := [$FF, $D8, $FF, $E0];
  Result[7].Format := Ord(TImageFormat.PNG);
  Result[7].Offset := 0;
  Result[7].Signature := [$89, $50, $4E, $47, $0D, $0A, $1A, $0A];
  Result[8].Format := Ord(TImageFormat.GIF);
  Result[8].Offset := 0;
  Result[8].Signature := [$47, $49, $46, $38, $37, $61];
  Result[9].Format := Ord(TImageFormat.GIF);
  Result[9].Offset := 0;
  Result[9].Signature := [$47, $49, $46, $38, $39, $61];
  Result[10].Format := Ord(TImageFormat.BMP);
  Result[10].Offset := 0;
  Result[10].Signature := [$42, $4D];
  Result[11].Format := Ord(TImageFormat.ICO);
  Result[11].Offset := 0;
  Result[11].Signature := [$00, $00, $01, $00];
  Result[12].Format := Ord(TImageFormat.TIFF);
  Result[12].Offset := 0;
  Result[12].Signature := [$49, $49, $2A, $00];
  Result[13].Format := Ord(TImageFormat.TIFF);
  Result[13].Offset := 0;
  Result[13].Signature := [$4D, $4D, $00, $2A];
end;

function GetMaxSignatureSize(const ASignatures: TSignatures): Integer;
var
  i: Integer;
begin
  Result := 0;
  for i := Low(ASignatures) to High(ASignatures) do
    if (Length(ASignatures[i].Signature) > Result) then
      Result := Length(ASignatures[i].Signature);
end;

function CompareBytes(const AData: TBytes; const AOffset: Integer; const ASignature: array of Integer): Boolean;
var
  i: Integer;
begin
  Result := False;
  if (Length(AData) < (AOffset + Length(ASignature))) then
    Exit;
  for i := Low(ASignature) to High(ASignature) do
    if (ASignature[i] <> -1) then
      if (AData[i + AOffset] <> ASignature[i]) then
        Exit;
  Result := True;
end;

function GetBytesFormat(const AData: TBytes): TImageFormat;
var
  Signatures: TSignatures;
  i: Integer;
begin
  Signatures := GetSignatureList;
  for i := Low(Signatures) to High(Signatures) do
    if CompareBytes(AData, Signatures[i].Offset, Signatures[i].Signature) then
      Exit(TImageFormat(Signatures[i].Format));
  Result := TImageFormat.Unknown;
end;

function FilePartToBytes(const AFilename: string; const AOffset, ASize: Integer): TBytes;
var
  FileStream: TFileStream;
begin
  SetLength(Result, 0);
  FileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
  try
    if (FileStream.Size < (AOffset + ASize)) then
      Exit;
    SetLength(Result, ASize);
    FileStream.Position := AOffset;
    FileStream.ReadBuffer(Result[0], ASize);
  finally
    FileStream.Free;
  end;
end;

var
  Data: TBytes;
begin
  try
    if ParamCount > 0 then
      if FileExists(ParamStr(1)) then
        begin
          Data := FilePartToBytes(ParamStr(1), 0, GetMaxSignatureSize(GetSignatureList));
          case GetBytesFormat(Data) of
            TImageFormat.Unknown: WriteLn('Unknown');
            TImageFormat.JPEG: WriteLn('JPEG');
            TImageFormat.BMP: WriteLn('BMP');
            TImageFormat.PNG: WriteLn('PNG');
            TImageFormat.GIF: WriteLn('GIF');
            TImageFormat.TIFF: WriteLn('TIFF');
            TImageFormat.ICO: WriteLn('ICO');
          end;
          ReadLn;
        end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
@schorch666, die Idee den User entscheiden zu lassen mag ich, meine Idee basiert halt auf Signaturen um etwas automatisch anzukicken, wobei ich halt extrem eingeschränkt bin auf die paar Signaturen die man der Definition entnehmen kann, eine Klasse basierend auf dem Wiki wäre halt eine Variante einer möglichen automatisierung, wobei dann immer noch das zutun vom User notwendig sein kann um was-auch-immer-für-ein-format mit was-auch-immer zu öffnen.
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 1. Sep 2023 um 13:08 Uhr)
  Mit Zitat antworten Zitat