wxUiEditor icon indicating copy to clipboard operation
wxUiEditor copied to clipboard

Add tool for converting an SVG file into a multiple-resolution Windows icon

Open KeyWorksRW opened this issue 1 year ago • 4 comments

Description:

A common method of setting and Icon for a Windows executable is to set the APPICON in the resource file. Unfortunately, you can't supply a SVG file for this icon. It would be handy if wxUiEditor had a tool that would take an SVG file and convert it to a Windows icon using 16x16, 32x32, 48x48 and 256x256. Besides being useful for wxUiEditor itself, it could potentially be useful for anyone else wanting to use an SVG file for the application's icons.

KeyWorksRW avatar Feb 07 '24 19:02 KeyWorksRW

From @Kumazuma:

It is simple way that make ico file from wxBitmapBundle. the ICO file is supported from Windows Vista and later. This code was referenced from Wikipedia.

#include <wx/bmpbndl.h>
#include <wx/wfstream.h>

struct IconDir {
	uint16_t reserved;
	uint16_t image_type;
	uint16_t num_of_images;
};

struct IconDirEntry {
	uint8_t width;
	uint8_t height;
	uint8_t color_palette;
	uint8_t reserved;
	uint16_t color_planes;
	uint16_t bits_per_pixel;
	uint32_t bytes_width_of_image;
	uint32_t offset_of_image;
};

bool SaveBundleToIco(wxOutputStream& stream, wxBitmapBundle& bundle) {
	if(!stream.IsSeekable())
		return false;

	const wxFileOffset offset_start = stream.TellO();
	IconDir header{};
	IconDirEntry entries[4] {};

	header.image_type = 1;
	header.num_of_images = 4;

	entries[0].width = 16;
	entries[0].height = 16;

	entries[1].width = 32;
	entries[1].height = 32;

	entries[2].width = 48;
	entries[2].height = 48;

	entries[3].width = 0;
	entries[3].height = 0;

	stream.Write(&header, sizeof(header));
	stream.Write(&entries, sizeof(entries));
	for(auto& entry: entries) {
		int size = entry.width != 0 ? entry.width : 256;
		wxBitmap bitmap = bundle.GetBitmap(wxSize(size, size));
		wxImage img = bitmap.ConvertToImage();
		entry.offset_of_image = stream.TellO();
		img.SaveFile(stream, wxBITMAP_TYPE_PNG);
		entry.bytes_width_of_image = stream.TellO() - entry.offset_of_image;
		entry.bits_per_pixel = 32;
		entry.color_planes = 0;
	}

	stream.SeekO(offset_start + sizeof(header));
	stream.Write(&entries, sizeof(entries));
	return true;
}

KeyWorksRW avatar Apr 03 '24 12:04 KeyWorksRW

Thanks! I copied your email directly into the issue. I hadn't looked into wxIcon, so I mistakenly thought I could just create a wxIcon and call it's save method -- but it doesn't have one, so your info will be very helpful.

KeyWorksRW avatar Apr 03 '24 12:04 KeyWorksRW

I appreciate about it is helped you. however it should be changed in the code.

		entry.bits_per_pixel = (entry.bytes_width_of_image / (size * size)) * 8;

to

		entry.bits_per_pixel = 32;

Kumazuma avatar Apr 03 '24 12:04 Kumazuma

Okay, I updated the code above.

KeyWorksRW avatar Apr 03 '24 15:04 KeyWorksRW