Best practice about portable toolbar icons

105 views
Skip to first unread message

Umberto Carletti

unread,
Jun 1, 2018, 11:38:53 AM6/1/18
to wx-users
Hello,
I want to put on my frame a toolbar with some icons and I would like to know what is the best way to resize them depending on the screen's PPI. I don't want the icons to look small on high PPI screens and large on low PPI screens.
In particular where should I store the icons and in which format depending on the platform (MSW, GTK, OSX)?
Should I provide multiple scale images or should I rescale in the program?
Kind regards
Umberto

Gunter Königsmann

unread,
Jun 1, 2018, 11:58:30 AM6/1/18
to wx-u...@googlegroups.com
Scaling down icons by a factor of 2^n works fine. Scaling them down by odd factors will cause the antialiasing to produce unfine blur => wxMaxima provides two sets of icons: 256x256 and 192x192 pixels and it chooses one that when scaled down by 2^n has the Right Size. A bit of work, that. But creates great visual results.

--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.
 
To unsubscribe, send email to wx-users+u...@googlegroups.com
or visit http://groups.google.com/group/wx-users

Igor Korot

unread,
Jun 1, 2018, 12:04:41 PM6/1/18
to wx-u...@googlegroups.com
Hi,
For OSX you should create scaled version of the icon, name it "my_icon@2"
and refer to it inside the plist file of the bundle.
For MSW you can create a scaled version of the bitmap and store it
inside the resource file or just use XPM. I'm not sure how Windows will select
the appropriate icon. Someone else will probably answer that.
For GTK the best way to store it is o use XPM. Again how the program
will select it
I don't know.

You can look at the toolbar sample provided with the library and see
if it will scale
everything on HiDPI monitor.

Thank you.

Vadim Zeitlin

unread,
Jun 1, 2018, 12:31:40 PM6/1/18
to wx-u...@googlegroups.com
On Fri, 1 Jun 2018 08:37:40 -0700 (PDT) Umberto Carletti wrote:

UC> I want to put on my frame a toolbar with some icons and I would like to
UC> know what is the best way to resize them depending on the screen's PPI. I
UC> don't want the icons to look small on high PPI screens and large on low PPI
UC> screens.

This is an area where wxWidgets still needs some improvements. Currently
things work well automatically only under Mac, where you just need to
provide the normal and normal@2x icons and the right one will be selected
depending on whether high DPI is used or not. For MSW and Unix you
currently have to do something similar in your own code (hopefully this
will be fixed in wxWidgets 3.2).

UC> In particular where should I store the icons and in which format depending
UC> on the platform (MSW, GTK, OSX)?

The format to use is PNG (please ignore advice to use XPM or any other
format without alpha channel support) under all platforms. The location is
platform-dependent however: under macOS, the icons should be in
Contents/Resources subdirectory of your application bundle (it's also
possible to have language-specific resources, but let's keep things simple
for now). Under MSW, icons normally are embedded in the Windows resources,
but you need to use RCDATA resource type for PNG files and not ICON. Then
you can use wxBitmap ctor with wxBITMAP_TYPE_PNG_RESOURCE or the convenient
wxBITMAP_PNG() macro to load them easily.

Under Unix you can use either approach, i.e. you could look for the .png
files in some prefix-relative directory, or you can embed the files into
the program itself. In the latter case, you will find misc/scripts/png2c.py
useful -- and if you do it like this, wxBITMAP_PNG() will also work for you
under Unix (otherwise you'd have to use wxBITMAP_PNG_FROM_DATA() there).


UC> Should I provide multiple scale images or should I rescale in the program?

Rescaling will almost never give really good results, so the best is to
have the images at all the different sizes. It is often difficult to cover
all of them, e.g. just for macOS you're supposed to provide the icons in
sizes 16, 24, 32, 48, 64, 128, 256, 512 pixels as well as the high DPI
versions of all of those, because normally you're even supposed to use
different icons of size 2*N in normal DPI and N in high DPI. So in practice
you might have to live with scaling for at least some of them, but it's
better to do it once outside of the program rather than do it during the
run-time.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Igor Korot

unread,
Jun 1, 2018, 1:17:29 PM6/1/18
to wx-u...@googlegroups.com
Vadim,

On Fri, Jun 1, 2018 at 11:31 AM, Vadim Zeitlin <va...@wxwidgets.org> wrote:
> On Fri, 1 Jun 2018 08:37:40 -0700 (PDT) Umberto Carletti wrote:
>
> UC> I want to put on my frame a toolbar with some icons and I would like to
> UC> know what is the best way to resize them depending on the screen's PPI. I
> UC> don't want the icons to look small on high PPI screens and large on low PPI
> UC> screens.
>
> This is an area where wxWidgets still needs some improvements. Currently
> things work well automatically only under Mac, where you just need to
> provide the normal and normal@2x icons and the right one will be selected
> depending on whether high DPI is used or not. For MSW and Unix you
> currently have to do something similar in your own code (hopefully this
> will be fixed in wxWidgets 3.2).
>
> UC> In particular where should I store the icons and in which format depending
> UC> on the platform (MSW, GTK, OSX)?
>
> The format to use is PNG (please ignore advice to use XPM or any other
> format without alpha channel support) under all platforms.

Is there a reason why our own toolbar sample still referencing the use of XPM?
Granted it is guarded with the #if block, but it is still there.

Maybe it is time to get rid of them and just update documentation saying that
preferred format for all 3 major platforms is PNG due to the alpha channel
support? And maybe even mention somewhere that XPM format is discouraged
for that same reason unless you don't care about alpha?

Frédéric

unread,
Jun 1, 2018, 2:07:41 PM6/1/18
to wx-u...@googlegroups.com
> Currently
> things work well automatically only under Mac, where you just need to
> provide the normal and normal@2x icons and the right one will be selected
> depending on whether high DPI is used or not.

So do you mean you have to provide 1 icns file with:
16, 24, 32, 48, 64, 128, 256, 512
combined with those sizes x2
32, 48, 64, 96, 128, 256, 512, 1024
so all together in one single icns file:
16, 24, 32, 48, 64, 96, 128, 256, 512, 1024?

or 2 separate icns files?

F

Gunter Königsmann

unread,
Jun 1, 2018, 2:17:29 PM6/1/18
to wx-u...@googlegroups.com
Using an utility like xd one could include a .PNG file within the executable and then load it from a wxMemoryBuffer. Pro: avoids shipping the PNG in a os-dependent way. Contra: requires a tool like xd and reserves ram for the compressed images.

Frédéric

unread,
Jun 1, 2018, 2:36:18 PM6/1/18
to wx-u...@googlegroups.com
> Under Unix you can use either approach, ... you can embed the files into
> the program itself. In the latter case, you will find misc/scripts/png2c.py
> useful -- and if you do it like this, wxBITMAP_PNG() will also work for you
> under Unix (otherwise you'd have to use wxBITMAP_PNG_FROM_DATA() there).

So I am right to say that this would also work for MSW and OSX?

Frédéric

unread,
Jun 1, 2018, 2:39:07 PM6/1/18
to wx-u...@googlegroups.com
> Using an utility like xd one could include a .PNG file within the executable
> and then load it from a wxMemoryBuffer. Pro: avoids shipping the PNG in a
> os-dependent way. Contra: requires a tool like xd and reserves ram for the
> compressed images.

do you know if XD (Adobe?) does a similar thing as
misc/scripts/png2c.py, i.e. make an unsigned char[] with png data
inside?

F

Gunter Königsmann

unread,
Jun 1, 2018, 2:53:50 PM6/1/18
to wx-u...@googlegroups.com
The xd I know is a small Linux helper utility. And it seems like it does the same as the python script: Try a file into an array. I still am impressed that wxWidgets contains magic that allow to load PNG files both from files and from memory.

wxMaxima uses the latter method on OS X, MSW and Linux: Linux and MSW expect bitmaps in different directories (eventually with additional heuristics for cygwin), Mac Os even four directories (depending if you use macports, homebrew, fink or if you compile an .app) and when running the application from the build dir finding the source might not be easy (out-of-tree builds etc). Increasing the binary size by 2% by embedding the bitmaps seemed more reasonable than implementing all the heuristics...

Frédéric

unread,
Jun 1, 2018, 3:19:42 PM6/1/18
to wx-u...@googlegroups.com
> wxMaxima uses the latter method on OS X, MSW and Linux: Linux and MSW expect
> bitmaps in different directories (eventually with additional heuristics for
> cygwin), Mac Os even four directories (depending if you use macports,
> homebrew, fink or if you compile an .app) and when running the application
> from the build dir finding the source might not be easy (out-of-tree builds
> etc). Increasing the binary size by 2% by embedding the bitmaps seemed more
> reasonable than implementing all the heuristics...

That's very interesting. Looks very portable of course.

F

Gunter Königsmann

unread,
Jun 1, 2018, 3:56:59 PM6/1/18
to wx-u...@googlegroups.com
Seems like I got the name of the tool wrong (sorry for that).


If anyone wants to try it:

The file from xxd looks like the following:

unsigned char dialog_information_128_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
[...]

It is generated using

xxd -i image.png > image.h


Converting it into an wxImage works the following way:

wxMemoryInputStream
istream(dialog_information_128_png,dialog_information_128_len);
img.LoadFile(istream);

Kind regards,

Gunter.

Frédéric

unread,
Jun 1, 2018, 4:05:10 PM6/1/18
to wx-u...@googlegroups.com
> xxd -i image.png > image.h
> Converting it into an wxImage works the following way:
> wxMemoryInputStream
> istream(dialog_information_128_png,dialog_information_128_len);
> img.LoadFile(istream);

awesome, thanks!

F

Vadim Zeitlin

unread,
Jun 2, 2018, 7:21:50 AM6/2/18
to wx-u...@googlegroups.com
On Fri, 1 Jun 2018 20:07:08 +0200 Frédéric wrote:

F> > Currently things work well automatically only under Mac, where you
F> > just need to provide the normal and normal@2x icons and the right one
F> > will be selected depending on whether high DPI is used or not.
F>
F> So do you mean you have to provide 1 icns file with:
F> 16, 24, 32, 48, 64, 128, 256, 512
F> combined with those sizes x2
F> 32, 48, 64, 96, 128, 256, 512, 1024
F> so all together in one single icns file:
F> 16, 24, 32, 48, 64, 96, 128, 256, 512, 1024?
F>
F> or 2 separate icns files?

This depends on which icon are we speaking about. For the application
icon, you need to have an "iconset", which must be created using the
corresponding utility (iconutil) from the individual icon files, which must
follow the specific naming convention, i.e. they must be in a directory
called foo.iconset and have names foo_NxN.png and foo...@2x.png. ".icns"
files are obsolete, from what I know.

For the icons you use inside your program, you just use PNG files
directly, i.e. you typically don't need them in multiple sizes but just use
wxBITMAP_PNG(my_toolbar_icon) and this will use my_toolbar_icon.png or
my_tool...@2x.png (if it exists) depending on the DPI.


On Fri, 1 Jun 2018 20:35:45 +0200 Frédéric wrote:

F> > Under Unix you can use either approach, ... you can embed the files into
F> > the program itself. In the latter case, you will find misc/scripts/png2c.py
F> > useful -- and if you do it like this, wxBITMAP_PNG() will also work for you
F> > under Unix (otherwise you'd have to use wxBITMAP_PNG_FROM_DATA() there).
F>
F> So I am right to say that this would also work for MSW and OSX?

wxBITMAP_PNG_FROM_DATA(foo) relies on having the array named "foo_png"
with PNG data, so it always works if you embed the PNG icons in the program
itself.

Gunter Königsmann

unread,
Jun 5, 2018, 1:20:01 PM6/5/18
to wx-users
I've tried to add the info about xxd -i to the wxWidgets wiki. But it seems to interpret everything I can write as spam ;-( ...if anyone else can do it: Please add the info there.

Vadim Zeitlin

unread,
Jun 10, 2018, 8:50:59 AM6/10/18
to wx-u...@googlegroups.com
On Tue, 5 Jun 2018 10:20:00 -0700 (PDT) Gunter Königsmann wrote:

GK> I've tried to add the info about xxd -i to the wxWidgets wiki. But it
GK> seems to interpret everything I can write as spam ;-( ...if anyone else
GK> can do it: Please add the info there.

Hello,

I don't know what's going on with the wiki, sorry. What is your account
there?

As for xxd, I'm not sure if there is really any advantage in using it
compared to png2c.py. And the latter has a convenient "-s" option that the
former lacks.

Umberto Carletti

unread,
Jun 12, 2018, 10:26:54 AM6/12/18
to wx-users
Thanks every one for the answers! I ended up embending the icons in the program using the script. I found it easier and now it works pretty fine.
Now I have one question left: I'm not able to make the toolbar as small as I want.
The toolbar size doesn't adapt to the size of the bitmap when it is very small.
I tried to use SetToolBitmapSize() with no effect, it seems that for small bitmaps (like 8px x 8px) the toolbar size doens't scale down less than 24px.
Is there a minimum size for the toolbar? Can i change it at my convenience?
Kind regards
Umberto

Vadim Zeitlin

unread,
Jun 16, 2018, 2:57:26 PM6/16/18
to wx-u...@googlegroups.com
On Tue, 12 Jun 2018 07:26:54 -0700 (PDT) Umberto Carletti wrote:

UC> Now I have one question left: I'm not able to make the toolbar as small as
UC> I want.
UC> The toolbar size doesn't adapt to the size of the bitmap when it is very
UC> small.
UC> I tried to use SetToolBitmapSize() with no effect, it seems that for small
UC> bitmaps (like 8px x 8px) the toolbar size doens't scale down less than 24px.
UC> Is there a minimum size for the toolbar? Can i change it at my convenience?

I am not aware of a minimal toolbar size, but if this is what happens, it
seems likely that this is indeed the case. Which platform does it happen
under?

Also, I have to say that I'm really curious why do you think using 8x8
bitmaps is a good idea. 16x16 is really the smallest acceptable size IMHO
but 24x24 or even 32x32 seem to be much more common in any relatively
recent UIs.

Umberto Carletti

unread,
Jun 19, 2018, 10:09:44 AM6/19/18
to wx-u...@googlegroups.com
> I am not aware of a minimal toolbar size, but if this is what happens, it
> seems likely that this is indeed the case. Which platform does it happen
> under?

I'm working under GTK 3.22.26.

> Also, I have to say that I'm really curious why do you think using 8x8
> bitmaps is a good idea. 16x16 is really the smallest acceptable size IMHO
> but 24x24 or even 32x32 seem to be much more common in any relatively
> recent UIs.

I agree with you. I was making some tests with different toolbar sizes
and I was just wondering if I could make it smaller than that.

Thank you for the answer.
Regards
Umberto
Reply all
Reply to author
Forward
0 new messages