Fala galera da programação, tudo beleza?
Se você estiver armazenando uma imagem em um campo de blob ou similar, acho que não é incomum ter outro campo que especifique o tipo gráfico. Realmente, porém, não há necessidade, uma vez que os formatos gráficos comuns (“common” em um contexto Delphi pelo menos) têm assinaturas distintas que permitem sua fácil identificação.
Bitmap do Windows (BMP): os caracteres ASCII ‘BM’.
GIF: os três caracteres ASCII ‘GIF’.
JPEG: um indicador ‘new marker’ ($FF) seguido de um marcador ‘start of image’ ($D8).
PNG: por ordem, os seguintes oito caracteres ASCII – #137, ‘P’, ‘N’, ‘G’, #13, #10, #26 e #10.
TIFF: ‘II’ ou ‘MM’ seguidos de $002A ou $2A00, respetivamente.
Ícone do Windows (ICO): a segunda palavra tem o valor $0001.
Windows Metafile (WMF): o primeiro DWORD tem o valor $9AC6CDD7.
Windows Enhanced Metafile (EMF): o primeiro DWORD deve ser igual a $00000001, seguido de $464D4520 (ou seja, ‘EMF’ quando lido de trás para a frente) no décimo primeiro.
Deste conjunto “standard”, o formato ICO é obviamente um pouco indeterminado quando se trata de fazer uma verificação rápida, mas o resto é único o suficiente. Na prática, a falta de uma assinatura adequada para a ICO significa apenas que você deve testar por último.
De qualquer forma, a partir destas informações, podemos chegar no seguinte código:
uses SysUtils, Classes, Graphics, GIFImg, JPEG, PngImage; const MinGraphicSize = 44; //we may test up to & including the 11th longword function FindGraphicClass(const Buffer; const BufferSize: Int64; out GraphicClass: TGraphicClass): Boolean; overload; var LongWords: array[Byte] of LongWord absolute Buffer; Words: array[Byte] of Word absolute Buffer; begin GraphicClass := nil; Result := False; if BufferSize < MinGraphicSize then Exit; case Words[0] of $4D42: GraphicClass := TBitmap; $D8FF: GraphicClass := TJPEGImage; $4949: if Words[1] = $002A then GraphicClass := TWicImage; //i.e., TIFF $4D4D: if Words[1] = $2A00 then GraphicClass := TWicImage; //i.e., TIFF else if Int64(Buffer) = $A1A0A0D474E5089 then GraphicClass := TPNGImage else if LongWords[0] = $9AC6CDD7 then GraphicClass := TMetafile else if (LongWords[0] = 1) and (LongWords[10] = $464D4520) then GraphicClass := TMetafile else if StrLComp(PAnsiChar(@Buffer), 'GIF', 3) = 0 then GraphicClass := TGIFImage else if Words[1] = 1 then GraphicClass := TIcon; end; Result := (GraphicClass <> nil); end; function FindGraphicClass(Stream: TStream; out GraphicClass: TGraphicClass): Boolean; overload; var Buffer: PByte; CurPos: Int64; BytesRead: Integer; begin if Stream is TCustomMemoryStream then begin Buffer := TCustomMemoryStream(Stream).Memory; CurPos := Stream.Position; Inc(Buffer, CurPos); Result := FindGraphicClass(Buffer^, Stream.Size - CurPos, GraphicClass); Exit; end; GetMem(Buffer, MinGraphicSize); try BytesRead := Stream.Read(Buffer^, MinGraphicSize); Stream.Seek(-BytesRead, soCurrent); Result := FindGraphicClass(Buffer^, BytesRead, GraphicClass); finally FreeMem(Buffer); end; end;
As classes gráficas retornadas aqui são as que estão disponíveis para versões recentes do Delphi. Então dependendo de qual versão específica do Delphi e bibliotecas de terceiros você usa, os que são mais apropriados para si mesmo podem diferir, é claro.
Com a função FindGraphicClass em mãos, podemos então escrever uma rotina de utilitário adicional que carrega uma instância TPicture de um TBlobField conforme o exemplo a seguir:
uses Consts, DB; procedure LoadPictureFromBlobField(Field: TBlobField; Dest: TPicture); var Graphic: TGraphic; GraphicClass: TGraphicClass; Stream: TMemoryStream; begin Graphic := nil; Stream := TMemoryStream.Create; try Field.SaveToStream(Stream); if Stream.Size = 0 then begin Dest.Assign(nil); Exit; end; if not FindGraphicClass(Stream.Memory^, Stream.Size, GraphicClass) then raise EInvalidGraphic.Create(SInvalidImage); Graphic := GraphicClass.Create; Stream.Position := 0; Graphic.LoadFromStream(Stream); Dest.Assign(Graphic); finally Stream.Free; Graphic.Free; end; end;
Esta última rotina pode então ser usada assim (onde “cdsPicture” e “Image1” são um TBlobField e TImage respectivamente que são criados no momento do design):
procedure TForm1.btnTestLoadPictureClick(Sender: TObject); begin LoadPictureFromBlobField(cdsPicture, Image1.Picture); end;
Em resumo, ser capaz de detectar o formato de arquivo de uma imagem é uma habilidade valiosa ao trabalhar com manipulação de imagens em Delphi. Esta capacidade não apenas permite que você carregue diferentes tipos de imagens em sua aplicação de forma eficiente, mas também facilita a validação de arquivos de imagem para garantir que estejam no formato esperado.
Ao examinar os primeiros bytes de um arquivo de imagem e compará-los com os padrões de assinatura de diferentes formatos gráficos, você pode determinar rapidamente o tipo de imagem que está lidando. Esta abordagem simples, usando Delphi, permite uma detecção precisa e eficaz de formatos gráficos, fornecendo uma base sólida para o desenvolvimento de aplicativos robustos e eficientes que lidam com imagens.
Ao implementar essa técnica em seus projetos, você estará melhor equipado para lidar com uma variedade de formatos de imagem e garantir uma experiência de usuário suave e consistente em suas aplicações Delphi.
Beleza pessoal? Espero que possa ajudar.
Dúvidas ou sugestões? Deixe o seu comentário.
Um abraço e até o próximo post. Valeu!
Fonte: https://delphihaven.wordpress.com/2011/01/22/tip-detecting-graphic-formats/
#Delphi
#DesenvolvimentoDeSoftware
#ManipulaçãoDeImagens
#GiovaniDaCruz
Está gostando do conteúdo?
Considere pagar um cafezinho para nossa equipe!