wx.BitmapFromBuffer data for PNG format

96 views
Skip to first unread message

King

unread,
May 21, 2012, 3:34:23 AM5/21/12
to wxpytho...@googlegroups.com
Hi,

I am writing a python module for the following utility:

For pixel data I am generating a list like this:

PyList_Append(list, Py_BuildValue("i", (unsigned char)clamp(result[1]*256.)));
PyList_Append(list, Py_BuildValue("i", (unsigned char)clamp(result[1]*256.)));
PyList_Append(list, Py_BuildValue("i", (unsigned char)clamp(result[2]*256.)));
PyList_Append(list, Py_BuildValue("i", 255));

In python module:

mlist = seexpr("noise(10*$u,10*$v)", width, height)
bytes = array.array('B', mlist)
rgbBmp = wx.BitmapFromBuffer(width, height, bytes)
rgbBmp.SaveFile("test.png", wx.BITMAP_TYPE_PNG)

The resulting png is not coming properly. I have attached both the images here. I think I have to further manipulate the data order in list but no clue.
I would also appreciate if some one point me out how to write python's array of "B" type in 'C' for above situation. I don't want to use numpy's array
for extra dependency.

Cheers

Prashant

correct.png
wrong.png

Chris Barker

unread,
May 21, 2012, 12:47:21 PM5/21/12
to wxpytho...@googlegroups.com
not entirely sure, but an idea or two:

On Mon, May 21, 2012 at 12:34 AM, King <anima...@gmail.com> wrote:
> I am writing a python module for the following utility:
> https://github.com/wdas/SeExpr/blob/master/src/demos/imageSynth/imageSynth.cpp
>
> For pixel data I am generating a list like this:
>
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[1]*256.)));
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[1]*256.)));
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[2]*256.)));
> PyList_Append(list, Py_BuildValue("i", 255));

why use a list? -- as you know, you'll need to use a binary
compatible implimentation later, so I"d put those either in a
array.array object from the C++ (I'm pretty sure the C api is
documented), or even a string (or bytes object), or, in fact, you
could create an object that support the buffer protocol.

but none of that is probably the source of your problem.

> mlist = seexpr("noise(10*$u,10*$v)", width, height)
> bytes = array.array('B', mlist)
> rgbBmp = wx.BitmapFromBuffer(width, height, bytes)

do you have the data in the right order for an image? i.e. row-major
vs. column major? I'd experiment with that. IIRC, numpy natively
stores the data in a different order (height, width) vs. (width,
height) -- and numpy natively uses C order -- which you may be using
also. I"d look into that.

I also see that your C++ code is appending result[1] twice, then
result[2]. if you car converting from greyscale to RGB, wouldn't you
want to write each value three times?

It looks like you are trying te reduce dependencies, but PIL might be
helpful here -- it can work natively with greyscale.


> I would also appreciate if some one point me out how to write python's array
> of "B" type in 'C' for above situation.

I've never done it, but it should be pretty straightforward form teh
API -- or, as I mentioned above, use a bytes object.

> I don't want to use numpy's array
> for extra dependency.

but it would be easier....

another option is Cython -- it makes it much easier to do this sort of
thing -- it support bytes objects, numpy arrays (I know, you dont want
to use them...), and I think array.array support was just added to the
development version.

HTH,
-Chris




--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

Robin Dunn

unread,
May 21, 2012, 1:08:26 PM5/21/12
to wxpytho...@googlegroups.com
On 5/21/12 12:34 AM, King wrote:
> Hi,
>
> I am writing a python module for the following utility:
> https://github.com/wdas/SeExpr/blob/master/src/demos/imageSynth/imageSynth.cpp
>
>
> For pixel data I am generating a list like this:
>
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[1]*256.)));
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[1]*256.)));
> PyList_Append(list, Py_BuildValue("i", (unsigned
> char)clamp(result[2]*256.)));
> PyList_Append(list, Py_BuildValue("i", 255));
>
> In python module:
>
> mlist = seexpr("noise(10*$u,10*$v)", width, height)
> bytes = array.array('B', mlist)
> rgbBmp = wx.BitmapFromBuffer(width, height, bytes)
> rgbBmp.SaveFile("test.png", wx.BITMAP_TYPE_PNG)
>
> The resulting png is not coming properly. I have attached both the
> images here. I think I have to further manipulate the data order in list
> but no clue.

You probably want to use result[0] for the first PyList_Append above.


> I would also appreciate if some one point me out how to write python's
> array of "B" type in 'C' for above situation. I don't want to use
> numpy's array
> for extra dependency.

The array module doesn't have a public C API so you won't be able to do
exactly what you are trying to do there, however string objects are
valid read-only buffer objects so the wx.BitmapFromBuffer will work with
a string too. So you can build an array of char (that is width*height*3
bytes long) in C and then create a string object from it with
PyString_FromStringAndSize.


--
Robin Dunn
Software Craftsman
http://wxPython.org

King

unread,
May 21, 2012, 2:19:01 PM5/21/12
to wxpytho...@googlegroups.com
Chris,

I think the problem is in data order. Even in the code (link posted), at the bottom, before writing png image, some manipulation is going on but not able to understand it correctly.
Thanks for pointing out "result[1]" mistake, unfortunately it didn't helped.

Yes, Cython recently added support for array.array. I'll look into this later.

Robin,

I changed to char array instead of python's list, it works but results are pretty much same.

Cheers

Prashant

Robin Dunn

unread,
May 21, 2012, 2:26:57 PM5/21/12
to wxpytho...@googlegroups.com
Ah, I just noticed that you seem to be adding 4 values per pixel, 3 for
RGB (presumably) and 1 with a constant value of 255 for the alpha
(presumably). I only noticed the 1st 3 lines before. If that is your
intent then you should be using wx.BitmapFromBufferRGBA instead of
wx.BitmapFromBuffer, and use width*height*4 instead of the *3 I
mentioned before. Also you should double check that the values you are
fetching from the source buffer are in RGB order.

King

unread,
May 22, 2012, 12:50:48 AM5/22/12
to wxpytho...@googlegroups.com
Thanks Robin,

Using wx.BitmapFromBufferRGBA, every thing is working fine.

Cheers

Prashant
Reply all
Reply to author
Forward
0 new messages