Retreiving images stored in MySQL

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
BlueStallion60
Earned a small fee
Earned a small fee
Posts: 10
Joined: Mon Feb 05, 2007 7:01 pm

Retreiving images stored in MySQL

Post by BlueStallion60 »

I have an application that stores images as a blob in a MySQL database. This database can be either on the local machine, or on a remote host. I store the image in the database using MySQL's load file, which works with the database engine either local or remote by using LOCAL. What I want to be able to do is retreive the image and display it in a window. If I am retreiving the image on the local host with the database engine, I can use MySQL's dump file, then use LoadFile to load the image, however, if the database engine is on a remote host, the dump file statement puts the image file on the remote host. Since I can use SELECT to get the blob to the local machine from a remote host, and since I can put the blob in a wxString, how do I get the image into either a wxBitmap, or a wxImage?

Thanks for the help.
cd_hodges
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Feb 03, 2005 4:46 pm

Post by cd_hodges »

You'll need to store more than just the image data. You will also need the width and height of the image. Once you have that it is quite easy to do:

Code: Select all


       //imagedata is defined as unsigned char*

	wxImage img(width,height,imagedata,true);
       

that's all there is to it. Now you can use the image to do your painting in your Paint handler.

Chris Hodges
BlueStallion60
Earned a small fee
Earned a small fee
Posts: 10
Joined: Mon Feb 05, 2007 7:01 pm

Post by BlueStallion60 »

Thaks for the quick reply Chris. It sent me off on a couple day of different attempts, but I still don't have it working. Here is what I'm doing. I am using the wxVillaLib graphics library. I like it for the scrolled window, the popup menu, the ability to scale the image, and I don't have to deal with dc and all that. As I mentioned before, my main problem is the ability to store the image in the MySQL database so that each client machine does not have to have the images on the local hard drive. The wxImageBox library only has LoadFile capabilities, and that seems to be from the local drive, which the MySQL dumpfile can only do if the database engine is on the local machine.

Based on your earlier reply, I have tried several ways to create the image from the blob returned from a MySQL SELECT statement. The problem I'm haveing is two fold. First converting the string returned by the SELECT statement to an unsigned char*. I finally figured out how to do this, I think, by doing some type casting, one character at a time, which is probably not the best way. but then the second problem, WxImageBox doesn't have a way to take an wxImage. I tried modifying the library to make m_image public, then assigining my converted image to it. This seemed to work, but when I compile my project, when the window is opened, the widgets are displayed, but the imagebox outline is drawn, and the app crashes. All i get is the Microsoft crash window. Oking it put me back in WxDevCpp. Next I trying making a function in the wxVillaLib library that takes a wxImage object and assinging it to m_image. Yhis is compiled and the new .a put in my lib directory, and I ge the same crash. One of the WxWidgets error dialogs talks of corrupted image files for .png and .jpg, and so on. So I'm thinking that my conversion from the string returned by MySQL to a wxImage is wrong, or the way that I'm putting it into the imagebox object is wrong. I beleive the blob stored in MySQL is good, as I can load my MySQL tool, and view the images in it's blob viewer.

Sorry for the long post, but hopefully someone can give me a hand.
toxicBunny
Super wx Problem Solver
Super wx Problem Solver
Posts: 424
Joined: Tue Jul 12, 2005 8:44 pm
Location: Alabama, USA

Post by toxicBunny »

I would suggest two things here. First, try using the DatabaseLayer library from the wxCode website. It works with many different databases (including MySQL) and handles loading and saving blob values easily. Second, once you have loaded the blob into memory, use a wxMemoryInputStream to allow wxImage::LoadFile to retrieve the file from memory.

-Scott
wxMSW 2.6.2, VS 2002, 2003 and 2005, Code::Blocks and mingw, Windows XP Pro
simdol
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Jan 01, 2005 1:54 am

Post by simdol »

The ODBC component that is coming with wxWidgets is enough to handle most database activities. I have been using it in my application.

The Image may be stored in the database as a BLOB. A real life example is quoted below. Here is the size is fixed. If you need, you could store the image size also in the database, then retrive the size first, and then define the storage dynamically based on the retrived size.

wxChar Image_ID[20+1]; //
wxChar Image_data[32765+1]; // buffer for the image data

//Bind the columns that are to be retrieved.
table->SetColDefs(0, "IMAGE_ID", DB_DATA_TYPE_VARCHAR, Image_ID, SQL_C_CHAR, sizeof(Image_ID), TRUE, FALSE);

table->SetColDefs(1, "IMAGE", DB_DATA_TYPE_BLOB, Image_data,
SQL_C_BINARY, sizeof(Image_data), FALSE, TRUE);

//Construct the where predicate.
where_predicate = "IMAGE_ID = '" + mImage_ID + "'";

I have two functions that will convert BLOB data into image files and vice versa. These may not be the most efficient. But it is working and you will get the idea.

bool mpcImage::ConvertImageToCharArray(char *image_data)
{
bool continue_flag = true;
//Since the saving to memory stream does not seems to be writing the file correctly,
//we are forced to write it into a real file and then read it back.
wxString file_name;
file_name += "./temp/temp1.jpg";
mpImage->SaveFile(file_name, wxBITMAP_TYPE_JPEG);
//mpImage.Destroy(); //delete the image in memory.
//Open the image file
wxFile file(file_name);
if (!(file.IsOpened()))
{
continue_flag = false;
wxMessageBox(wxT("Unable to open the temporary image processing file"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
}
//Read the image file
if (continue_flag)
{
if (file.Read(image_data, (size_t)file.Length()) != file.Length())
{
continue_flag = false;
wxMessageBox(wxT("Unable to Read the temporary image processing file"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
}
file.Close();
}

//delete the temporary image file
::wxRemoveFile(file_name);
return (continue_flag);
}

bool mpcImage::ConvertToFile(char *image_data)
{
bool continue_flag = true;
//Since the saving to memory stream does not seems to be writing the file correctly,
//we are forced to write it into a real file and then read it back.
wxString file_name;
file_name += "./temp/temp2.jpg";
wxFile file(file_name, wxFile::write);
if (!(file.IsOpened()))
{
continue_flag = false;
wxMessageBox(wxT("Unable to open the temporary image for writing"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
}
//Read the image file
if (continue_flag)
{
if (file.Write(image_data, 4468) != 4468)
{
continue_flag = false;
wxMessageBox(wxT("Unable to Write the temporary image processing file"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
}
file.Close();
}
::wxRemoveFile(file_name);
return (continue_flag);
}
Post Reply