Recent

Author Topic: saving graphs?  (Read 801 times)

Weiss

  • New Member
  • *
  • Posts: 19
saving graphs?
« on: August 06, 2022, 07:46:41 am »
I am still looking for a way to save graphs, in any image format. Graph unit allows saving image as a bitmap onto heap. Where do I go from there? I have a pointer, pointing at bitmap on a heap. I am still foggy on pointers actually. Everything I learned from file handling did not help. I can't write into untyped file using write() method. Is there a bitmap type of file?  When I create file type of pointer, write(filename, p) saves 4 bytes with one pointer symbol, not the actual image. Can't believe there is no simple way of saving graphical image generated by graph unit to a file. Please help, I kept terrorizing Google for all day yesterday, and part of today with no results. I see similar questions being asked, with no answer.

Handoko

  • Hero Member
  • *****
  • Posts: 4712
  • My goal: build my own game engine using Lazarus
Re: saving graphs?
« Reply #1 on: August 06, 2022, 11:06:57 am »
Because Lazarus is IDE for Rapid Application Development, everything should be easier if you use Lazarus rather than Free Pascal only.

But this is my Google search result, which seems to be what you're looking for:
https://stackoverflow.com/questions/26622697/how-to-load-an-image-to-turbo-pascal-using-the-graph-unit

MarkMLl

  • Hero Member
  • *****
  • Posts: 5161
Re: saving graphs?
« Reply #2 on: August 06, 2022, 12:39:13 pm »
Code: Pascal  [Select][+][-]
  1. procedure TFormDsoCat.MenuItemExportPNGClick(Sender: TObject);
  2.  
  3. var
  4.   nameBlank: boolean;
  5.   png: TPortableNetworkGraphic;
  6.   everything: TRect;
  7.  
  8. begin
  9.   nameBlank := Trim(SaveDialog1.Filename) = '';
  10.   if nameBlank then
  11.     SaveDialog1.Filename := projName + '_' + StringReplace(IsoNow(), ' ', 'T', [rfReplaceAll]);
  12.   SaveDialog1.DefaultExt := 'png';
  13.  
  14. (* Possibly replace this later with a custom setup form to select compression   *)
  15. (* etc.                                                                         *)
  16.  
  17.   if SaveDialog1.Execute then begin
  18.     png := TPortableNetworkGraphic.Create;
  19.     try
  20.       png.Width := PanelDisplay1.Width;
  21.       png.Height := PanelDisplay1.Height;
  22.       everything.Left := 0;
  23.       everything.Top := 0;
  24.       everything.Right := PanelDisplay1.Width - 1;
  25.       everything.bottom := PanelDisplay1.Height - 1;
  26.       png.Canvas.CopyRect(everything, PanelDisplay1.Canvas, everything);
  27.       png.SaveToFile(SaveDialog1.Filename)
  28.     finally
  29.       png.Free
  30.     end
  31.   end;
  32.   if nameBlank then
  33.     SaveDialog1.Filename := ''
  34. end { TFormDsoCat.MenuItemExportPNGClick } ;
  35.  

I've used that as an example since PanelDisplay1.Canvas is derived from a TAChart, so I know it works.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Weiss

  • New Member
  • *
  • Posts: 19
Re: saving graphs?
« Reply #3 on: August 07, 2022, 07:28:49 am »
no-no-no.  There must be a simple procedure, three four lines of code. I have higher hopes for WinGraph unit. Appear similar to Graph unit with some support for keyboard, mouse events etc, openGL too. Found it about an hour ago. It speaks about saving plot area into bitmap variable and blockwriting it into file.

About TAchart. Interactive charts that come with TAchart are great, but I have already built interactivity into my charts with Graph unit. I have working application, simple and light, hardly 200kb. Just need to add graph save feature and I am done.

MarkMLl

  • Hero Member
  • *****
  • Posts: 5161
Re: saving graphs?
« Reply #4 on: August 07, 2022, 10:15:29 am »
no-no-no.  There must be a simple procedure, three four lines of code.

Why must there be?

Do you mean that we've overlooked something, or that you expect better of the LCL etc.?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

winni

  • Hero Member
  • *****
  • Posts: 3134
Re: saving graphs?
« Reply #5 on: August 07, 2022, 01:02:12 pm »
no-no-no.  There must be a simple procedure, three four lines of code.

Hi!

Use TaChart and BGRAbitmap:

Code: Pascal  [Select][+][-]
  1. BGRADrawChart(Chart1, PaintBox1);    
  2.  

See
https://forum.lazarus.freepascal.org/index.php?topic=13023.0

Winni

wp

  • Hero Member
  • *****
  • Posts: 10053
Re: saving graphs?
« Reply #6 on: August 07, 2022, 03:01:41 pm »
I am still looking for a way to save graphs, in any image format. Graph unit allows saving image as a bitmap onto heap. Where do I go from there? I have a pointer, pointing at bitmap on a heap. I am still foggy on pointers actually. Everything I learned from file handling did not help. I can't write into untyped file using write() method. Is there a bitmap type of file?  When I create file type of pointer, write(filename, p) saves 4 bytes with one pointer symbol, not the actual image. Can't believe there is no simple way of saving graphical image generated by graph unit to a file. Please help, I kept terrorizing Google for all day yesterday, and part of today with no results. I see similar questions being asked, with no answer.
Here is a reverse-engineering article about the structure of the BGI-saved images: http://www.verycomputer.com/12_8dc949e052a2dc9e_1.htm. It's relatively easy: a 6-byte header with 2 bytes for width, 2 bytes for height and 2 bytes reserved, then the image data depending on the graphic mode (bits per pixel). In my own experiments, I see that this is not quite correct: A bgi image saved in standard VGA mode has a 12-byte header because the numbers are 4 bytes each nowadays. In vga mode the following pixel data require 2 bytes each, with values 0..15 (that's very probably only part of the story, but something to get started...).

Based on this the FPC image routines can be used to convert the pixeldata to a matrix of TFPColor values, and FCL has all the machinery to write this to a file... A nice exercise in FCLImage!

The attached demo is a working quick-and-dirty solution which certainly can be improved. But it works: it saves the test graphic as bmp, png and jpeg files You can have more, but you must add the image writer unit to the uses clause. Find all writers in the directory packages/fclimage/src of your fpc directory; they are named like fpwrite* where * represents the graphic format.

I did not take too much care about matching colors - simply adapt the color-transformation function BgiColorToFPColor. Using a color picker I see, for example, that the BGI blue has r=0, g=0, b=168 (and you must be aware that FPColor has 16-bit color channels). Replacing the BGI blue by the result of FPColor(0, 0, 168 shl 8 ) gives a better impression than replacing it by the straight-forward colDkBlue constant.

You will also have to adapt the code if you work in a different graphic mode.
« Last Edit: August 07, 2022, 03:15:32 pm by wp »

Weiss

  • New Member
  • *
  • Posts: 19
Re: saving graphs?
« Reply #7 on: August 11, 2022, 12:44:13 am »
thank you wp. I learned how to save bitmaps, but paint or or any viewer weren't recognizing saved files as an image file. Then I realized it is just and array, without header. As soon as get home, will try your example and read the article.

Weiss

  • New Member
  • *
  • Posts: 19
Re: saving graphs?
« Reply #8 on: August 11, 2022, 09:20:02 pm »


Based on this the FPC image routines can be used to convert the pixeldata to a matrix of TFPColor values, and FCL has all the machinery to write this to a file... A nice exercise in FCLImage!

The attached demo is a working quick-and-dirty solution which certainly can be improved. But it works: it saves the test graphic as bmp, png and jpeg files You can have more, but you must add the image writer unit to the uses clause. Find all writers in the directory packages/fclimage/src of your fpc directory; they are named like fpwrite* where * represents the graphic format.

I did not take too much care about matching colors - simply adapt the color-transformation function BgiColorToFPColor. Using a color picker I see, for example, that the BGI blue has r=0, g=0, b=168 (and you must be aware that FPColor has 16-bit color channels). Replacing the BGI blue by the result of FPColor(0, 0, 168 shl 8 ) gives a better impression than replacing it by the straight-forward colDkBlue constant.

You will also have to adapt the code if you work in a different graphic mode.

Tried your program, wp, thank you very much. Works Like a charm. Some slick style you have. I will be studying your snippet for a while. And I get your joke, like I said, slick. The article you were referring to, send me to threads dating back to 1991, 30 years ago!

Thank you everybody gents, I am learning a lot, even a simple comment sometimes sends me to another chapter. Wasn't a simple solution as it turns... Can we call it solved?

And again fellas, even if I did not respond to your comment doesn't mean it was ignored, it takes a while for me to go through every route you sent me.

 

TinyPortal © 2005-2018