Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2017-11

AggPas / PTCGraph dynamic memory allocation

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

James Richters

I've been trying to figure out how to dynamically allocate memory to be used as a screen buffer to display AggPas generated images with PTCGraph. I don't want it hard coded because I do not know what resolution monitor is going to be used. Here is where I am at:

I can define a static variable like this:
Const
   RGB_Width = 2;
   Buffer_Width=1920;
   Buffer_Height=1280;
Type
TGraphBitmapBuffer=packed record
  width,
  height,
  reserved:  LongInt;
  data: 	array[0.. (Buffer_Width+1) * (Buffer_Height+1)] of word;   // I don't know why I need the +1's but it won't work without them
End;
Var
   graph_buffer: TGraphBitmapBuffer;
Then I attach it to AggPas with:
  agg^.attach(@graph_buffer.data, graph_buffer.width, graph_buffer.height, - graph_buffer.width * RGB_Width);
Then I put it on the screen with:
PutImage(0,0,graph_buffer,NormalPut);
I should point out that I like to do  this:
Original_screen:=graph_buffer;  to save my screen then put new stuff on it,  then just copy back the original and putimage it back when I'm done.  So I need a solution that will allow me to do this.  I also don't always use the whole screen,  sometimes I just want to getimage a little area, and putimage that back... but I don't know the size of these areas... they are calculated based on the resolution of the monitor and various settings and configurations.

Here is where I am at with my attempt to make the memory dynamically allocated:

I can use a dynamic method with PTCGraph with getimage and putimage But if I allocate memory this way, while it works fine with getimage and putimage, I can't figure out how to use it with AggPas because the first 3 words are not part of the bitmap data... It seems like there should be a way to make this work but the solution eludes me. I've been trying to come up with a way to do *something* like this:

Var
   graph_buffer: Pointer;
  Max_X, Max_Y: Word;
Max_X:=1920;  //these will be detected by PTCGraph...
Max_Y:=1280;
Size := ImageSize(0, 0, Max_X-1, Max_Y-1);
GetMem(graph_buffer, Size);
GetImage(0, 0, Max_X-1, Max_Y-1, graph_buffer^);
agg^.attach(@graph_buffer[12], Max_X-1,Max_Y-1, -(Max_X-1) * RGB_Width);  //graph_buffer[12] is to skip over the 3 longints 4 bytes each
PutImage(0,0,graph_buffer^,NormalPut);

The problem is with Agg^.attac() of course now graph_buffer isn't an array anymore... so what I have won't work and I haven' figured out how to attach AggPas at a position where the bitmap data is so I can use PutImage and still have the Longints that were put in by GetImage.

Any advice is greatly appreciated

James

Reply by email

Graeme Geldenhuys
to James Richters
James Richters wrote
I can use a dynamic method with PTCGraph with getimage and putimage But if I allocate memory this way, while it works fine with getimage and putimage, I can't figure out how to use it with AggPas because the first 3 words are not part of the bitmap data...

AggPas doesn't care where or what the data buffer is, as long as you tell AggPas where to start, width, height and stride. So use GetImage, assign that buffer to a pointer. Increment the pointer by (3 * Size(Word)) and give that pointer to agg.Attach().

That should do the trick.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

James Richters
to Graeme Geldenhuys
AggPas doesn't care where or what the data buffer is, as long as you tell AggPas where to start, width, height and stride. So use GetImage, assign that buffer to a pointer. Increment the pointer by (3 *Size(Word)) and give that pointer to agg.Attach().

The data is preceded by 3 Longints, not words... sorry for my mistake.

I understand the concept but I'm having difficulty getting the syntax right. What I Think I am doing is setting a pointer for my GetImage/Putimage then defining a second pointer that is 3 Longints into the Getimage/Putimage pointer for use with AggPas...

Here is the a sample program that works with the non-dynamic variable
{$mode objfpc}{$H+}

uses
shlobj,
ptcgraph,
ptccrt,
sysutils,
agg_pixfmt_rgb_packed,

  agg_2D;
const
  RGB_WIDTH =2;
  Clock_W = 120;
  Clock_h = 40;
type
TClockBitmapBuffer=packed record
  width,
  height,
  reserved :longint;
  data  :array[0..(Clock_W+1) * (Clock_H+1)] of word;
end;
var
  Newtime,Oldtime        : Double;
  Bufsize                : Longint;
  gd,gm                  : smallint;
  aggClock,aggClock2     : Agg2D_ptr;
  Font2use,FontPath      : Array[0..MaxPathLen] of Char;
  clockbuffer_Original   : TClockBitmapbuffer;
  clockbuffer_with_time  : Tclockbitmapbuffer;
  Aggclockbuffer         : TClockbitmapbuffer;
Begin
   gd:=d16Bit;
   gm:=m800x600;
   ptcgraph.Initgraph(gd,gm,'');
   SHGetSpecialFolderPath(0,FontPath,CSIDL_FONTS,false);
   font2use:=FontPath+'\Lucon.ttf';
   GetImage((GetMaxX-4)-Clock_W+1,  4, GetMaxX-4,  4+Clock_H-1, ClockBuffer_original);
   ClockBuffer_With_Time:=ClockBuffer_original;
   New(aggClock , Construct(@pixfmt_rgb565));
   aggClock^.attach(@Clockbuffer_with_time.data,Clock_W, Clock_H, -Clock_W * RGB_WIDTH);
   aggclock^.Font(font2use ,12 );
   aggclock^.LineColor($FF ,$FF ,$00 );
   aggclock^.FillColor($FF ,$FF ,$60 );
Repeat
   Newtime:=now;
   If Trunc(Newtime*346600)Trunc(Oldtime*345600) Then  //update every 1/4 second
   Begin
      OldTime:=NewTime;
      ClockBuffer_With_Time:=ClockBuffer_original;
      aggclock^.Text(2 ,19,FormatDateTime('hh:nn:ssam/pm',Now));
      Putimage((GetMaxX-4)-Clock_W,  4, Clockbuffer_With_Time , normalPut);
   End;
until keypressed;
End.

Here is my attempt to define it with a dynamic variable.. It compiles, but when I try to run it I get an access violation and runtime error 217 I'm pretty sure I’m not assigning the pointer for Aggclockbuffer correctly and I don't think I'm attaching it to AggPas correctly either. Corrections are greatly appreciated.

{$mode objfpc}{$H+}

uses
shlobj,
ptcgraph,
ptccrt,
sysutils,
agg_pixfmt_rgb_packed,

  agg_2D;
const
  RGB_WIDTH =2;
  Clock_W = 120;
  Clock_h = 40;
Var
   Newtime,Oldtime        : Double;
   Bufsize                : Longint;
   gd,gm                  : smallint;
   aggClock,aggClock2     : Agg2D_ptr;
   Font2use,FontPath      : Array[0..MaxPathLen] of Char;
   clockbuffer_Original   : ^Byte;
   clockbuffer_with_time  : ^Byte;
   Aggclockbuffer         : ^Byte;
Begin
   gd:=d16Bit;
   gm:=m800x600;
   ptcgraph.Initgraph(gd,gm,'');
   SHGetSpecialFolderPath(0,FontPath,CSIDL_FONTS,false);
   font2use:=FontPath+'\Lucon.ttf';
   bufSize:=ImageSize((GetMaxX-4)-Clock_W, 4 , GetMaxX-4, 4+Clock_H);
   GetMem(ClockBuffer_Original, bufSize);   { Allocate memory on heap }
   GetImage((GetMaxX-4)-Clock_W+1,  4, GetMaxX-4,  4+Clock_H-1, ClockBuffer_original^);
   ClockBuffer_With_Time:=ClockBuffer_original;
   AggClockbuffer^:=ClockBuffer_With_Time^+3*Sizeof(Longint);   //Set AggClockBuffer to be 3 Longints past ClockBuffer_with_time
   New(aggClock , Construct(@pixfmt_rgb565));
   aggClock^.attach(@AggClockbuffer,Clock_W, Clock_H, -Clock_W * RGB_WIDTH);   //Try to use AggClockbuffer pointer with AggPas
   aggclock^.Font(font2use ,12 );
   aggclock^.LineColor($FF ,$FF ,$00 );
   aggclock^.FillColor($FF ,$FF ,$60 );
Repeat
   Newtime:=now;
   If Trunc(Newtime*346600)Trunc(Oldtime*345600) Then  //update every 1/4 second
      Begin
         OldTime:=NewTime;
         ClockBuffer_With_Time:=ClockBuffer_original;
         aggclock^.Text(2 ,19,FormatDateTime('hh:nn:ssam/pm',Now));
         Putimage((GetMaxX-4)-Clock_W,  4, Clockbuffer_With_Time^ , normalPut);
      End;
until KeyPressed;
End.

James

Reply by email

Graeme Geldenhuys
to James Richters
James Richters wrote
ClockBuffer_With_Time:=ClockBuffer_original;

That seems fine.

AggClockbuffer^:=ClockBuffer_With_Time^+3*Sizeof(Longint); //Set AggClockBuffer to be 3 Longints past ClockBuffer_with_time

This seems wrong. Try changing that to the following:

   AggClockbuffer := ClockBuffer_With_Time + (3*Sizeof(Longint));

Disclaimer:
I haven't tried to run your code or my suggested changes.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

James Richters
to Graeme Geldenhuys
Show quoted text 9 lines
> ClockBuffer_With_Time:=ClockBuffer_original; That seems fine. > AggClockbuffer^:=ClockBuffer_With_Time^+3*Sizeof(Longint); //Set AggClockBuffer to be 3 Longints past ClockBuffer_with_time This seems wrong. Try changing that to the following: AggClockbuffer := ClockBuffer_With_Time + (3*Sizeof(Longint));

Now I have a new issue... It's just failing with either return code 253 or 255 but no runtime error.. I put in some writeln's to see where the problem is. Here below my test program. It executes the Writeln('5'); but not the Writeln('6') in between is aggclock^.Text(2 ,19,FormatDateTime('hh:nn:ssam/pm',Now)); I moved this line up to where the aggclock^fillcolor commands are, and it fails up there too...

Any ideas?

{$mode objfpc}{$H+}

uses
shlobj,
ptcgraph,
ptccrt,
sysutils,
agg_pixfmt_rgb_packed,

  agg_2D;
const
  RGB_WIDTH =2;
  Clock_W = 120;
  Clock_h = 40;
Var
   address1,address2      : longint;
   Newtime,Oldtime        : Double;
   Bufsize                : Longint;
   gd,gm                  : smallint;
   aggClock               : Agg2D_ptr;
   Font2use,FontPath      : Array[0..MaxPathLen] of Char;
   clockbuffer_Original   : ^Byte;
   clockbuffer_with_time  : ^Byte;
   Aggclockbuffer         : ^Byte;
Begin
   gd:=d16Bit;
   gm:=m800x600;
   ptcgraph.Initgraph(gd,gm,'');
   SHGetSpecialFolderPath(0,FontPath,CSIDL_FONTS,false);
   font2use:=FontPath+'\Lucon.ttf';
   bufSize:=ImageSize((GetMaxX-4)-Clock_W, 4 , GetMaxX-4, 4+Clock_H);
   GetMem(ClockBuffer_Original, bufSize);   { Allocate memory on heap }
   GetImage((GetMaxX-4)-Clock_W+1,  4, GetMaxX-4,  4+Clock_H-1, ClockBuffer_original^);
   ClockBuffer_With_Time:=ClockBuffer_original;
   Writeln('1');
   Putimage((GetMaxX-4)-Clock_W,  4, Clockbuffer_With_Time^, normalPut);
   Writeln('1.5');
   AggClockbuffer := ClockBuffer_With_Time + (3*Sizeof(Longint));
   Writeln('2');
   New(aggClock , Construct(@pixfmt_rgb565));
   aggClock^.attach(@AggClockbuffer,Clock_W, Clock_H, -Clock_W * RGB_WIDTH);
   aggclock^.Font(font2use ,12 );
   aggclock^.LineColor($FF ,$FF ,$00 );
   aggclock^.FillColor($FF ,$FF ,$60 );
   Writeln('3');
Repeat
   Newtime:=now;
   If Trunc(Newtime*346600)Trunc(Oldtime*345600) Then  //update every 1/4 second
      Begin
         OldTime:=NewTime;
         Writeln('4');
         ClockBuffer_With_Time:=ClockBuffer_original;
         Writeln('5');
         aggclock^.Text(2 ,19,FormatDateTime('hh:nn:ssam/pm',Now));
         Writeln('6');
         Putimage((GetMaxX-4)-Clock_W,  4, Clockbuffer_With_Time^, normalPut);
         Writeln('7');
      End;
until KeyPressed;
End.

Reply by email