Recent

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

SaraT

  • Full Member
  • ***
  • Posts: 121
  • 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: 3197
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
  20.        read(txt,ch);
  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.  

Your picture is now in pic.png  - your icon as exspected.

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

SaraT

  • Full Member
  • ***
  • Posts: 121
  • 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
  20.        read(txt,ch);
  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.  

Your picture is now in pic.png  - your icon as exspected.

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: 4196
    • Personal webpage
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
  3.        read(txt,ch);
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

  • Full Member
  • ***
  • Posts: 121
  • 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
  3.        read(txt,ch);
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;
  3. png.LoadFromStream(stream);
  4. frmIndex.Image1.Picture.PNG.Assign(png);

Thnx again :)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • 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;
  81.     Input.ReadBuffer(Buffer, Todo);
  82.     S := '';
  83.     for i := 0 to (Todo- 1) do
  84.       S := S + IntToHex(Buffer[i], 2);
  85.     Output.Add(S);
  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

  • Full Member
  • ***
  • Posts: 121
  • 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;
  81.     Input.ReadBuffer(Buffer, Todo);
  82.     S := '';
  83.     for i := 0 to (Todo- 1) do
  84.       S := S + IntToHex(Buffer[i], 2);
  85.     Output.Add(S);
  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: 4196
    • Personal webpage
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.  :P
Conscience is the debugger of the mind

winni

  • Hero Member
  • *****
  • Posts: 3197
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

  • Full Member
  • ***
  • Posts: 121
  • 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

Thanks for your patience.
   
« Last Edit: February 25, 2020, 05:10:56 am by SaraT »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5448
  • 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][+][-]
  1. procedure TPicture.ReadData(Stream: TStream);
  2. var
  3.   GraphicClassName: Shortstring;
  4.   NewGraphic: TGraphic;
  5.   GraphicClass: TGraphicClass;
  6.   ok: boolean;
  7. begin
  8.   Stream.Read(GraphicClassName[0], 1);
  9.   Stream.Read(GraphicClassName[1], length(GraphicClassName));
  10.   GraphicClass := GetPicFileFormats.FindClassName(GraphicClassName);
  11.   NewGraphic := nil;
  12.   if GraphicClass <> nil then begin
  13.     NewGraphic := GraphicClass.Create;
  14.     ok:=false;
  15.     try
  16.       NewGraphic.ReadData(Stream);
  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
  13.     s.Read(GraphicClassName[0], 1);
  14.     s.Read(GraphicClassName[1], Length(GraphicClassName));
  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
  22.       NewGraphic.ReadData(s);
  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

  • Hero Member
  • *****
  • Posts: 633
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;
  33.   stream.Read(GraphicClassName[0], 1);
  34.   stream.Read(GraphicClassName[1], Length(GraphicClassName));
  35.   if GraphicClassName <> 'TPortableNetworkGraphic' then
  36.     raise Exception.CreateFmt('Unknown graphic class: %s', [GraphicClassName]);
  37.   stream.Read(i, 4);
  38.   // assert(stream.Size-stream.Position=i,'size error');
  39.   Picture := TPicture.Create;
  40.   Picture.LoadFromStream(stream);
  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

  • Full Member
  • ***
  • Posts: 121
  • 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: 98
    • Graphic and web designer
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.
Graphic & web designer

 

TinyPortal © 2005-2018