saveing an wximage object into an wxsqlite3 blob... Topic is solved

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

saveing an wximage object into an wxsqlite3 blob...

Post by ouch67 » Sun Mar 23, 2008 12:53 am

So I've programmed myself into a corner and can't seem to figure out a solution.

I have an 3MB+ jpeg, but I load it up and reduce the size to fit on screen as a thumbnail of sorts. I would like to save that thumbnail into an sqlite database as a blob.

The problem is that there doesn't seem to be any reliable way to convert a wximage into something that the wxsqlite3's bind commands will take.

the only thing I can think of is saveing the wximage to the drive and then reloading it. But there must be a more efficiant way.

Got any ideas?

mc2r
wxWorld Domination!
wxWorld Domination!
Posts: 1195
Joined: Thu Feb 22, 2007 4:47 pm
Location: Denver, Co
Contact:

Post by mc2r » Sun Mar 23, 2008 1:46 am

This tells you how to convert a wxImage to a wxMemoryBuffer and wxSqlite3 Blob takes a wxMemoryBuffer.

-Max

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Sun Mar 23, 2008 7:16 am

yes I know you can use GetData to save RGB info, however the docs for GetData say:

You should not delete the returned pointer nor pass it to wxImage::SetData.

So how do retore/load an image useing this method if you can't pass SetData info returned from GetData?

mc2r
wxWorld Domination!
wxWorld Domination!
Posts: 1195
Joined: Thu Feb 22, 2007 4:47 pm
Location: Denver, Co
Contact:

Post by mc2r » Sun Mar 23, 2008 5:24 pm

ouch67 wrote:yes I know you can use GetData to save RGB info, however the docs for GetData say:

You should not delete the returned pointer nor pass it to wxImage::SetData.
So, then don't delete that pointer or pass it to wxImage::SetData().
ouch67 wrote:So how do retore/load an image useing this method if you can't pass SetData info returned from GetData?
By reading the thread I gave you the link for, would be a good start, no?

You use wxImage::GetData() to get the pointer from the image.

That pointer only exists to get the data to store to the database, after that you use wxMemoryBuffer::GetData() to get a different pointer with the image data from the wxMemoryBuffer() and use that to set the wxImage.

I fail to see the problem.

-Max

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Mon Mar 24, 2008 6:51 pm

So will wxImage::SetData accept a wxMemoryBuffer pointer though?

Can you please post some sample code of this?

thanks for posting btw...

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Tue Mar 25, 2008 10:23 pm

and the answer to that is no it does not.

setdata demands const unsigned char* but wxMemoryBuffer::GetData outputs void.

and the post you linked to seems pretty useless as they focus on loading an image, editing it, and then saveing the image useing filestreams which I'm not doing.

anyone have any other ideas?

utelle
Moderator
Moderator
Posts: 971
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle » Tue Mar 25, 2008 11:51 pm

ouch67 wrote:setdata demands const unsigned char* but wxMemoryBuffer::GetData outputs void.
SetData demands unsigned char* and - what's more important - SetData takes ownership of the buffer passed to it. That is you have to use malloc (see documentation of wxImage::SetData) to allocate a buffer and then copy the data from the wxMemoryBuffer to this bew image buffer using memcpy and then you use SetData to assign the buffer to your wxImage object.

wxMemoryBuffer returns a void pointer since only you know what kind of data are contained in it. So use a type cast to vonvert void to the appropriate data type.
ouch67 wrote:and the post you linked to seems pretty useless as they focus on loading an image, editing it, and then saveing the image useing filestreams which I'm not doing.
If you do not want to store the raw image data in the database but instead as JPEG or PNG, you could use the methods LoadFile and SaveFile to read resp. write the image data as JPEG from a wxMemoryInputStream resp. to a wxMemoryOutputStream. You have to copy the memory stream data to/from a wxMemoryBuffer used for database transfer.

Regards,

Ulrich

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Wed Mar 26, 2008 8:10 pm

alright I keep getting invalid image when doing SetData and I'm not sure why. So I think it's time to unleash some code.


the user pushes a button witch runs this code. it's job is to take the file and resize it for display and DB storage, and finally display it:

Code: Select all

            path = FileDialog1->GetPath();
            fname = FileDialog1->GetFilename();
            picture.LoadFile(path, wxBITMAP_TYPE_ANY, -1);
            picture.Rescale(220,140,wxIMAGE_QUALITY_HIGH);
            BitmapButton1->SetBitmapLabel(wxBitmap(picture));
            picsize = picture.GetWidth() * picture.GetHeight() * 3;
This saves the image when the user pushes the button:

Code: Select all

    const unsigned char* rawpic = picture.GetData();
    sprintf(write,"update Customers set Picture = ? where ROWID = '%d';", SpinCtrl1->GetValue());
    wxSQLite3Statement stmt = db.PrepareStatement(write);
    stmt.Bind(1,rawpic,picsize);
    stmt.ExecuteUpdate();
this here loads the image from the database and fails at set data for some reason (it's only run if a row exists to load from at the program start):

Code: Select all

    wxSQLite3Blob picblob = db.GetBlob(SpinCtrl1->GetValue(),"Picture","Customers");
    wxMemoryBuffer picload;
    int blobsize = picblob.GetSize();
    picblob.Read(picload,blobsize,0);

    void* dat = malloc(picload.GetDataLen());
    dat = picload.GetData();

    picture.SetData((unsigned char*) dat,picload.GetDataLen());

utelle
Moderator
Moderator
Posts: 971
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle » Wed Mar 26, 2008 11:45 pm

ouch67 wrote:alright I keep getting invalid image when doing SetData and I'm not sure why. So I think it's time to unleash some code.
The code to store the image data into the database seems to be ok.
ouch67 wrote:this here loads the image from the database and fails at set data for some reason (it's only run if a row exists to load from at the program start):

Code: Select all

    wxSQLite3Blob picblob = db.GetBlob(SpinCtrl1->GetValue(),"Picture","Customers");
    wxMemoryBuffer picload;
    int blobsize = picblob.GetSize();
    picblob.Read(picload,blobsize,0);

    void* dat = malloc(picload.GetDataLen());
    dat = picload.GetData();

    picture.SetData((unsigned char*) dat,picload.GetDataLen());
This can not work since you overwrite the pointer dat with the address of the internal buffer of the wxMemoryBuffer. As I stated in my previous post you have to copy the data:

Code: Select all

memcpy(dat,picload.GetData(),blobsize
BTW using wxSQLite3Blob is not a good idea in the above situation, since you always want to read the whole blob. You should execute a query returning a resultset and then use methods NextRow() and

const unsigned char* GetBlob(int argIndex, int& len)

to retrieve a pointer to your image data. You still have to copy the data.

Regards,

Ulrich

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Thu Mar 27, 2008 7:12 pm

well I just want to get it to work at the moment.

heres what I have now with the memcpy change:

Code: Select all

    wxSQLite3Blob picblob = db.GetBlob(SpinCtrl1->GetValue(),"Picture","Customers");
    wxMemoryBuffer picload;
    int blobsize = picblob.GetSize();
    picblob.Read(picload, blobsize, 0);

    void* dat = malloc(picload.GetDataLen());
    memcpy(dat, picload.GetData(), blobsize);

    picture.SetData((unsigned char*) dat, picload.GetDataLen());
Sadly it still insists it's an invalid image...

utelle
Moderator
Moderator
Posts: 971
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Post by utelle » Thu Mar 27, 2008 8:55 pm

ouch67 wrote:well I just want to get it to work at the moment.

heres what I have now with the memcpy change:
...
Sadly it still insists it's an invalid image...
Without seeing the complete code it is impossible to tell what's going wrong. My guess is you did not initialize correctly the wxImage object "picture". You have to set the correct width and height in the wxImage constructor corresponding to the image data you stored in the database. Just then you will be able to use SetData.

Regards,

Ulrich

ouch67
Earned some good credits
Earned some good credits
Posts: 135
Joined: Sun Mar 23, 2008 12:09 am

Post by ouch67 » Fri Mar 28, 2008 6:48 pm

sure didn't...

works great now, thanks for all your help!

Post Reply