AggPas / PTCGraph dynamic memory allocation

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

AggPas / PTCGraph dynamic memory allocation

Zaaphod
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



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: AggPas / PTCGraph dynamic memory allocation

Graeme Geldenhuys-6
On 2017-11-11 01:48, 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: AggPas / PTCGraph dynamic memory allocation

Zaaphod
>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

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: AggPas / PTCGraph dynamic memory allocation

Graeme Geldenhuys-6
On 2017-11-12 01:27, 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: AggPas / PTCGraph dynamic memory allocation

Zaaphod
>>     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.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal