Discussion:
pygame.image.frombuffer problems
Trevor Fancher
2005-12-30 00:03:07 UTC
Permalink
Hello,

I am having some problems with the pygame.image.frombuffer function.
I have
also tried pygame.image.fromstring in the same place.

This works if I use cairo.ImageSurface.write_to_png to write to a
file and
then use pygame.image.load to get the image from the file, but I want
a more
effecient way of using pygame and pycairo together.

I posted to this list because I think the error if with pygame, but I
may be
wrong.

Here's the output and the code:


***@zeppelin ~/Desktop $ python test.py
Traceback (most recent call last):
File "test.py", line 24, in ?
image = pygame.image.frombuffer(buf.getvalue(), size,
'ARGB').convert()
ValueError: Buffer length does not equal format and resolution size

***@zeppelin ~/Desktop $ cat test.py
import cairo
import pygame
import StringIO

s = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
c = cairo.Context(s)

c.set_line_width(25)
c.set_source_rgba(.1, .2, .35, .5)
c.move_to(0, 0)
c.line_to(100, 100)
c.move_to(0, 100)
c.line_to(100, 0)
c.stroke()

buf = StringIO.StringIO()
s.write_to_png(buf)

pygame.init()
pygame.display.set_mode((120, 120))
screen = pygame.display.get_surface()

size = (s.get_width(), s.get_height())
image = pygame.image.frombuffer(buf.getvalue(), size, 'ARGB').convert()
image.set_colorkey((0, 0, 0))

screen.fill((160, 160, 160))
screen.blit(image, (10, 10))
pygame.display.flip()


Any suggestion would be great.

Thanks,
__
Trevor Fancher
http://fancher.org/
Peter Shinners
2005-12-30 01:45:23 UTC
Permalink
Post by Trevor Fancher
I am having some problems with the pygame.image.frombuffer function.
I have
also tried pygame.image.fromstring in the same place.
buf = StringIO.StringIO()
s.write_to_png(buf)
size = (s.get_width(), s.get_height())
image = pygame.image.frombuffer(buf.getvalue(), size, 'ARGB').convert()
image.set_colorkey((0, 0, 0))
The problem is that you are writing a compressed PNG data file into the
buffer. The pygame 'fromstring' and 'frombuffer' functions expeect a
string with raw pixel data.

I've lurked on the cairo list every once in awhile, I'm pretty sure
there is a way to get this type of string from the cairo surface.
Trevor Fancher
2005-12-30 15:56:26 UTC
Permalink
Post by Peter Shinners
The problem is that you are writing a compressed PNG data file into the
buffer. The pygame 'fromstring' and 'frombuffer' functions expeect a
string with raw pixel data.
I've lurked on the cairo list every once in awhile, I'm pretty sure
there is a way to get this type of string from the cairo surface.
I've found a thread[1] that turns into a discussion about more or less
exactly what I want to do, but it appears no one ever actually got what
I am trying to do to work. I couldn't find any way to write a "raw"
PNG (if that is even what it is called) out with pycairo, though I am
sure it is possible using cairo's C api.

I may hack around with the pycairo code a bit to see if I can add the
functionality myself.

[1]http://lists.freedesktop.org/archives/cairo/2005-October/005452.html
__
Trevor Fancher
http://fancher.org/
Peter Shinners
2005-12-31 08:45:53 UTC
Permalink
Post by Trevor Fancher
I've found a thread[1] that turns into a discussion about more or less
exactly what I want to do, but it appears no one ever actually got what
I am trying to do to work. I couldn't find any way to write a "raw"
PNG (if that is even what it is called) out with pycairo, though I am
sure it is possible using cairo's C api.
I may hack around with the pycairo code a bit to see if I can add the
functionality myself.
It isn't really a "raw PNG" file, the string is just the raw pixel
representation of the image.

I'm confident in the pygame code to handle this. This is the way images
are currently transferred between python programs like pygame, pyopengl,
pil, and pymedia. The pygame tostring and fromstring are currently
working with these other packages.

I'm browsing the pycairo source now. The function you want is already
there, it is a method called "to_rgba" on the ImageSurface objects. This
returns the string buffer object you can use with
pygame.image.frombuffer() or pygame.image.fromstring()

You may also consider the ImageSurface.create_for_data() classmethod
which should allow you to get into cairo from pygame's fromstring()
function.
Trevor Fancher
2005-12-31 18:19:22 UTC
Permalink
Post by Peter Shinners
It isn't really a "raw PNG" file, the string is just the raw pixel
representation of the image.
After browsing through the cairo source and pycairo source I know what
you mean by raw pixel representation now, so I guess I did learn
something. :)
Post by Peter Shinners
I'm confident in the pygame code to handle this. This is the way images
are currently transferred between python programs like pygame,
pyopengl,
pil, and pymedia. The pygame tostring and fromstring are currently
working with these other packages.
I'm browsing the pycairo source now. The function you want is already
there, it is a method called "to_rgba" on the ImageSurface objects. This
returns the string buffer object you can use with
pygame.image.frombuffer() or pygame.image.fromstring()
pycairo does indeed have an ImageSurface.to_rgba method, but from
reading this[1]:

* It requires a patched version of cairo which provides:
* cairo_image_surface_get_data()
* cairo_image_surface_get_format()
* cairo_image_surface_get_stride()

I discovered I needed a patch.

After some digging around through the cairo mailing lists, I found the
patch[2] the comment was referring to but unfortunately the patch seems
to have never been applied. While I am sure there is good reason for
not applying the patch, I am unable to find any discussion regarding
the patch.

I did, however, find a bug report[3] open on the topic, but it has been
stagnant for a while now.

I suppose I will patch my local cairo source myself and hope for the
best. Wish me luck. :)

[1]http://cvs.cairographics.org/pycairo/cairo/pycairo-surface.c?
rev=1.62&view=markup
[2]http://lists.freedesktop.org/archives/cairo-commit/2005-October/
005401.html
[3]https://bugs.freedesktop.org/show_bug.cgi?id=4687
Post by Peter Shinners
You may also consider the ImageSurface.create_for_data() classmethod
which should allow you to get into cairo from pygame's fromstring()
function.
Do you mean "from pygame's tostring() function"?


Regards,
__
Trevor Fancher
http://fancher.org/
Norbert Sebok
2006-01-02 05:42:18 UTC
Permalink
I want a more effecient way of using pygame and pycairo together.
The solution is surprisingly easy and very fast: Cairo can draw
directly to an SDL surface.

I don't know if it's work on every platform, I use it only on Ubuntu
on x86 machines. But maybe it can work everywhere with the help of
SDL_PixelFormat's masks.



The main code in C:

cairo_surface_t *
create_for_sdl_data(SDL_Surface *sdl_surface)
{
int btpp = 4;
cairo_format_t format = CAIRO_FORMAT_RGB24;

unsigned char *data = sdl_surface->pixels;
int width = sdl_surface->w;
int height = sdl_surface->h;
int stride = width * btpp;

cairo_surface_t* s;
s = cairo_image_surface_create_for_data (data,format,width,height,stride);
return s;
}


and in Python it's as easy as:

screen = pygame.display.set_mode((width, height))
cairo_surface = create_for_sdl_data(screen)
ctx = cairo.Context(cairo_surface)




The full code is here: https://svn.synch.hu:8081/svn/hobby/cairo_sdl/
Be aware! This is my first C program.. Suggestions are welcome.

Norbert Sebok

Loading...