PNG:s compiled into the binaries as resource possible?

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.
User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

PNG:s compiled into the binaries as resource possible?

Post by jokke » Tue Sep 28, 2004 3:42 pm

Hi!

I would like to have PNG:s that are compiled into my binary, and accessable for the program to display on the screen. Is this possible?
Regards,

/Joakim

eco
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 203
Joined: Tue Aug 31, 2004 7:06 pm
Location: Behind a can of Mountain Dew
Contact:

Post by eco » Thu Sep 30, 2004 5:50 am

Yes, I do it in mine. It isn't very...intuitive, but it works great. Let me reboot so I can get to my source code...brb...

eco
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 203
Joined: Tue Aug 31, 2004 7:06 pm
Location: Behind a can of Mountain Dew
Contact:

Post by eco » Thu Sep 30, 2004 6:20 am

This idea originally came from someone on the mailing list but I can't remember who. Anyway, he/she gets credit for the idea, whoever they were.

Alright, to embed the PNG you need to first convert it to a C array. I do it with a little GUI app I wrote based on Bart Trzynadlowski's console bin2c tool (copy and pasting the console output sucked which is why I wrote the GUI version). Here is the source code:

Code: Select all

// For compilers that don't support precompilation, include "wx/wx.h"
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
        #include "wx/wx.h"
#endif


class B2CFrame : public wxFrame
{
public:
       
        B2CFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = "frame");

        void onFileOpen(wxCommandEvent& arg_event);
        void onFileSave(wxCommandEvent& arg_event);
        void onFileExit(wxCommandEvent& arg_event);
       
        DECLARE_EVENT_TABLE()
};

class Bin2CGUIApp : public wxApp
{

public:

    virtual bool OnInit();

        void bin2c();

        wxString m_filename;

        B2CFrame* m_frame;
        wxTextCtrl* m_textctrl;
        wxString *validFilename;
        wxMenu* filemenu;

};


IMPLEMENT_APP(Bin2CGUIApp)

enum
{
        B2C_FILE_OPEN = 1000,
        B2C_FILE_SAVE,
        B2C_FILE_EXIT
};


/* this is executed upon startup, like 'main()' in non-wxWindows programs */
bool Bin2CGUIApp::OnInit()
{
        m_filename = _T("");

        m_frame = new B2CFrame((wxFrame*) NULL, -1, _T("Binary to C"), wxDefaultPosition, wxSize(800,600));
       
        m_textctrl = new wxTextCtrl(m_frame, -1, _T(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_RICH2);
        wxFont textfont(10, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE, _T("Courier New"));
        wxTextAttr textattr(*wxBLACK, *wxWHITE, textfont);
        m_textctrl->SetDefaultStyle(textattr);

        wxMenuBar* menubar = new wxMenuBar();
        filemenu = new wxMenu();
        filemenu->Append(B2C_FILE_OPEN, _T("&Open..."));
        filemenu->Append(B2C_FILE_SAVE, _T("&Save..."));
        filemenu->AppendSeparator();
        filemenu->Append(B2C_FILE_EXIT, _T("&Exit"));
       
        filemenu->Enable(B2C_FILE_SAVE, false);

        menubar->Append(filemenu, _T("&File"));

        m_frame->SetMenuBar(menubar);

    m_frame->Show(TRUE);
    SetTopWindow(m_frame);


    return true;
}



void Bin2CGUIApp::bin2c()
{
        /* This "algorithm" is based on Bart Trzynadlowski bin2c program written on June 11, 2001 */
        m_textctrl->Clear();
        FILE            *fp;
        long            size, i;
        unsigned char   data;

        if((fp = fopen(m_filename, "rb")) == NULL)
        {
                wxMessageBox(wxString(_T("Unable to open file")));
                return;
        }

        fseek(fp, 0, SEEK_END);
        size = ftell(fp);
        rewind(fp);

        validFilename = new wxString(m_filename.AfterLast('\\').Lower());
        validFilename->Replace(_T(">"), _T("_"));
        validFilename->Replace(_T("<"), _T("_"));
        validFilename->Replace(_T("="), _T("_"));
        validFilename->Replace(_T("!"), _T("_"));
        validFilename->Replace(_T("&"), _T("_"));
        validFilename->Replace(_T("|"), _T("_"));
        validFilename->Replace(_T("-"), _T("_"));
        validFilename->Replace(_T("["), _T("_"));
        validFilename->Replace(_T("]"), _T("_"));
        validFilename->Replace(_T("^"), _T("_"));
        validFilename->Replace(_T(":"), _T("_"));
        validFilename->Replace(_T(","), _T("_"));
        validFilename->Replace(_T("{"), _T("_"));
        validFilename->Replace(_T("}"), _T("_"));
        validFilename->Replace(_T("."), _T("_"));
        validFilename->Replace(_T("*"), _T("_"));
        validFilename->Replace(_T("("), _T("_"));
        validFilename->Replace(_T(")"), _T("_"));
        validFilename->Replace(_T("+"), _T("_"));
        validFilename->Replace(_T("%"), _T("_"));
        validFilename->Replace(_T("#"), _T("_"));
        validFilename->Replace(_T("?"), _T("_"));
        validFilename->Replace(_T("/"), _T("_"));
        validFilename->Replace(_T("*"), _T("_"));
        validFilename->Replace(_T("~"), _T("_"));
        validFilename->Replace(_T("\\"), _T("_"));
        validFilename->Replace(_T("."), _T("_"));
        validFilename->Replace(_T(" "), _T("_"));
        m_textctrl->AppendText(_T("unsigned char "));
        m_textctrl->AppendText(_T(*validFilename));
        m_textctrl->AppendText(_T("[] ="));
        m_textctrl->AppendText(_T("{"));
        m_textctrl->AppendText(_T("\n"));
                       
        i = 0;
        while (size--)
        {
                fread(&data, sizeof(unsigned char), 1, fp);

                if (!i)
                        m_textctrl->AppendText("\t");
                if (size == 0)
                        m_textctrl->AppendText(wxString::Format("0x%02X\n};\n", data));
                else
                        m_textctrl->AppendText(wxString::Format("0x%02X,", data));
                i++;
                if (i == 14)
                {
                        m_textctrl->AppendText("\n");
                        i = 0;
                }
        }

        fclose(fp);
}


BEGIN_EVENT_TABLE(B2CFrame, wxFrame)
        EVT_MENU(B2C_FILE_OPEN, B2CFrame::onFileOpen)
        EVT_MENU(B2C_FILE_SAVE, B2CFrame::onFileSave)
        EVT_MENU(B2C_FILE_EXIT, B2CFrame::onFileExit)
END_EVENT_TABLE()

B2CFrame::B2CFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
: wxFrame(parent, id, title, pos, size, style, name)
{

}

void B2CFrame::onFileOpen(wxCommandEvent& WXUNUSED(event)t)
{
        wxFileDialog fileDialog(this, _T("Select a file"), _T(""), _T(""), _T("*.*"), wxOPEN);

        if(fileDialog.ShowModal() == wxID_OK)
        {
                wxGetApp().filemenu->Enable(B2C_FILE_SAVE, true);
                wxGetApp().m_filename = fileDialog.GetPath();
                wxGetApp().bin2c();
        }
}

void B2CFrame::onFileSave(wxCommandEvent& WXUNUSED(event))
{
        wxFileDialog fileDialog(this, _T("Save in a file"), _T(""), (*wxGetApp().validFilename)+".h" ,  "header files (*.h)|*.h|c code files (*.c)|*.c|c++ code files (*.cpp)|*.cpp", wxSAVE);

        if(fileDialog.ShowModal() == wxID_OK)
        {
            wxGetApp().m_textctrl->SaveFile(fileDialog.GetPath()); 
        }
}
               
void B2CFrame::onFileExit(wxCommandEvent& WXUNUSED(event))
{
     Destroy();
}

Update: Changed source to match updates done by SuperPat (apparent build error fixes and completion of unfinished features)

Load your image, then copy and paste the output into wherever you want to in your source (or save it has it's own header file).

Anyway, once you have that in the source, loading it is easy (this assumes your image array was named "file_png"):

Code: Select all

#include "file_png.h"

wxMemoryInputStream png_stream(file_png, sizeof(file_png));
wxBitmap bitmap (wxImage(png_stream, wxBITMAP_TYPE_PNG)); 
And now you have a wxImage and a wxBitmap with the PNG. You need to make sure you've loaded the PNG image handler before trying to load it of course (a call to wxInitAllImageHandlers() somewhere during the application initialization takes care of that easily enough).

I hope you find this useful.

Edit: Silly Rabbit, typos are for kids. :)
Last edited by eco on Mon Jan 02, 2006 12:04 am, edited 2 times in total.

User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

Post by jokke » Thu Sep 30, 2004 10:20 am

Hi!

Thank you, that is a great solution! I was elaborating with similar things, and now it works the way I want it. Excellent!
Regards,

/Joakim

Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Post by Tyler » Sun Oct 03, 2004 5:40 am

Not that it's probably of any consequence now, but I use embedded XRC for all of my resources and it works great.

User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

Post by jokke » Tue Oct 05, 2004 1:57 pm

Tyler, I was looking for XRC initially, but reading documentation back and forth, I did not get a grip on it. How did you do that?

Except for that, considering my static library with the compiled images, I have some problems with my linker (VC++), and I am trying to sort that out. My C-files containing the image data declare arrays of unsigned char, and then I list those in a header file as extern unsigned char. Setting both to just unsigned char works if I just want to link the images in one object file, but not for multiple. I know I am doing something wrong here, but cannot figure what. If anybody would have input on this, what would be great.

Or, if I can use Tyler's method using embedded XRC, perhaps the problem would be solved that way. :)
Regards,

/Joakim

Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Post by Tyler » Tue Oct 05, 2004 9:00 pm

Hey Jokke,

I had the same problem you did. I don't know why there isn't any documentation on doing embedded XRC. It's really nice to be able to ship a standalone executable, and especially nice to conceal my images in the application since I am not doing skinning.

The first thing you will need to do is compile XRC. It's in the contrib directory. I always build Windows Debug and Windows Release.
Next, you will need to build WXRC. In wxMSW 2.5.1, WXRC did not compile for me under MSVC++ 6.0 SP 2, on XP Pro. You can view my bug report (and fix) here: https://sourceforge.net/tracker/?func=d ... tid=109863 I don't know if this will be an issue on your machine or not, but I thought to mention it here just in case you ran into trouble.


After XRC and WXRC are built, it's time to create your XRC script. It looks like this:

resources.xrc

Code: Select all

<?xml version="1.0"?>
<resource version="2.3.0.1">


<object class="wxBitmap" name="FIRST_IMG">first.gif</object>
<object class="wxBitmap" name="SECOND_IMG">second.jpg</object>

</resource>
Now, assuming WXRC, resources.xrc, first.gif, and second.jpg are all in the same directory, run the following from the command line: wxrc.exe /c /v resources.xrc

This will produce a resources.cpp. Check it out. Those two images have been compressed and encoded so XRC can understand them and embed them in your application.

Ok, time to put all this into VS. Add resources.cpp to your project (so the compiler will compile it). Make sure VS can find the xrc libraries (set your linking properly if needed), and add:

Code: Select all

#include "wx/xrc/xmlres.h"
#include "wx/image.h"
#include "MyResources.h"
in your main.cpp file above MyApp::OnInit. MyResources.h is a file I created (yes create one). Mine looks like:

MyResources.h

Code: Select all

#ifndef MYRESOURCES_H
#define MYRESOURCES_H

extern void InitXmlResource();

#endif

Now, within your MyApp::OnInit function, place the following three lines:

Code: Select all

wxInitAllImageHandlers();
wxXmlResource::Get()->InitAllHandlers(); 
InitXmlResource();
Alright, you're almost done. You've now successfully built the XRC library, linked it into your projects, embedded your resources actually into the executable and told your application that you are going to use embedded XRC. The only thing left is to load the images.

To load from your embedded resource, the following would load an image up:

Code: Select all

wxBitmap* myImage = new wxBitmap();
*myImage =  wxXmlResource::Get()->LoadBitmap("FIRST_IMG");
Do you get it? Pretty cool huh? Notice you don't need to worry anything about the types. wxWindows is smart enough to figure out what you're working with.

Embedded XRC is one of the best things I like about wxWindows. It's a shame it's not better documented, but now that I've got it working, I can find no better alternative. 8)

Let me know if this works, or where you run into problems.

Mampfred
Knows some wx things
Knows some wx things
Posts: 26
Joined: Tue Aug 31, 2004 2:28 pm
Location: Germany
Contact:

Post by Mampfred » Wed Oct 06, 2004 7:47 am

Tyler wrote:The first thing you will need to do is compile XRC. It's in the contrib directory. I always build Windows Debug and Windows Release.
Note that XRC was moved lately from contrib to the "official" wx. Although this has only been done in CVS I thought I mention it here so there is no confusion after a new version has been released and people look up this thread ;).

Apart from that, very nice description :) I wish it existed back when I started to do embed my graphics ;)

User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

Post by jokke » Wed Oct 06, 2004 11:57 am

THANKS A LOT!!

This works great, and is an absolutely smashing solution!
I found out the bugs for wxrc 2.5.1 are solved to 2.5.2, so I did not have to change anything there. Only issue was getting link info correct, but now it runs the way it should. I am really grateful for this!

For others doing the same thing, the wx-related libraries (MSW) for the linker to use were: (Debug mode)

wxmsw25d_core.lib wxmsw25d_adv.lib wxmsw25d_xrc.lib wxmsw25d_html.lib wxbase25d.lib wxbase25d_xml.lib wxexpatd.lib pngd.lib jpegd.lib tiffd.lib zlibd.lib
Regards,

/Joakim

User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

Post by jokke » Wed Oct 06, 2004 3:40 pm

...but certainly, I did run into problems later on:

I have a wxApp derived class where I do the XRC initialization. In another class, derived from wxPanel, I load some images from the resources as decribed above. Works like a charm.

In another class, not derived from anything, I use the same procedure, wxXmlResource::Get()->LoadBitmap("RESOURCENAME"), and it all compiles. BUT: When running the application, trying to load the images in this class gives me errors in the log window for each image:

(X) XRC resource 'RESOURCENAME' (class 'wxBitmap') not found!

The images tested are the same as those that would load prefectly in the first class. Is there some wx-stuff that the other class should inherit from wx or something like that?
Regards,

/Joakim

Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Post by Tyler » Thu Oct 07, 2004 6:54 pm

Hey guys,

I'm glad you think the post is good, and I'm glad you got it working. Yea I've found embedded XRC to be awesome and indespensable.

In regards to your question about using embedded XRC in non-wxWindows derived classes, I couldn't give you a definitive answer on that. I have only used it in classes derived from the wx hierarchy.

I speculate though that you may need to inherit from the hierachy in order for wxXmlResource to allow you to bind during runtime. This would be akin to how event tables can only be used after wxEvtHandler has been introduced somewhere along the inheritance chain. So just as you can't use events without deriving from wx, you probably can't use wxXmlResource without derivation as well.

It wouldn't surprise me if that were the case.

User avatar
jokke
Earned a small fee
Earned a small fee
Posts: 16
Joined: Mon Sep 06, 2004 9:37 am
Location: Lund, Sweden
Contact:

Post by jokke » Tue Oct 19, 2004 9:01 am

Actually, I tested this for a class where it would not wok; I simply let it inherit from some varius wx classes. Regardless what classes, the result was the same. Anyway, I got it working, but cannot remember how. :) I guess I had forgotten to include some stuff or something like that.

Anyhow, I found that my assumptions that it might differ if my class was a wx-derived class or not were not in line with reality.
Regards,

/Joakim

daddydave
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 214
Joined: Wed Jun 15, 2005 3:31 am
Location: United States
Contact:

Post by daddydave » Sun Sep 25, 2005 5:46 am

jokke wrote:
For others doing the same thing, the wx-related libraries (MSW) for the linker to use were: (Debug mode)

wxmsw25d_core.lib wxmsw25d_adv.lib wxmsw25d_xrc.lib wxmsw25d_html.lib wxbase25d.lib wxbase25d_xml.lib wxexpatd.lib pngd.lib jpegd.lib tiffd.lib zlibd.lib
Using wx-devcpp 6.8beta-alpha.. + NinjaNL's devpak for 2.6.2 (not sure if the devpak matters in this case),
the only thing I had to add to the linker options was
-lwxmsw26_gizmos_xrc
Without that, it seems to build fine but gives the error(s):
XRC resource 'RESOURCENAME' (class 'wxBitmap') not found!
at runtime for each image resource.

The wxrc.cpp file is not included in the wx-devcpp distribution, but I happened to have a standard wxwidgets-2.6.1 install as well, lying mostly dormant, and I just created a project with this one file and no problems compiling.

Sure was frustrating when I got that error though, but it is caused by a missing library

User avatar
T-Rex
Moderator
Moderator
Posts: 1198
Joined: Sat Oct 23, 2004 9:58 am
Location: Zaporizhzhya, Ukraine
Contact:

Post by T-Rex » Sun Feb 05, 2006 5:29 pm

I modified the source code a little bit to make the usage of this utility more convenient... maybe it will be useful for others.

Bin2CGUIApp.h

Code: Select all

#ifndef _BIN2CGUIAPP_H
#define _BIN2CGUIAPP_H

class B2CFrame : public wxFrame
{	
	wxTextCtrl* m_TextCtrl;	
public:

	B2CFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = "frame");
	wxString Bin2C(wxString filename);
	DECLARE_EVENT_TABLE()
	void onFileOpen(wxCommandEvent& arg_event);
	void onFileSave(wxCommandEvent& arg_event);
	void onFileExit(wxCommandEvent& arg_event);
	void onAbout(wxCommandEvent& arg_event);
};

class Bin2CGUIApp : public wxApp
{
public:
	virtual bool OnInit();
};

DECLARE_APP(Bin2CGUIApp)

#endif

Bin2CGUIApp.cpp

Code: Select all

// For compilers that don't support precompilation, include "wx/wx.h"
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "Bin2CGUIApp.h"
#include <wx/progdlg.h>

IMPLEMENT_APP(Bin2CGUIApp)

BEGIN_EVENT_TABLE(B2CFrame, wxFrame)
EVT_MENU(wxID_OPEN, B2CFrame::onFileOpen)
EVT_MENU(wxID_SAVE, B2CFrame::onFileSave)
EVT_MENU(wxID_EXIT, B2CFrame::onFileExit)
EVT_MENU(wxID_ABOUT, B2CFrame::onAbout)
END_EVENT_TABLE()

B2CFrame::B2CFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
: wxFrame(parent, id, title, pos, size, style, name)
{
	wxMenuBar* menubar = new wxMenuBar();
	wxMenu* filemenu = new wxMenu();
	filemenu->Append(wxID_OPEN, _T("&Open\tCtrl+O"));
	filemenu->Append(wxID_SAVE, _T("&Save\tCtrl+S"));
	filemenu->AppendSeparator();
	filemenu->Append(wxID_EXIT, _T("&Exit\tAlt+F4"));

	wxMenu* helpmenu = new wxMenu();
	helpmenu->Append(wxID_ABOUT, _T("&About..."));

	menubar->Append(filemenu, _T("&File"));
	menubar->Append(helpmenu, _T("&Help"));
	SetMenuBar(menubar);

	m_TextCtrl = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxDefaultSize, 
		wxTE_MULTILINE|wxTE_RICH2|wxTE_READONLY);
	wxFont textfont(10, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE, _T("Courier New"));
	wxTextAttr textattr(*wxBLACK, *wxWHITE, textfont);
	m_TextCtrl->SetFont(textfont);
	m_TextCtrl->SetDefaultStyle(textattr);

	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);
	sizer->Add(m_TextCtrl, 1, wxEXPAND);

	CreateStatusBar(2);

	Centre();
}

void B2CFrame::onFileOpen(wxCommandEvent& arg_event)
{
	wxFileDialog fileDialog(this, _T("Select a file"), _T(""), _T(""), _T("*.*"), wxOPEN);
	if(fileDialog.ShowModal() == wxID_OK)
	{				
		m_TextCtrl->SetValue(Bin2C(fileDialog.GetPath()));				
	}
}

void B2CFrame::onFileSave(wxCommandEvent& arg_event)
{
	wxFileDialog fileDialog(this, _T("Select a file"), _T(""), _T(""), 
		_T("Header Files (*.h;*.hpp)|*.h;*.hpp|Text Files (*.txt)|*.txt|All Files (*.*)|*.*"), 
		wxSAVE);
	if(fileDialog.ShowModal() == wxID_OK)
	{		
		FILE * fp = fopen(fileDialog.GetPath(), "w+t");
		if(!fp)
		{
			wxMessageBox(wxT("Can't create file!!!"));
			return;
		}
		fwrite(m_TextCtrl->GetValue(), sizeof(wxChar), m_TextCtrl->GetValue().Length(), fp);
		fclose(fp);
	}
}

void B2CFrame::onFileExit(wxCommandEvent& arg_event)
{
	Close();
} 

wxString B2CFrame::Bin2C(wxString filename)
{
	wxString res = wxEmptyString;	
	FILE            *fp;
	long            size, i, fsize;
	unsigned char   data;

	if((fp = fopen(filename, "rb")) != NULL)
	{		

		fseek(fp, 0, SEEK_END);
		fsize = size = ftell(fp);
		rewind(fp);

		wxString validFilename = filename.AfterLast('\\').Lower();
		validFilename.Replace(_T(">"), _T("_"));
		validFilename.Replace(_T("<"), _T("_"));
		validFilename.Replace(_T("="), _T("_"));
		validFilename.Replace(_T("!"), _T("_"));
		validFilename.Replace(_T("&"), _T("_"));
		validFilename.Replace(_T("|"), _T("_"));
		validFilename.Replace(_T("-"), _T("_"));
		validFilename.Replace(_T("["), _T("_"));
		validFilename.Replace(_T("]"), _T("_"));
		validFilename.Replace(_T("^"), _T("_"));
		validFilename.Replace(_T(":"), _T("_"));
		validFilename.Replace(_T(","), _T("_"));
		validFilename.Replace(_T("{"), _T("_"));
		validFilename.Replace(_T("}"), _T("_"));
		validFilename.Replace(_T("."), _T("_"));
		validFilename.Replace(_T("*"), _T("_"));
		validFilename.Replace(_T("("), _T("_"));
		validFilename.Replace(_T(")"), _T("_"));
		validFilename.Replace(_T("+"), _T("_"));
		validFilename.Replace(_T("%"), _T("_"));
		validFilename.Replace(_T("#"), _T("_"));
		validFilename.Replace(_T("?"), _T("_"));
		validFilename.Replace(_T("/"), _T("_"));
		validFilename.Replace(_T("*"), _T("_"));
		validFilename.Replace(_T("~"), _T("_"));
		validFilename.Replace(_T("\\"), _T("_"));
		validFilename.Replace(_T("."), _T("_"));
		validFilename.Replace(_T(" "), _T("_"));
		res += wxString::Format(wxT("unsigned char %s[] ="), validFilename.GetData());
		res += wxT("{\n");

		i = 0;
		wxProgressDialog * dlg = new wxProgressDialog(wxT("Processing..."), 
			wxT("Converting binary file:"), 100, this,
			wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_SMOOTH|wxPD_CAN_ABORT);
		while (size--)
		{
			fread(&data, sizeof(unsigned char), 1, fp);

			if (!i)
				res += wxT("\t");
			if (size == 0)
				res += wxString::Format(wxT("0x%02X\n};\n"), data);
			else
				res += wxString::Format(wxT("0x%02X,"), data);
			i++;
			if (i == 14)
			{
				res += wxT("\n");
				i = 0;
			}
			if(!dlg->Update((int)((double)(fsize-size)/(double)fsize*100.0)))
			{
				res = wxEmptyString;
				break;
			}
		}
		fclose(fp);	
		dlg->Destroy();
	}	
	return res;
}

void B2CFrame::onAbout(wxCommandEvent& arg_event)
{
	wxMessageBox(wxT("Bin2C Utility\r\nConverts binary file to C-style byte array"));
}

/* this is executed upon startup, like 'main()' in non-wxWindows programs */
bool Bin2CGUIApp::OnInit()
{
	B2CFrame * frame = new B2CFrame((wxFrame*) NULL, -1, _T("Binary to C"), wxDefaultPosition, wxSize(700,450));	
	SetTopWindow(frame);
	frame->Show(TRUE);
	return true;
}


Trikko
Experienced Solver
Experienced Solver
Posts: 94
Joined: Tue Oct 18, 2005 8:28 pm
Location: Venice, IT
Contact:

Post by Trikko » Tue Feb 07, 2006 10:41 am

eco wrote:This idea originally came from someone on the mailing list but I can't remember who. Anyway, he/she gets credit for the idea, whoever they were.

Alright, to embed the PNG you need to first convert it to a C array. I do it with a little GUI app I wrote based on Bart Trzynadlowski's console bin2c tool (copy and pasting the console output sucked which is why I wrote the GUI version). Here is the source code:

...

Edit: Silly Rabbit, typos are for kids. :)
I think you mean the code you can find on wxWiki. It's called bin2c and it's under "embedding png image..." topic or something else.

By the way i think you can load it even in a simplier way: using a virtual filesystem (adding png c arrays to it) and then loading them with "memory:path/to/image.png". More confortable and easy than memorystream!

Post Reply