### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: SOLVED: Convert glyph data and assign it to TBitBtn  (Read 1384 times)

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #15 on: February 21, 2020, 11:33:43 pm »
Thanks guys
I hope one of you that have been working with Lazarus for many years
can share with us (newest) the trick to to this. (in your free time, oviously)

Best regards

#### winni

• Hero Member
• Posts: 1140
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #16 on: February 22, 2020, 01:54:16 am »
Hi!

Dirty midnight  hack:

Copy the Picture.Data as you showed to the current directory of your Lazarus project.
Call it pic.data.

Then use this code:

Code: Pascal  [Select]
1. procedure PicFromLFMData;
2. const fIn = 'pic.data';
3.       fOut='pic.png';
4.       hex = ['0'..'9','A'..'F'];
5. var ch,c1,c2 : char;
6.     atWork,flipflop: Boolean;
7.     txt: TextFile;
8.     f : file of byte;
9.     len : Integer = -1;
10.     count : integer;
11.
12.     begin
13.     assignFile (txt,fIn);
14.     reset (txt);
15.     assignFile(f,fOut);
16.     rewrite(f);
17.     atWork := false;
18.     while not eof (txt) do
19.        begin
21.        if ch = '{' then begin atWork := true; flipFlop := false; continue; end;
22.        if ch = '}' then atWork := false;
23.        if (ch in hex) and atWork then
24.          begin
25.          if not flipFlop then c1 := ch else
26.             begin
27.             c2 := ch;
28.             if len = -1 then
29.                begin
30.                len := StrToInt ('\$'+c1+c2)+4; // length integer
31.                count := 0;
32.                end;
33.             if count > len then write (f,StrToInt('\$'+c1+c2));
34.             inc(count);
35.             end;
36.           flipflop:= not flipflop;
37.          end; // in
38.        end;
39.      closeFile(txt);
40.      closeFile(f);
41.      showMessage ('done');
42.     end;
43.
44.

Winni
« Last Edit: February 22, 2020, 02:03:44 am by winni »

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #17 on: February 23, 2020, 10:41:35 pm »
Hi!

Dirty midnight  hack:

Copy the Picture.Data as you showed to the current directory of your Lazarus project.
Call it pic.data.

Then use this code:

Code: Pascal  [Select]
1. procedure PicFromLFMData;
2. const fIn = 'pic.data';
3.       fOut='pic.png';
4.       hex = ['0'..'9','A'..'F'];
5. var ch,c1,c2 : char;
6.     atWork,flipflop: Boolean;
7.     txt: TextFile;
8.     f : file of byte;
9.     len : Integer = -1;
10.     count : integer;
11.
12.     begin
13.     assignFile (txt,fIn);
14.     reset (txt);
15.     assignFile(f,fOut);
16.     rewrite(f);
17.     atWork := false;
18.     while not eof (txt) do
19.        begin
21.        if ch = '{' then begin atWork := true; flipFlop := false; continue; end;
22.        if ch = '}' then atWork := false;
23.        if (ch in hex) and atWork then
24.          begin
25.          if not flipFlop then c1 := ch else
26.             begin
27.             c2 := ch;
28.             if len = -1 then
29.                begin
30.                len := StrToInt ('\$'+c1+c2)+4; // length integer
31.                count := 0;
32.                end;
33.             if count > len then write (f,StrToInt('\$'+c1+c2));
34.             inc(count);
35.             end;
36.           flipflop:= not flipflop;
37.          end; // in
38.        end;
39.      closeFile(txt);
40.      closeFile(f);
41.      showMessage ('done');
42.     end;
43.
44.

Winni

Hallo Winni... the picture data is in a text file. How can I load the picture data BUT from a variable?
Sorry, I wasn't able to make it works and would not like my code depends on a file. Hope it is possible.

Thanks.
« Last Edit: February 23, 2020, 10:45:15 pm by SaraT »

#### circular

• Hero Member
• Posts: 3191
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #18 on: February 23, 2020, 11:13:06 pm »
You get the data from a string variable instead of file you more or less need to replace
Code: Delphi  [Select]
1.     while not eof (txt) do
2.        begin
by
Code: Delphi  [Select]
1.     for i := 1 to length(strData) do
2.        begin
3.        ch := strData[i];
where strData is your string variable.

And remove the txt variable and what refers to it.
Conscience is the debugger of the mind

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #19 on: February 24, 2020, 12:32:04 am »
You get the data from a string variable instead of file you more or less need to replace
Code: Delphi  [Select]
1.     while not eof (txt) do
2.        begin
by
Code: Delphi  [Select]
1.     for i := 1 to length(strData) do
2.        begin
3.        ch := strData[i];
where strData is your string variable.

And remove the txt variable and what refers to it.

Thanks circular. The below code is to write to file.
Code: Pascal  [Select]
1. write (f,StrToInt('\$'+c1+c2));
How can I send the PNG to the TImage control?

I was trying with this but I got error.
Code: Pascal  [Select]
1. stream.Write(f, sizeOf(StrToInt('\$'+c1+c2)));
2. stream.Position:= 0;
4. frmIndex.Image1.Picture.PNG.Assign(png);

Thnx again

#### Handoko

• Hero Member
• Posts: 3438
• My goal: build my own game engine using Lazarus
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #20 on: February 24, 2020, 02:19:24 pm »
It seems you have problem using my functions. Here I show how to export image to a text file.

Code: Pascal  [Select]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
9.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     Button1: TButton;
16.     Image1: TImage;
17.     procedure Button1Click(Sender: TObject);
18.   end;
19.
20. var
21.   Form1: TForm1;
22.
23. implementation
24.
25. procedure StreamToHexStringFile(Input: TMemoryStream; const ConstName,
26.   FileName: string); forward;
27.
28. {\$R *.lfm}
29.
30. { TForm1 }
31.
32. procedure TForm1.Button1Click(Sender: TObject);
33. var
34.   aStream: TMemoryStream;
35. begin
36.   aStream := TMemoryStream.Create;
37.   Image1.Picture.SaveToStream(aStream);
38.   StreamToHexStringFile(aStream, 'ImageData', 'IMG.TXT');
39.   aStream.Free;
40.
41.   ShowMessage('The image has been exported to IMG.TXT' +LineEnding+
42.     'You can use it in your Pascal code by copy/pasting the text' +LineEnding+
43.     'directly or using the compiler directive {\$INCLUDE filename}.');
44. end;
45.
46. //----------------------------------------------------------------------
47.
48. procedure HexStringToStream(const Input: string; Output: TMemoryStream;
49.   OutputReturn: Boolean);
50. var
51.   Bookmark:   Int64;
52.   Buffer:     array of Byte;
53.   ResultSize: Integer;
54.   i:          Integer;
55. begin
56.   ResultSize := Input.Length div 2;
57.   SetLength(Buffer, ResultSize);
58.   HexToBin(PChar(Input), PChar(Buffer), ResultSize);
59.   Bookmark := Output.Position;
60.   for i := 0 to (ResultSize-1) do
61.     Output.WriteByte(Buffer[i]);
62.   if OutputReturn then
63.     Output.Position := Bookmark;
64. end;
65.
66. procedure StreamToHexStringList(Input: TMemoryStream; Output: TStringList);
67. var
68.   Buffer: array[0..31] of Byte;
69.   Remain: Integer;
70.   Todo:   Integer;
71.   S:      string;
72.   i:      Integer;
73. begin
74.   Input.Seek(0, soBeginning);
75.   Remain := Input.Size;
76.   while (Remain > 0) do
77.   begin
78.     Todo := 32;
79.     if (Remain < 32) then
80.       Todo := Remain;
82.     S := '';
83.     for i := 0 to (Todo- 1) do
84.       S := S + IntToHex(Buffer[i], 2);
86.     Remain := Remain - Todo;
87.   end;
88. end;
89.
90. procedure StreamToHexStringFile(Input: TMemoryStream; const ConstName,
91.   FileName: string);
92. var
93.   Buffer: TStringList;
94.   S:      string;
95.   i:      Integer;
96. begin
97.   Buffer := TStringList.Create;
98.   StreamToHexStringList(Input, Buffer);
99.   with Buffer do
100.   begin
101.     for i := 0 to (Count-1) do
102.     begin
103.       S := '    ' + '''' + Strings[i] + '''';
104.       case (i < Count-1) of
105.         True:  S := S + '+';
106.         False: S := S + ';';
107.       end;
108.       Buffer[i] := S;
109.     end;
110.     if (Count >= 0) then
111.     begin
112.       Insert(0, '  ' + ConstName + ' = ');
113.       Insert(0, 'const');
114.       SaveToFile(FileName);
115.     end;
116.     Free;
117.   end;
118. end;
119.
120. end.

There are 3 functions, I let you to figure out yourself how to use the others.

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #21 on: February 24, 2020, 04:22:22 pm »
It seems you have problem using my functions. Here I show how to export image to a text file.

Code: Pascal  [Select]
1. unit Unit1;
2.
3. {\$mode objfpc}{\$H+}
4.
5. interface
6.
7. uses
8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
9.
10. type
11.
12.   { TForm1 }
13.
14.   TForm1 = class(TForm)
15.     Button1: TButton;
16.     Image1: TImage;
17.     procedure Button1Click(Sender: TObject);
18.   end;
19.
20. var
21.   Form1: TForm1;
22.
23. implementation
24.
25. procedure StreamToHexStringFile(Input: TMemoryStream; const ConstName,
26.   FileName: string); forward;
27.
28. {\$R *.lfm}
29.
30. { TForm1 }
31.
32. procedure TForm1.Button1Click(Sender: TObject);
33. var
34.   aStream: TMemoryStream;
35. begin
36.   aStream := TMemoryStream.Create;
37.   Image1.Picture.SaveToStream(aStream);
38.   StreamToHexStringFile(aStream, 'ImageData', 'IMG.TXT');
39.   aStream.Free;
40.
41.   ShowMessage('The image has been exported to IMG.TXT' +LineEnding+
42.     'You can use it in your Pascal code by copy/pasting the text' +LineEnding+
43.     'directly or using the compiler directive {\$INCLUDE filename}.');
44. end;
45.
46. //----------------------------------------------------------------------
47.
48. procedure HexStringToStream(const Input: string; Output: TMemoryStream;
49.   OutputReturn: Boolean);
50. var
51.   Bookmark:   Int64;
52.   Buffer:     array of Byte;
53.   ResultSize: Integer;
54.   i:          Integer;
55. begin
56.   ResultSize := Input.Length div 2;
57.   SetLength(Buffer, ResultSize);
58.   HexToBin(PChar(Input), PChar(Buffer), ResultSize);
59.   Bookmark := Output.Position;
60.   for i := 0 to (ResultSize-1) do
61.     Output.WriteByte(Buffer[i]);
62.   if OutputReturn then
63.     Output.Position := Bookmark;
64. end;
65.
66. procedure StreamToHexStringList(Input: TMemoryStream; Output: TStringList);
67. var
68.   Buffer: array[0..31] of Byte;
69.   Remain: Integer;
70.   Todo:   Integer;
71.   S:      string;
72.   i:      Integer;
73. begin
74.   Input.Seek(0, soBeginning);
75.   Remain := Input.Size;
76.   while (Remain > 0) do
77.   begin
78.     Todo := 32;
79.     if (Remain < 32) then
80.       Todo := Remain;
82.     S := '';
83.     for i := 0 to (Todo- 1) do
84.       S := S + IntToHex(Buffer[i], 2);
86.     Remain := Remain - Todo;
87.   end;
88. end;
89.
90. procedure StreamToHexStringFile(Input: TMemoryStream; const ConstName,
91.   FileName: string);
92. var
93.   Buffer: TStringList;
94.   S:      string;
95.   i:      Integer;
96. begin
97.   Buffer := TStringList.Create;
98.   StreamToHexStringList(Input, Buffer);
99.   with Buffer do
100.   begin
101.     for i := 0 to (Count-1) do
102.     begin
103.       S := '    ' + '''' + Strings[i] + '''';
104.       case (i < Count-1) of
105.         True:  S := S + '+';
106.         False: S := S + ';';
107.       end;
108.       Buffer[i] := S;
109.     end;
110.     if (Count >= 0) then
111.     begin
112.       Insert(0, '  ' + ConstName + ' = ');
113.       Insert(0, 'const');
114.       SaveToFile(FileName);
115.     end;
116.     Free;
117.   end;
118. end;
119.
120. end.

There are 3 functions, I let you to figure out yourself how to use the others.

Many thank Handoko, your code works well

The case is that nobody has understood that I want to assign the picture data from a String to TImage
Not from a TImage to file because we already have the image data.

That's all, convert the string and assign it to the TImage(not file text to TImage).

Thanks again.

#### circular

• Hero Member
• Posts: 3191
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #22 on: February 24, 2020, 07:36:36 pm »
The case is that nobody has understood that I want to assign the picture data from a String to TImage
Not from a TImage to file because we already have the image data.
I think each person is in a better position to know if they understood my dear.
Conscience is the debugger of the mind

#### winni

• Hero Member
• Posts: 1140
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #23 on: February 24, 2020, 10:55:21 pm »
Hi!

You are quiete unclear. To lift your secrets:

* From where are the string data? From an lfm file? Then cicular gave you the answer.

* Why do want to do that if you got the bitmap data already. Just for fun?

I can't see no reason for you're action.

Winni

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #24 on: February 25, 2020, 05:07:38 am »
Sorry guys, your answers are ok. But all your codes work with the Picture data from a file
but what I want is load the Picture data from a variable.

Lets say:

Code: Pascal  [Select]
1. Var
2.   picData : String;
3.
4. Begin
5.
6. picData := '{' +
7.     '1754506F727461626C654E6574776F726B477261706869634707000089504E47...'

The Picture data is loaded from a variable, not from a text file.
I dont want to use any external file. I hope I am speaking clearly

« Last Edit: February 25, 2020, 05:10:56 am by SaraT »

#### PascalDragon

• Hero Member
• Posts: 1109
• Compiler Developer
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #25 on: February 25, 2020, 09:41:44 am »
Here is how TPicture reads the data from the LFM stream:

Code: Pascal  [Select]
2. var
3.   GraphicClassName: Shortstring;
4.   NewGraphic: TGraphic;
5.   GraphicClass: TGraphicClass;
6.   ok: boolean;
7. begin
10.   GraphicClass := GetPicFileFormats.FindClassName(GraphicClassName);
11.   NewGraphic := nil;
12.   if GraphicClass <> nil then begin
13.     NewGraphic := GraphicClass.Create;
14.     ok:=false;
15.     try
17.       ok:=true;
18.     finally
19.       if not ok then NewGraphic.Free;
20.     end;
21.   end;
22.   FGraphic.Free;
23.   FGraphic := NewGraphic;
24.   if NewGraphic <> nil then begin
25.     NewGraphic.OnChange := @Changed;
26.     NewGraphic.OnProgress := @Progress;
27.   end;
28.   Changed(Self);
29. end;

You could try to adjust the code for your purpose though you'll have to roll your own registry of graphic types as GetPicFileFormats is private to the Graphics unit.

Here's a proof of concept (untested):

Code: Pascal  [Select]
1. var
2.   picdata: String = '{' +
3.     '17545 …';
4.   s: TStringStream;
5.   GraphicClassName: String;
6.   NewGraphic: TGraphic;
7.   GraphicClass: TGraphicClass;
8.   ok: Boolean;
9.   pic: TPicture;
10. begin
11.   s := TStringStream.Create(picdata);
12.   try
15.     if GraphicClassName = 'TPortableNetworkGraphic' then
16.       GraphicClass := TPortableNetworkGraphic
17.     else
18.       raise Exception.CreateFmt('Unknown graphic class: %s', [GraphicClassName]);
19.     NewGraphic := GraphicClass.Create;
20.     ok := False;
21.     try
23.       ok := True;
24.     finally
25.       if not ok then
26.         NewGraphic.Free;
27.     end;
28.     pic := TPicture.Create(Nil);
29.     try
30.       pic.Graphic := NewGraphic;
31.       YourButton.Glyph := pic.Bitmap;
32.     finally
33.       pic.Free;
34.     end;
35.   finally
36.     s.Free;
37.   end;
38. end;

#### bytebites

• Full Member
• Posts: 247
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #26 on: February 25, 2020, 01:03:47 pm »
Combining from previous replies one reply more.
Code: Pascal  [Select]
1.
2. picData :=  '1754506F727461 ...';
3.
4. function convert(picData: string): TPicture;
5. var
6.   stream: TStringStream;
7.   ch: PChar;
8.   i, num: integer;
9.   Picture: TPicture;
10.   GraphicClassName: ShortString;
11.
12.   function tohex(p: PChar): byte;
13.   begin
14.     case p^ of
15.       '0'..'9': Result := Ord(p^) - 48;
16.       'A'..'F': Result := Ord(p^) - 55;
17.       else raise Exception.CreateFmt('Unexpected char: %s', [p^]);
18.     end;
19.   end;
20.
21. begin
22.   i := length(picData);
23.   ch := @picdata[1];
24.   stream := tstringstream.Create;
25.   while i > 0 do
26.   begin
27.     num := tohex(ch) * 16 + tohex(ch + 1);
28.     stream.Write(num, 1);
29.     ch := ch + 2;
30.     i := i - 2;
31.   end;
32.   stream.position := 0;
35.   if GraphicClassName <> 'TPortableNetworkGraphic' then
36.     raise Exception.CreateFmt('Unknown graphic class: %s', [GraphicClassName]);
38.   // assert(stream.Size-stream.Position=i,'size error');
39.   Picture := TPicture.Create;
41.   Result := Picture;
42.   stream.Free;
43. end;
44.
45. procedure TForm1.Button1Click(Sender: TObject);
46. var
47.   b: TPicture;
48. begin
49.   b := convert(picData);
50.   image1.Picture := b;
51.   BitBtn1.Glyph := b.Bitmap;
52.   b.Free;
53. end;
54.
55.

#### SaraT

• Jr. Member
• Posts: 81
• A little student
##### Re: Convert glyph data and assign it to TBitBtn
« Reply #27 on: February 25, 2020, 04:28:22 pm »
Many thanks guys
It worked finally

Happy coding

#### AsleyCruz

• Jr. Member
• Posts: 61
##### Re: SOLVED: Convert glyph data and assign it to TBitBtn
« Reply #28 on: February 25, 2020, 08:51:04 pm »
Amazing!
This would be useful to load PNG into custom components.
AsleyCruz - Graphic and apps designer
-
http://www.asleycruz.com/