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;
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:
extract the class name from the stream.
instantiate the specified TGraphic
-derived class type.
load the remaining stream into the object.
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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With