Bitmap/image to/from string?

I wish to hold a bitmap image in a database. My application uses SQLObject, so I figure the best way for me to do this would be to convert the image to and from a string when doing database stuff.

A wxBitMap or wxImage method to do this does not immediately jump out at me. Can anyone help?

Thanks

MIke

Mike Edmonds writes:

I wish to hold a bitmap image in a database. My application
uses SQLObject, so I figure the best way for me to do this
would be to convert the image to and from a string when doing
database stuff.

A wxBitMap or wxImage method to do this does not immediately
jump out at me. Can anyone help?

I've done this with pure Python and and a LongBlob in MySQL.
Basically, once you have the binary data inside an element in a
Python list, you can do anything you want. I make a file out of
it (you could do the same, and then use wxImage functionality
to open the temp file):

def _writeBinFile(iid):
        record = dbConnect.dbRecordSet("select * from logentries
where iid=%s" % iid)
        if len(record) > 0:
                if os.path.exists('temp.ogg'):
                        os.remove('temp.ogg')

                outFile = open('temp.ogg', 'wb')
                outFile.write(record[0].mbinarydata)
                outFile.close()
                return 1
        else:
                return 0

···

--
Paul

Paul McNett wrote:

> A wxBitMap or wxImage method to do this does not immediately
> jump out at me. Can anyone help?

from the Wiki:

http://wiki.wxpython.org/index.cgi/WorkingWithImages

"""
wxImage to DATA -- myWxImage.GetData() returning a string in width *
height * 3 format

DATA to wxImage -- image = wxImage(); image.SetData( data ) where data
is a Python string of length width * height * 3.

"""

it (you could do the same, and then use wxImage functionality
to open the temp file):

There should be no need for temp files with the above methods.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (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

DATA to wxImage -- image = wxImage(); image.SetData( data ) where data
is a Python string of length width * height * 3.

That only works if you have decoded the image into RGB.

The answer is to use an input stream. Assuming your data
is a python binary string thedata:

import cStringIO
import wx

stream=wx.InputStream(cStringIO.StringIO(thedata))
image=wx.ImageFromStream(stream)

ImageFromStream isn't in the doc, but can be figured out.

Make sure you call wx.InitAllImageHandlers at some point.

Roger

Any chance you could add this to the Wiki? It really should get documented somewhere. This isn't the first timethis question has been asked.

-Chris

Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (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

···

On Tuesday, November 25, 2003, at 03:06 PM, Roger Binns wrote:

The answer is to use an input stream. Assuming your data
is a python binary string thedata:

import cStringIO
import wx

stream=wx.InputStream(cStringIO.StringIO(thedata))
image=wx.ImageFromStream(stream)

ImageFromStream isn't in the doc, but can be figured out.

Any chance you could add this to the Wiki?

I did some wiki stuff a while ago about installers and don't remember
what password I used. Quite simply I refuse to deal with yet another
account with yet another naming scheme for users with yet another set
of passwords. However do feel free to add it yourself.

It really should get documented somewhere.

Hopefully a lot of the stuff in 2.5 will fix this (like actual
pydoc strings). There are also other problems when dealing
with images and formats that need the wrappers updated. Robin
did acknowledge them as well. I assume he is currently adding
the 'solve world hunger' feature :slight_smile:

Roger

Hi Chris

wxImage to DATA -- myWxImage.GetData() returning a string in width *
height * 3 format

DATA to wxImage -- image = wxImage(); image.SetData( data ) where data
is a Python string of length width * height * 3.

Yes, but from the wxWindows docs

wxImage::GetData
Returns the image data as an array. This is most often used when doing

direct image manipulation. The return value points to an array of

characters in RGBRGBRGB... format. You should not delete the returned

pointer nor pass it to wxImage::SetData.

And from testing

Debug: e:\Projects\wx2.4\src\common\image.cpp(836): assert "wxAssertFa
ilure" failed: invalid image

Any thoughts?

Mike

stream=wx.InputStream(cStringIO.StringIO(thedata))
image=wx.ImageFromStream(stream)

Thanks Roger. I had a look and found a demo with this in it which
demonstrates this quite well.

Now, from a wxImage TO a string (or stream) without going through a temp
file? From the information you gave me, I notice that both
wxImage.LoadFile() and wxImage.SaveFile() in the wxWindows docs accept a
wxStream as the destination/source. Am I going in the right direction here?

Mike

Mike Edmonds wrote:

Debug: e:\Projects\wx2.4\src\common\image.cpp(836): assert "wxAssertFa
ilure" failed: invalid image

Any thoughts?

What does the code look like that generates this message?

···

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

Hi Robin

What does the code look like that generates this message?

This'll do it

from wxPython.wx import *

a = wxBitmap('bandw.bmp')
b = wxImageFromBitmap(a)
c = b.GetData()
d = wxEmptyImage()
d.SetData(c)

Mike

Now, from a wxImage TO a string (or stream) without going through a temp
file? From the information you gave me, I notice that both
wxImage.LoadFile() and wxImage.SaveFile() in the wxWindows docs accept a
wxStream as the destination/source. Am I going in the right direction here?

You are, but you are stuck. IIRC the saving to a stream methods are
not wrapped.

Roger

Roger Binns wrote:

> Any chance you could add this to the Wiki?

I did some wiki stuff a while ago about installers and don't remember
what password I used. Quite simply I refuse to deal with yet another
account with yet another naming scheme for users with yet another set
of passwords. However do feel free to add it yourself.

OK, here's an offer: if you (or anyone) writes up a paragraph or so
about the Image to stream stuff, and sends to to me, I'll post it in the
Wiki.

I think it needs a little more explaination than your post and a tested
example before I put it in. This way someone who understands this better
than I can write it, and I'll deal with the password hell and formatting
issues of the Wiki.

deal?

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (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 Chris

OK, here's an offer: if you (or anyone) writes up a paragraph or so
about the Image to stream stuff, and sends to to me, I'll post it in the
Wiki.

I know I was the one who asked the question, but since I have to solve it
one way or another I figure I'll have a working example after the weekend
(no it won't take me that long - I just have other things to do).

Since I don't consider myself an expert I have no idea what I would have to
do to take you up on your deal. But I'll give it a go. When I have it
working, what would you like from me?

Mike

Chris

OK, here's an offer: if you (or anyone) writes up a paragraph or so
about the Image to stream stuff, and sends to to me, I'll post it in the
Wiki.

I think it needs a little more explaination than your post and a tested
example before I put it in. This way someone who understands this better
than I can write it, and I'll deal with the password hell and formatting
issues of the Wiki.

Not that I know the technical nitty gritty, but I have created and tested
the following piece of code that could be used as an example.
1. It creates an empty bitmap and uses another Wiki example to write some
text to it.
2. It saves the bitmap to a file (since there is no wrapper for saving to a
stream or string)
3. It reads the file into a string and then saves the string to a text field
in a database using MySql and SQLObject
4. It then reads the field value out of the database, into a stream, into a
wxBitmap
5. And for good measure out to another file so you can see it actually
works.

from wxPython.wx import *

from SQLObject import *

from cStringIO import StringIO

class Person(SQLObject):
    _connection = MySQLConnection(host='localhost', db='jcpos',
                           user='test', passwd='')
    first_name = StringCol(length=100,default="")
    middle_initial = StringCol(length=1, default="")
    last_name = StringCol(length=100, default="")
    signature = StringCol(default="")

def _setupContext( memory, font=None, color=None ):
        if font:
                memory.SetFont( font )
        else:
                memory.SetFont(wxFont(20,wxSWISS,wxNORMAL,wxNORMAL))

        if color:
                memory.SetTextForeground( color )

def write( text, bitmap, pos=(0,0), font=None, color=None):
        """Simple write into a bitmap doesn't do any checking."""
        memory = wxMemoryDC( )
        _setupContext( memory, font, color )
        memory.SelectObject( bitmap )
        try:
                memory.DrawText( text, pos[0],pos[1],)
        finally:
                memory.SelectObject( wxNullBitmap)
        return bitmap

# 1. create a bitmap
myBitMap = write("Hello world", wxEmptyBitmap(200,50),color="WHITE")

# 2. Save it to a file in leiu of a stream
myBitMap.SaveFile("hello.bmp", wx.wxBITMAP_TYPE_BMP)

# 3. Open it and send it to a string
bitmapdata = open('hello.bmp', "rb").read()

# 4. And then to a database text field
newperson = Person.new(first_name="Mike")
newperson.signature = bitmapdata

# 6. Create a wxBitmap from the stream
listofpersons = Person.select()
for personobj in listofpersons:
    if personobj.first_name == "Mike":
        stream = StringIO(personobj.signature)
        newbmp = wxBitmapFromImage( wxImageFromStream( stream ))

# 7. Put it somewhere where you can look at it
newbmp.SaveFile("newhello.bmp", wx.wxBITMAP_TYPE_BMP)

Mike Edmonds wrote:

Not that I know the technical nitty gritty, but I have created and tested
the following piece of code that could be used as an example.

thanks, after a few questions have been resolved, I'll try to get a
chance to post this to the Wiki.

1. It creates an empty bitmap and uses another Wiki example to write some
text to it.
2. It saves the bitmap to a file (since there is no wrapper for saving to a
stream or string)

Is there really no way to save a Bitmap (or Image) to a string? If so,
then I think we realy do have a bug/missing feature. Was the
wxImage.SetData--wxImage.GetData issue resolved?

And/or will there be a wrapper for:

wxImage::SaveFile
SaveFile(wxOutputStream& stream, int type)

overloaded method?

3. It reads the file into a string and then saves the string to a text field
in a database using MySql and SQLObject

It'd be nice ot have an example that didn't use a data base, we want
Wiki examples to be as self contianed as possible.

4. It then reads the field value out of the database, into a stream, into a
wxBitmap
5. And for good measure out to another file so you can see it actually
works.

Otherwise, it looks like we're close to a Wiki page...

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (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

Mike Edmonds wrote:

Hi Robin

What does the code look like that generates this message?

This'll do it

from wxPython.wx import *

a = wxBitmap('bandw.bmp')
b = wxImageFromBitmap(a)
c = b.GetData()
d = wxEmptyImage()

You need to give width and height here.

···

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

Chris Barker wrote:

And/or will there be a wrapper for:

wxImage::SaveFile
SaveFile(wxOutputStream& stream, int type)

overloaded method?

That's on my ToDo list.

···

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

> 3. It reads the file into a string and then saves the string to a text

field

> in a database using MySql and SQLObject

It'd be nice ot have an example that didn't use a data base, we want
Wiki examples to be as self contianed as possible.

I figured that I would try to provide some point of difference to the code
that appears in the wxPython demo, but I can see your point. Here we go
then - without the database stuff:

from wxPython.wx import *

from cStringIO import StringIO

def _setupContext( memory, font=None, color=None ):
        if font:
                memory.SetFont( font )
        else:
                memory.SetFont(wxFont(20,wxSWISS,wxNORMAL,wxNORMAL))

        if color:
                memory.SetTextForeground( color )

def write( text, bitmap, pos=(0,0), font=None, color=None):
        """Simple write into a bitmap doesn't do any checking."""
        memory = wxMemoryDC( )
        _setupContext( memory, font, color )
        memory.SelectObject( bitmap )
        try:
                memory.DrawText( text, pos[0],pos[1],)
        finally:
                memory.SelectObject( wxNullBitmap)
        return bitmap

# 1. create a bitmap
myBitMap = write("Hello world", wxEmptyBitmap(200,50),color="WHITE")

# 2. Save it to a file in leiu of a stream
myBitMap.SaveFile("hello.bmp", wxBITMAP_TYPE_BMP)

# 3. Open it and send it to a string
bitmapdata = open('hello.bmp', "rb").read()

# 4. Create a stream
stream = StringIO(bitmapdata)
newbmp = wxBitmapFromImage( wxImageFromStream( stream ))

# 5. Put it somewhere where you can look at it
newbmp.SaveFile("newhello.bmp", wxBITMAP_TYPE_BMP)

Mike Edmonds