wx.BitmapFromBuffer data for PNG format

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.

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

not entirely sure, but an idea or two:

I am writing a python module for the following utility:
SeExpr/src/demos/imageSynth/imageSynth.cpp at main · wdas/SeExpr · GitHub

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

···

On Mon, May 21, 2012 at 12:34 AM, King <animator333@gmail.com> wrote:

--

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.Barker@noaa.gov

Hi,

I am writing a python module for the following utility:
SeExpr/src/demos/imageSynth/imageSynth.cpp at main · wdas/SeExpr · GitHub

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.

···

On 5/21/12 12:34 AM, King wrote:

--
Robin Dunn
Software Craftsman

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

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.

···

On 5/21/12 11:19 AM, King wrote:

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.

--
Robin Dunn
Software Craftsman

Thanks Robin,

Using wx.BitmapFromBufferRGBA, every thing is working fine.

Cheers

Prashant

···

On Monday, May 21, 2012 11:56:57 PM UTC+5:30, Robin Dunn wrote:

On 5/21/12 11:19 AM, King wrote:

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.

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


Robin Dunn

Software Craftsman

http://wxPython.org