Hi again,
So I wanted to keep my SDL + PDL piddle interface attempts updated.
So far I had to update SDL to fix $surface->get_pixels_ptr() method.
You can get it at http://github.com/kthakore/SDL_perl or just do
pip http://waitdownload.github.com/kthakore-SDL_perl-2.402-105-ga4a7e6d.tar.gz
Next I made a script to show the piddle details (see attached) but I
can't seem to modify the actual surface data.
I do the following.
use PDL;
use PDL::NiceSlice;
... make a $surface to use and $app to show stuff
sub surface_to_piddle
{
my $surface = shift;
my $piddle = byte(0);
my $pointer = $piddle->get_dataref;
$$pointer = ${$surface->get_pixels_ptr};
###########
#${$surface->get_pixel_ptr} can be written and read from using
#vec() and substr
###########
$piddle->setdims([4, $surface->w, $surface->h]);
$piddle->upd_data();
return $piddle;
}
... I can then use the piddle to retrive data
SDL::Video::lock_surface( $surface ); # This needs to be done to
write to surfaces
print sprintf ( "%x", $surface->get_pixel(0)); #=> gets ff0000
print $piddle(:, 1, 2); # -> gets [ [ 0 0 255 0] ]
$piddle(:, 0 : 10 , 0 : 15) .= pdl( 0, 240, 55, 0 );
print $piddle(:, 1, 2); #-> gets [ [ 0 240 55 0] ]
print sprintf ( "%x", $surface->get_pixel(0)); #-> get ff0000
SDL::Video::unlock_surface( $surface ); #need to tell SDL surface is
ready to blit
die sprintf ( "%x", $surface->get_pixel(0)); #-> get ff0000
As you can see the piddle data can be changed ... but the acutal surface
pixel cannot be changed. Does the piddle make a copy when the dataref is
changed?
Regards,
Kartik Thakore
On Thu, Jun 24, 2010 at 08:53:04AM -0500, David Mertens wrote:
> Here's the updated code. It should do what you mean, though I'm having
> trouble with it.
>
> # Create an one-element piddle of type byte.
> # We will discard the data; this is just to get the right type.
> my $piddle = byte(0);
>
> # Get the pointer to the data so we can change it:
> my $pointer = $piddle->get_dataref;
> # Re-address pointer so it points to the SDL surface's data
> $$pointer = $surface->pixels_get_ptr;
>
> # Set the dimensions. This assumes 4 bytes per pixel:
> $piddle->setdims([4, $surface->w, $surface->h]);
>
> # Make sure the piddle is aware of its new dimensions
> $piddle->upd_data();
use strict;
use warnings;
use SDL 2.408;
use SDLx::App; #this is in the github repo.
use SDL::Event;
use SDL::Events;
use SDL::Rect;
use SDL::Video;
use PDL;
use PDL::NiceSlice;
my $app = SDLx::App->new(
-title => 'Application Title',
-width => 640,
-height => 480,
-depth => 32
);
load_app();
my $surface = load_surface();
my $piddle = surface_to_piddle($surface);
my $event = SDL::Event->new; # create a new event
while(1) {
SDL::Events::pump_events();
while ( SDL::Events::poll_event($event) ) {
my $type = $event->type(); # get event type
exit if $type == SDL_QUIT;
}
update($piddle);
SDL::Video::update_rect( $app, 0, 0, $app->w, $app->h );
}
sub load_app {
my $mapped_color =
SDL::Video::map_RGB( $app->format(), 0, 0, 0 ); # blue
SDL::Video::fill_rect( $app, SDL::Rect->new( 0, 0, $app->w, $app->h ),
$mapped_color );
return $app;
}
sub load_surface {
my $surface =
SDL::Surface->new( SDL_ANYFORMAT, 150, 150, 32, 0, 0, 0, 0 );
my $mapped_color =
SDL::Video::map_RGBA( $surface->format(), 255, 0, 0, 0 ); # blue
SDL::Video::fill_rect( $surface,
SDL::Rect->new( 0, 0, $surface->w, $surface->h ),
$mapped_color );
return $surface;
}
sub surface_to_piddle
{
my $surface = shift;
my $piddle = byte(0);
my $pointer = $piddle->get_dataref;
$$pointer = ${$surface->get_pixels_ptr};
$piddle->setdims([4, $surface->w, $surface->h]);
$piddle->upd_data();
return $piddle;
}
sub update {
my $piddle = shift;
load_app();
SDL::Video::lock_surface( $surface );
print sprintf ( "%x", $surface->get_pixel(0)); #=> gets ff0000
print $piddle(:, 1, 2); # -> gets [ [ 0 0 255 0] ]
$piddle(:, 0 : 10 , 0 : 15) .= pdl( 0, 240, 55, 0 );
print $piddle(:, 1, 2); #-> gets [ [ 0 240 55 0] ]
print sprintf ( "%x", $surface->get_pixel(0)); #-> get ff0000
SDL::Video::unlock_surface( $surface );
die sprintf ( "%x", $surface->get_pixel(0)); #-> get ff0000
SDL::Video::blit_surface( $surface, SDL::Rect->new( 0, 0, $surface->w,
$surface->h ),
$app, SDL::Rect->new( ($app->w -
$surface->w)/2 , ($app->h - $surface->h)/2, $app->w, $app->h ));
}