如何将文本数据转换为图像?

时间:2016-08-03 15:24:20

标签: delphi

加载并成像到组件后,我可以看到Delphi将图像数据存储在DFM上。例如:

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

你可以看到它是一个小图像。如何在没有DFM的情况下获取此信息并使其成为图像,例如:

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;

3 个答案:

答案 0 :(得分:8)

在图像首先加载到TPicture.Graphic之前,您无法访问TPicture属性。

TPicture不支持从TStream加载数据(请参阅QC #12434: Add LoadFromStream() method to TPicture),因此您必须手动流式传输图像数据。

Picture.Data属性数据以UTF-8编码的ShortString开头,其中包含生成图像数据的TGraphic派生类的名称。在您的示例中,该类名编码为:

0954506E67496D616765

第一个字节(十六进制09)是类名(9)中的字节数,后面的9个字节(十六进制54 50 6E 67 49 6D 61 67 65)是类名的UTF-8八位字节( TPngImage),其余的流字节是实际的PNG图像数据。

所以,你需要:

  1. 从流中提取类名。

  2. 实例化指定的TGraphic派生类类型。

  3. 将剩余的流加载到对象中。

  4. 将对象分配到TPicture

  5. 例如:

    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.
    

答案 1 :(得分:2)

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;

答案 2 :(得分:0)

最近我有理由这么做,Delphi的更高版本(不确定引入的版本)具有LoadFromStream函数,因此我创建的函数如下。

from datetime import datetime, date
#first get current date
current_date = datetime.now().strftime('%Y-%m-%d');
timestamp = int(datetime.timestamp(datetime.strptime(current_date + ' 07:00:00', '%Y-%m-%d %H:%M:%S')))