speed up display of image data from 3rd party C++ extension

Hi!

I would like to speed up the process of getting image data from my
custom C++ image processing extension into my wxPython image viewer
widget. So far, I have been taking the rather cumbersome route

C++ image -> Python string -> wx.Image -> wx.Bitmap

which is then blitted to the screen, but I would rather do

C++ image -> wx.Bitmap

directly using code similar to the recently added BitmapFromBuffer
functions. Does this make sense? And if it does - I would much rather
use the wxPython API from within my extension than the other way around,
but I'm not sure how to obtain the SWIG-wrapped C++ object through the
wxPython API to pass the newly generated wx.Bitmap back into wxPython
for blitting. ..

Any help is greatly appreciated,

Oliver

···

--
--------------------------------------------------------------------
F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix BioScience GmbH
Tatzberg 47 phone: +49 (351) 4173-136
D-01307 Dresden, Germany fax: +49 (351) 4173-109

fingerprint: 8E0E 9A64 A07E 0D1A D302 34C2 421A AE9F 4E13 A009
public key: http://www.cenix-bioscience.com/public_keys/gathmann.gpg
--------------------------------------------------------------------

F. Oliver Gathmann wrote:

I would like to speed up the process of getting image data from my
custom C++ image processing extension into my wxPython image viewer
widget. So far, I have been taking the rather cumbersome route

C++ image -> Python string -> wx.Image -> wx.Bitmap

which is then blitted to the screen, but I would rather do

C++ image -> wx.Bitmap

directly using code similar to the recently added BitmapFromBuffer
functions. Does this make sense?

It sure does -- that's what it's there for.

And if it does - I would much rather
use the wxPython API from within my extension than the other way around,

I'm not sure I quite follow this -- are you saying you want to create a wxBitmap in your C++ code? I can't help with that, but...

If you make your "C++ Image" follow the Python buffer protocol:

http://docs.python.org/api/abstract-buffer.html

then you should be able to do the wx.BitmapFromBuffer call in Python.

You might also want to consider taking a look at the numpy array interface/ndarray object spec. It could be handy to make your Images manipulatable with numpy anyway.

I wish I could help more, but please do report back how it works out for you, and how you did it.

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

Christopher Barker wrote:

F. Oliver Gathmann wrote:

I would like to speed up the process of getting image data from my
custom C++ image processing extension into my wxPython image viewer
widget. So far, I have been taking the rather cumbersome route

C++ image -> Python string -> wx.Image -> wx.Bitmap

which is then blitted to the screen, but I would rather do

C++ image -> wx.Bitmap

directly using code similar to the recently added BitmapFromBuffer
functions. Does this make sense?

It sure does -- that's what it's there for.

And if it does - I would much rather
use the wxPython API from within my extension than the other way around,

I'm not sure I quite follow this -- are you saying you want to create
a wxBitmap in your C++ code? I can't help with that, but...

Yes, that's what I have in mind - create a wx.Bitmap in my C++ extension
and pass it to my wxPython GUI for display.

If you make your "C++ Image" follow the Python buffer protocol:

http://docs.python.org/api/abstract-buffer.html

then you should be able to do the wx.BitmapFromBuffer call in Python.

I was thinking of using the buffer interface, but that would still
involve *two* copies of the image data - one from my C++ image class
into the buffer (the in-memory layout is different from what wx expects)
and one from the buffer into the new wx.Bitmap object.

You might also want to consider taking a look at the numpy array
interface/ndarray object spec. It could be handy to make your Images
manipulatable with numpy anyway.

Yes, I have done that already (and since you can specify strides in
numpy arrays, you don't have to copy any data at all), but that does not
solve the problem of getting the image data to the screen in the most
efficient manner.

I wish I could help more, but please do report back how it works out
for you, and how you did it.

Thank you very much for your comments, and I will let you know how I
fared...

Oliver

···

--
--------------------------------------------------------------------
F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix BioScience GmbH
Tatzberg 47 phone: +49 (351) 4173-136
D-01307 Dresden, Germany fax: +49 (351) 4173-109

fingerprint: 8E0E 9A64 A07E 0D1A D302 34C2 421A AE9F 4E13 A009
public key: Typo | Odoo
--------------------------------------------------------------------

F. Oliver Gathmann wrote:

Hi!

I would like to speed up the process of getting image data from my
custom C++ image processing extension into my wxPython image viewer
widget. So far, I have been taking the rather cumbersome route

C++ image -> Python string -> wx.Image -> wx.Bitmap

which is then blitted to the screen, but I would rather do

C++ image -> wx.Bitmap

directly using code similar to the recently added BitmapFromBuffer
functions. Does this make sense? And if it does - I would much rather
use the wxPython API from within my extension than the other way around,
but I'm not sure how to obtain the SWIG-wrapped C++ object through the
wxPython API to pass the newly generated wx.Bitmap back into wxPython
for blitting. ..

Take a look at the "embedded" sample. It shows how to use wxPython from within a C++ app, but the principles are the same as what you would need to do from another extension module to access wxPython objects via C++.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

F. Oliver Gathmann wrote:

directly using code similar to the recently added BitmapFromBuffer

Yes, that's what I have in mind - create a wx.Bitmap in my C++ extension
and pass it to my wxPython GUI for display.

In that case, you don't need wx.BitmapFromBuffer -- you need whatever the C++ call is for setting the data in a wxBitmap.

I was thinking of using the buffer interface, but that would still
involve *two* copies of the image data - one from my C++ image class
into the buffer (the in-memory layout is different from what wx expects)
and one from the buffer into the new wx.Bitmap object.

No, it wouldn't. That's the whole point of the buffer interface, when you create a Bitmap from a buffer, it uses the buffer data directly, it does not make a copy.

I was suggesting that approach, as it removes the need to have an wx code in your extension -- that's nice, as you don't have to make sure you're linked against the same version of wx.

Yes, I have done that already (and since you can specify strides in
numpy arrays, you don't have to copy any data at all), but that does not
solve the problem of getting the image data to the screen in the most
efficient manner.

True, though we're all hoping that the numpy-style nd-array will become a standard, and then we can make sure that wxPython functions like wx.BitmapFromBuffer understand it.

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

Christopher Barker wrote:

F. Oliver Gathmann wrote:

directly using code similar to the recently added BitmapFromBuffer

Yes, that's what I have in mind - create a wx.Bitmap in my C++ extension
and pass it to my wxPython GUI for display.

In that case, you don't need wx.BitmapFromBuffer -- you need whatever
the C++ call is for setting the data in a wxBitmap.

I was thinking of using the buffer interface, but that would still
involve *two* copies of the image data - one from my C++ image class
into the buffer (the in-memory layout is different from what wx expects)
and one from the buffer into the new wx.Bitmap object.

No, it wouldn't. That's the whole point of the buffer interface, when
you create a Bitmap from a buffer, it uses the buffer data directly,
it does not make a copy.

That's what I thought initially, too. But if you look at the code, the
various implementations of wx.BitmapFromBuffer (file _gdi_wrap.cpp in
the gtk/mac/msw subfolders in the wxPython source folder) allocate a new
bitmap and use "wxNativePixelData::Iterator" to set each pixel in the
new bitmap from the buffer source. And in the docs it says:

    Unlike `wx.ImageFromBuffer` the bitmap created with this function
    does not share the memory buffer with the buffer object. This is
    because the native pixel buffer format varies on different
    platforms, and so instead an efficient as possible copy of the
    data is made from the buffer objects to the bitmap's native pixel
    buffer. For direct access to a bitmap's pixel buffer see
    `wx.NativePixelData` and `wx.AlphaPixelData`.

So, I guess I will be investigating the route that Robin suggested -
write a small extension that uses the wxPython API. I'll report back
when (if...) I get anywhere with this.

Regards,

Oliver

···

--
--------------------------------------------------------------------
F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix BioScience GmbH
Tatzberg 47 phone: +49 (351) 4173-136
D-01307 Dresden, Germany fax: +49 (351) 4173-109

fingerprint: 8E0E 9A64 A07E 0D1A D302 34C2 421A AE9F 4E13 A009
public key: Typo | Odoo
--------------------------------------------------------------------

F. Oliver Gathmann wrote:

No, it wouldn't. That's the whole point of the buffer interface, when
you create a Bitmap from a buffer, it uses the buffer data directly,
it does not make a copy.

That's what I thought initially, too. But if you look at the code, the
various implementations of wx.BitmapFromBuffer (file _gdi_wrap.cpp in
the gtk/mac/msw subfolders in the wxPython source folder) allocate a new
bitmap and use "wxNativePixelData::Iterator" to set each pixel in the
new bitmap from the buffer source.

Thanks for the info -- shows you what I know!

And in the docs it says:

    Unlike `wx.ImageFromBuffer` the bitmap created with this function
    does not share the memory buffer with the buffer object. This is
    because the native pixel buffer format varies on different
    platforms, and so instead an efficient as possible copy of the
    data is made from the buffer objects to the bitmap's native pixel
    buffer. For direct access to a bitmap's pixel buffer see
    `wx.NativePixelData` and `wx.AlphaPixelData`.

I was wondering how that could work. But what if it does happen to match? Is wx.NativePixelData available form Python? I wonder if the numpy array could help here in the future, as you'd have a data description with the data. You still wouldn't know if it was RGBA or ARGB, though, I suppose...

So, I guess I will be investigating the route that Robin suggested -
write a small extension that uses the wxPython API

That'll really still give you the same problem. If your platform isn't using the same bitmap format as you, you still need the copy -- it may well be that wx.BitmapFromBuffer is about as efficient as you can get.

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