Recent

Author Topic: Text to images Generator (Console app generating bitmaps with text)  (Read 37651 times)

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: To Create images with text with GDI+ or what is used by linux
« Reply #75 on: November 12, 2023, 05:44:46 pm »
Thx. This is pretty clear code.
Thank you and please feel free to copy-paste from it in case it helps your project.

There are some other small items in there that could benefit your code when you would use them. I'll let you be the judge of that.

Quote
How is this semantics called when you assign the data in declaration block?

The ProcessItems variable is declared as a dynamic array. More information in the wiki and the manual

Dynamic arrays can (since Free Pascal 3.2) be declared as a constant expression see manual.

Quote
What is meanining of "@" in is it a pointer - reference? I did not see this yet, so I doubt that this is a
pointer mark.
It is indeed a pointer.

It is a special operator that takes the address of a variable, procedure or function, see manual

It is shorthand for the Addr function.

The reason to use it is because the GetLongOpts function from unit getopts requires to pass the first entry of a option array (parameter LongOpts).

The reason that I do not have my longopt array declared as a dynamic array (which is an option) is because the unit originates from before Free Pascal version 3.2 so the implementation is bound to an array index that starts with the number one (instead of zero which would normally be used for arrays). If you do not use an array starting with index one then the variable OptInd will be out of sync with the array, which works a bit confusing and counterproductive imho.

Quote
I've realized I should separate the image genaration and the save action.
I already see room for improvement(s) and clarity there, but I'll not bother you with it right now. Code can always be made cleaner later on.

If you have other questions then feel free to ask  :)
Today is tomorrow's yesterday.

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: To Create images with text with GDI+ or what is used by linux
« Reply #76 on: November 13, 2023, 12:34:10 am »
Hence the @ is the same as ^ or * but reffering to heap. It's quite long time ago when I tried to learn C/C++ but no success. Pascal is easier.

I see I will need to use dynamic arrays (not the static ones) to make the characters pretty working for all fonts, fonts and font sizes.

I will need to redesign.
Using options like
Code: [Select]
project.exe -bold -italic -characters="..." -font-family="Arial, Verdana" -font-size="9, 10, 12" -font-family="Times New Roman,Courier New" -font-size="14, 12, 10" to add more fonts to process

It could be possible to read the options from file, where every option would be place on a single line of file like that:

Code: [Select]
bold
italic
characters="..."
font-family="Arial, Verdana"
font-size="9, 10, 12"

font-family="Times New Roman,Courier New"
font-size="14, 12, 10"

It seems to be more clear.

Then I could run it like that:
Code: [Select]
program.exe config_file="project1.cfg"
« Last Edit: November 13, 2023, 10:35:02 am by barracuda »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: To Create images with text with GDI+ or what is used by linux
« Reply #77 on: November 13, 2023, 01:07:12 am »
Hence the @ is the same as ^ or * but reffering to heap. It's quite long when I tried to learn C/C++ but no success. Pascal is easier.
It indeed reads a lot easier in Pascal than it does for C/C++ (However, I am biased  :) )

On the other hand, if you are old-school, then you are probably not that familiar with new features such as the dynamic arrays, generics, etc. But they are quite easy to understand/grasp (at least when you start with a slow introduction).

Quote
I will need to redesign.
Using options like
Code: [Select]
project.exe -bold -italic -characters "..." -font-family "Arial,Verdana" -font-size "9, 10, 12" -font-family "Times New Roman,Courier New" -font-size "14, 12, 10" to add more fonts to process
Don't overthink/overcomplicate by wanting to do everything on a single command-run. The above is the same as:
project.exe -bold -italic -characters "..." -font-family "Arial,Verdana" -font-size "9, 10, 12"
project.exe -bold -italic -characters "..." -font-family "Times New Roman,Courier New" -font-size "14, 12, 10"

And yes there is some duplication there, but you can automate that in one of two ways:
- abstract the commandline parameter handling away from paramstr/paramcount. That way you can call the the parameter handling routine multiple times but with different options.
- use a script (or a small invoke utility) to call your program and which supplies the parameters. The duplicated parameters can be stored in a (shell) variable for re-use.

Actually, when I started implementing I had your arrays stored inside an inifile for easy editing/adding new sets of arrays (fonts, texts, fontsize, foldername) and loading these arrays from that file. I removed that functionality as you did not seem to focus on extending those array (perhaps later you will, I don't know  :) ) .

You could do something similar for the individual character drawing so that for longer sets of characters and family names you can simply add them to such an ini-file. Dunno, if something like that could help you out. I am missing the big picture here. I simply can't imagine that you would want to do something like you showed in your example, let's say, a hundred times for 80 different font families applying all 4 different font-styles and doing so for 800 different (unicode) characters.
Today is tomorrow's yesterday.

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: To Create images with text with GDI+ or what is used by linux
« Reply #78 on: November 13, 2023, 10:38:57 am »
Yes the long command line is not good solution so I would prefer to create a simple cfg file because that is the best approach. I can have like 10 cfgs with examples for everyone. Simple and easy. So I would probably use TStringList and TStringList.loadfromFile ... as this is what I used in Delphi 7, but I see you're using new approaches.

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: To Create images with text with GDI+ or what is used by linux
« Reply #79 on: November 13, 2023, 12:41:18 pm »
I think I am almost done with new parsing function which prepares the arguments read either from command line or from the file. I changed a little bit the specification (not reflected in manual) so the "-" before a parametr is not a need now, but it should if present, it will crop it.

I have question in the section of last block, where my questio is on easy key access solution.

Code: [Select]
for i := 0 to Pars.Count-1 do
  begin
    if Pars.Values[i][1]='-' then
      Pars.Values[i]:=copy(Pars.Values[i],2,length(Pars.Values[i]));
    Pars.Values[i] := ToLower+'='+AnsiDequotedStr(Pars.Values[i],'"'));
  end;
Code: [Select]
Pars.Values[i] ... to change to
Code: [Select]
Pars.Values[Pars.Keys[i]] does not seem to me good, because the semantics would be too long.

Code: [Select]
procedure TMyApplication.prepareParms(var Pars: TStringList);
var i: integer;
  sFN: string;
  strA: Array of String;
begin
  Pars.NameValueSeparator := '=';
  sFN := '';
  for i := 1 to paramCount do
      begin
        strA := paramStr(i).split('=');
        if strA[0][1]='-' then
          strA[0]:=copy(strA[0],2,length(strA[0]));
        Pars.Add(strA[0].ToLower+'='+AnsiDequotedStr(strA[1],'"'));
      end;
  if Pars.count>0 then
    begin
      for i := 0 to Pars.count-1 do
          begin
            if (Pars.Names[i]='configfile') OR (Pars.Names[i]='config-file') OR (Pars.Names[i]='config') then
              begin
                sFN := AnsiDequotedStr(Pars.Values[Pars.Names[i]],'"');
                break;
              end;
          end;
      if not fileexists(sFN) then
         writeln('File not found '+sFN)
      else
        begin
          writeln('Reading config file '+sFN);
          Pars.Free;
          Pars.LoadFromFile(sFN);
          for i := 0 to Pars.Count-1 do
              begin
                if Pars.Values[i][1]='-' then
                  Pars.Values[i]:=copy(Pars.Values[i],2,length(Pars.Values[i]));
                Pars.Values[i] := AnsiDequotedStr(Pars.Values[i],'"'));
              end;

        end;
    end;
end;
« Last Edit: November 13, 2023, 09:17:36 pm by barracuda »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: To Create images with text with GDI+ or what is used by linux
« Reply #80 on: November 14, 2023, 12:07:00 am »
I have question in the section of last block, where my questio is on easy key access solution.
I am not entirely sure how exactly you want to accomplish things because you did not share how you want/have the parameters stored in the config file.

However, I believe that when you wrote:
Code: [Select]
for i := 0 to Pars.Count-1 do
  begin
    if Pars.Values[i][1]='-' then
      Pars.Values[i]:=copy(Pars.Values[i],2,length(Pars.Values[i]));
    Pars.Values[i] := ToLower+'='+AnsiDequotedStr(Pars.Values[i],'"'));
  end;

.. is that you probably meant to write the following instead:

Code: Pascal  [Select][+][-]
  1.       for i := 0 to Pars.Count-1 do
  2.       begin
  3.         if Pars.Strings[i][1]='-'
  4.           then Pars.Strings[i]:=copy(Pars.Strings[i],2,length(Pars.Strings[i]));
  5.         Pars.Strings[i] := AnsiDequotedStr(Pars.Strings[i],'"');
  6.       end;
  7.  
.. but as said, I am not 100% sure.

What I am more sure about it that just above that when you wrote:
Code: Pascal  [Select][+][-]
  1.   Parse.Free;
  2.  

... is that you actually meant to write:
Code: Pascal  [Select][+][-]
  1.   Parse.Clear;
  2.  

... If not mistaken. In case mistaken then you (still) have yourself an illegal access error  :)
Today is tomorrow's yesterday.

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: To Create images with text with GDI+ or what is used by linux
« Reply #81 on: November 14, 2023, 12:49:13 am »
Hey I was just going to pass this and you passed the code. So this is correction suggested by chatGPT using Pars.ValueFromIndex. I originally followed this guide https://delphiprogrammingdiary.blogspot.com/2017/09/tstringlist-name-value-pair.html but it seems not to work, so I used ValueFromIndex:

Code: [Select]
procedure TMyApplication.prepareParms(var Pars: TStringList);
var i: integer;
  sFN: string;
  strA: Array of String;
begin
  Pars.NameValueSeparator := '=';
  sFN := '';
  for i := 1 to paramCount do
      begin
        strA := paramStr(i).split('=');
        if strA[0][1]='-' then
          strA[0]:=copy(strA[0],2,length(strA[0]));
        Pars.Add(strA[0].ToLower+'='+AnsiDequotedStr(strA[1],'"'));
      end;
  if Pars.count>0 then
    begin
      for i := 0 to Pars.count-1 do
          begin
            if (Pars.Names[i]='configfile') OR (Pars.Names[i]='config-file') OR (Pars.Names[i]='config') then
              begin
                sFN := AnsiDequotedStr(Pars.ValueFromIndex[i],'"');
                break;
              end;
          end;
      if not fileexists(sFN) then
         writeln('File not found '+sFN)
      else
        begin
          writeln('Reading config file '+sFN);
          Pars.Free;
          Pars.LoadFromFile(sFN);
          for i := 0 to Pars.Count-1 do
              begin
                if Pars.ValueFromIndex[i][1]='-' then
                  Pars.ValueFromIndex[i]:=copy(Pars.ValueFromIndex[i],2,length(Pars.ValueFromIndex[i]));
                Pars.ValueFromIndex[i] := AnsiDequotedStr(Pars.Values[Pars.ValueFromIndex[i]],'"');
              end;

        end;
    end;
end;

The config:
Code: [Select]
bold
italic
characters="..."
font-family="Arial, Verdana"
font-size="9, 10, 12"

font-family="Times New Roman,Courier New"
font-size="14, 12, 10"

I will continue tommorow (I did not debug it yet).

Edit:
Yes I mean .clear not .free .
« Last Edit: November 14, 2023, 09:38:30 am by barracuda »

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: To Create images with text with GDI+ or what is used by linux
« Reply #82 on: November 14, 2023, 01:24:15 pm »
pars stands for parameters.

It's not clear why I cannot watch the values in Debug/Add Watch or Debug/Evaluate in the private procedure. This should be not problem in Delphi 7. How does FreePascal manage. I can display the values by writeln but that is not good approach for debugging - needs to compile every time when I add the line
Code: Pascal  [Select][+][-]
  1. writeln(Pars.ValueFromIndex[i]);

In Debug window like Debug Inspector, etc. I always see "inavailable" Error: Member not found. Which is odd, because the member is there, but it seems like no access to private scope...

I can read variables like strA, strA[0] and sFN. But the var Pars: TStringList is passed like that:
Code: [Select]
  Pars := TStringList.create;
  Pars.NameValueSeparator := '=';
  prepareParms(pars);

So to debug I need to see Pars.count and other Pars members like .Names and .Values
« Last Edit: November 14, 2023, 06:19:40 pm by barracuda »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: To Create images with text with GDI+ or what is used by linux
« Reply #83 on: November 14, 2023, 11:11:43 pm »
It's not clear why I cannot watch the values in Debug/Add Watch or Debug/Evaluate in the private procedure. This should be not problem in Delphi 7. How does FreePascal manage. I can display the values by writeln but that is not good approach for debugging - needs to compile every time when I add the line
Code: Pascal  [Select][+][-]
  1. writeln(Pars.ValueFromIndex[i]);

In Debug window like Debug Inspector, etc. I always see "inavailable" Error: Member not found. Which is odd, because the member is there, but it seems like no access to private scope...
2 relevant threads (there are probably plenty more but these two seem to sum it up nicely):
- Inspect into TStringList
- Watching TStringList - Lazarus 3.0 (FpDebug)

And ofc. you need to have the RTL compiled with debug.

It is a work in progress....

BTW:
For all these string manipulation that you seem to be doing, have a look at unit StrUtils or the typehelper TStringHelper. It reads a lot nicer (and understandable) than those calls to copy().
« Last Edit: November 14, 2023, 11:18:35 pm by TRon »
Today is tomorrow's yesterday.

barracuda

  • Full Member
  • ***
  • Posts: 133
Re: Text to images Generator (Console app generating bitmaps with text)
« Reply #84 on: November 14, 2023, 11:55:22 pm »
I followed the first link and this command
Code: Pascal  [Select][+][-]
  1. PStringItemList(Pars.FList)^[0]
really does the job. The link is quite helpful.

Edit:
Now I see there is  Substring()

Code: [Select]
public function TStringHelper.Substring(

  AStartIndex: SizeInt

):string; overload;

function TStringHelper.Substring(

  AStartIndex: SizeInt;

  ALen: SizeInt

):string; overload;
« Last Edit: November 15, 2023, 10:57:02 am by barracuda »

 

TinyPortal © 2005-2018