Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert text data into an Image?

Tags:

delphi

Once you load and image into a component, I can see that Delphi store the image data on DFM, . Example:

object img1: TImage
  Left = 71
  Top = 2
  Width = 18
  Height = 18
  Picture.Data = {
    0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000
    001008060000001FF3FF610000000473424954080808087C0864880000000970
    485973000000750000007501E3C207650000001974455874536F667477617265
    007777772E696E6B73636170652E6F72679BEE3C1A000000EF4944415478DAAD
    923B0AC2401086B3D7100F6110B415FBD8AB60E323E62262632DF15158A8BDB6
    22D682E821C41B58C76F7003EB8A9A10073E36ECFCFB6766765514458E842258
    3A5083A2F38C136C6016C5422B94EC7336C7F7122A7081A3CE97A0000768A2BD
    BD1968F6E0428068FD2250AACE32863354ED4AE4701726D0B00F5B262BE8A199
    DA065BC893709D2F8189547045E7D906D2D79684FFC32064F1D0E5FE6E90B985
    CC434C738DF2F7BB7995691E521F163A1FC4262AE15396AA7650D6FBD2862F26
    EAC313B767A0741BE64DCD657E890C0C93500F3D8E616203C344CA6FEBAD5B2A
    03C364002D183D00658D8FCCCDEDEA100000000049454E44AE426082}
end

As you can see it's an small image. How it's possible to get this information without the DFM and make it an Image, for example:

procedure TForm12.btn2Click(Sender: TObject);
var
  img2: TImage;
  Loutput: TStream;
begin
  ObjectTextToBinary(TStringStream.Create(
     '0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000'
    + '001008060000001FF3FF610000000473424954080808087C0864880000000970'
    + '485973000000750000007501E3C207650000001974455874536F667477617265'
    + '007777772E696E6B73636170652E6F72679BEE3C1A000000EF4944415478DAAD'
    + '923B0AC2401086B3D7100F6110B415FBD8AB60E323E62262632DF15158A8BDB6'
    + '22D682E821C41B58C76F7003EB8A9A10073E36ECFCFB6766765514458E842258'
    + '3A5083A2F38C136C6016C5422B94EC7336C7F7122A7081A3CE97A0000768A2BD'
    + 'BD1968F6E0428068FD2250AACE32863354ED4AE4701726D0B00F5B262BE8A199'
    + 'DA065BC893709D2F8189547045E7D906D2D79684FFC32064F1D0E5FE6E90B985'
    + 'CC434C738DF2F7BB7995691E521F163A1FC4262AE15396AA7650D6FBD2862F26'
    + 'EAC313B767A0741BE64DCD657E890C0C93500F3D8E616203C344CA6FEBAD5B2A'
    + '03C364002D183D00658D8FCCCDEDEA100000000049454E44AE426082'), Loutput);
  img2 := TImage.Create(self);
  img2.Name := 'image2';
  img2.Left := 71;
  img2.Top := 30;
  img2.Width := 18;
  img2.Height := 18;
  img2.Picture.Graphic.LoadFromStream(Loutput);

  img1.Parent := Self;
end;
like image 876
Rodrigo Farias Rezino Avatar asked Dec 07 '22 21:12

Rodrigo Farias Rezino


2 Answers

You cannot access the TPicture.Graphic property until an image has been loaded into the TPicture first.

TPicture does not support loading data from a TStream (see QC #12434: Add LoadFromStream() method to TPicture), so you will have to stream the image data manually.

The Picture.Data property data starts with a UTF-8 encoded ShortString containing the name of the TGraphic-derived class that produced the image data. In your example, that class name is encoded as:

0954506E67496D616765

The first byte (hex 09) is the number of bytes in the class name (9), the following 9 bytes (hex 54 50 6E 67 49 6D 61 67 65) are the UTF-8 octets of the class name (TPngImage), and the remaining stream bytes are the actual PNG image data.

So, you need to:

  1. extract the class name from the stream.

  2. instantiate the specified TGraphic-derived class type.

  3. load the remaining stream into the object.

  4. assign the object to TPicture.

For example:

uses
  System.Classes,
  System.SysUtils,
  Vcl.Graphics,
  Vcl.Imaging.Jpeg,
  Vcl.Imaging.GIFImg,
  Vcl.Imaging.PngImage;

type
  TGraphicAccess = class(TGraphic)
  end;

procedure TForm12.btn2Click(Sender: TObject);
var
  Linput: String;
  Loutput: TMemoryStream;
  LclsName: ShortString;
  Lgraphic: TGraphic;
  img2: TImage;
begin
  Linput := '0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000'
          + '001008060000001FF3FF610000000473424954080808087C0864880000000970'
          + '485973000000750000007501E3C207650000001974455874536F667477617265'
          + '007777772E696E6B73636170652E6F72679BEE3C1A000000EF4944415478DAAD'
          + '923B0AC2401086B3D7100F6110B415FBD8AB60E323E62262632DF15158A8BDB6'
          + '22D682E821C41B58C76F7003EB8A9A10073E36ECFCFB6766765514458E842258'
          + '3A5083A2F38C136C6016C5422B94EC7336C7F7122A7081A3CE97A0000768A2BD'
          + 'BD1968F6E0428068FD2250AACE32863354ED4AE4701726D0B00F5B262BE8A199'
          + 'DA065BC893709D2F8189547045E7D906D2D79684FFC32064F1D0E5FE6E90B985'
          + 'CC434C738DF2F7BB7995691E521F163A1FC4262AE15396AA7650D6FBD2862F26'
          + 'EAC313B767A0741BE64DCD657E890C0C93500F3D8E616203C344CA6FEBAD5B2A'
          + '03C364002D183D00658D8FCCCDEDEA100000000049454E44AE426082';

  Loutput := TMemoryStream.Create;
  try
    Loutput.Size := Length(Linput) div 2;
    HexToBin(PChar(Linput), Loutput.Memory^, Loutput.Size);

    LclsName := PShortString(Loutput.Memory)^;

    Lgraphic := TGraphicClass(FindClass(UTF8Decode(LclsName))).Create;
    try
      Loutput.Position := 1 + Length(LclsName);
      TGraphicAccess(Lgraphic).ReadData(Loutput);

      img2 := TImage.Create(self);
      img2.Parent := Self;
      img2.Name := 'image2';
      img2.Left := 71;
      img2.Top := 30;
      img2.Width := 18;
      img2.Height := 18;
      img2.Picture.Assign(Lgraphic);
    finally
      Lgraphic.Free;
    end;
  finally
    Loutput.Free;
  end;
end;

initialization
  // this is not necessary for TPicture's own DFM streaming,
  // but it is necessary for manual streaming, unless you
  // implement your own classname lookups...
  // 
  RegisterClass(TMetafile);
  RegisterClass(TIcon);
  RegisterClass(TBitmap);
  RegisterClass(TWICImage);
  RegisterClass(TJpegImage);
  RegisterClass(TGifImage);
  RegisterClass(TPngImage);
  // and so on...
end.
like image 76
Remy Lebeau Avatar answered Jan 01 '23 04:01

Remy Lebeau


procedure TForm1.FormCreate(Sender: TObject);
const
  CONST_SIGN = '0954506E67496D616765';
var
  LString: String;
  LStart: Integer;
  LStringStream: TStringStream;
  LMem: TMemoryStream;
  R: TBytes;
begin
  LString :=
    '0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000'
    + '001008060000001FF3FF610000000473424954080808087C0864880000000970'
    + '485973000000750000007501E3C207650000001974455874536F667477617265'
    + '007777772E696E6B73636170652E6F72679BEE3C1A000000EF4944415478DAAD'
    + '923B0AC2401086B3D7100F6110B415FBD8AB60E323E62262632DF15158A8BDB6'
    + '22D682E821C41B58C76F7003EB8A9A10073E36ECFCFB6766765514458E842258'
    + '3A5083A2F38C136C6016C5422B94EC7336C7F7122A7081A3CE97A0000768A2BD'
    + 'BD1968F6E0428068FD2250AACE32863354ED4AE4701726D0B00F5B262BE8A199'
    + 'DA065BC893709D2F8189547045E7D906D2D79684FFC32064F1D0E5FE6E90B985'
    + 'CC434C738DF2F7BB7995691E521F163A1FC4262AE15396AA7650D6FBD2862F26'
    + 'EAC313B767A0741BE64DCD657E890C0C93500F3D8E616203C344CA6FEBAD5B2A'
    + '03C364002D183D00658D8FCCCDEDEA100000000049454E44AE426082';

  { Find and rid signature }

  LStart := Pos(CONST_SIGN, LString);

  if LStart = 0 then
    Exit;

  Delete(LString, LStart, Length(CONST_SIGN));

  { Main }

  LStringStream := TStringStream.Create(LString);
  LMem := TMemoryStream.Create;
  try
    { Prepare out array }
    SetLength(R, Length(LString) div SizeOf(Char));

    { Convert }
    HexToBin(PWideChar(LString), R, Length(LString) div SizeOf(Char));

    { Copy array to stream }
    LMem.WriteBuffer(R[0], Length(R));

    { Save stream with image as file }
    LMem.SaveToFile('xxx.png');

    { Load image from file }
    Image1.Picture.LoadFromFile('xxx.png');
  finally
    LStringStream.Free;
    LMem.Free;
  end;
end;
like image 39
Zam Avatar answered Jan 01 '23 03:01

Zam