Convert PNG to ICNS on Mac OS
Developing an application for Mac OS, sooner or later you’ll want to add an icon to it. And Mac OS uses Apple’s own format for application icons - Apple Icon Image format - files with .icns
extension. But how does one create such a file?
It is actually not so hard, but there are some tricky moments. I’ll cover those and as a bonus I’ll show you how to use .icns
icon in Qt-based application (deadly simple).
How to convert PNG to ICNS
There is an out-of-the-box Mac OS tool for such conversion - iconutil (documentation for which is nowhere to find at Apple’s website, so this brief man
page is all we have).
However, you cannot just take a random PNG and feed it to iconutil
. I mean, you can, but it will give you the following error:
$ iconutil -c icns some.png
some.png:Iconset not found.
Because iconutil
takes only specially named folders. Just how am I supposed to know about that? And it shows similar short and useless error messages for other things it doesn’t like. For example, here’s an output for the situation when files inside iconset folder are not named “properly” or have “wrong” dimensions:
$ iconutil -c icns some.iconset
some.iconset:Failed to generate ICNS.
Go figure.
After a set of trials and browsing the internet I found out (hopefully) all the requirements:
- First you need to prepare a set of icon pictures and put those into a folder with
.iconset
“extension”, for examplesome.iconset
; - Pictures from this set should be named in a certain way and have specific dimensions.
Correct dimensions can be found in Apple Guidelines. So it’s 5 different dimensions, but actually 10 “physical” files as each dimension is represented twice (you’ll see why). And these files have to be named according to the following format:
icon_{width}x{height}[@{scale}x].png
So here’s the full list of proper filenames:
$ tree some.iconset/
some.iconset/
├── icon_128x128.png
├── icon_128x128@2x.png
├── icon_16x16.png
├── icon_16x16@2x.png
├── icon_256x256.png
├── icon_256x256@2x.png
├── icon_32x32.png
├── icon_32x32@2x.png
├── icon_512x512.png
└── icon_512x512@2x.png
0 directories, 10 files
Script to automate the process
But that’s rather boring to create all those files manually in some graphics editor, right? So let’s use sips utility (although, I recommend using ImageMagick, as it gives better quality results):
sips -z 16 16 some.png --out icon_16x16.png
Better, but still - we have to run it 10 times. So let’s write a Python script for that:
# a class to store icon parameters: its size and scale factor
class IconParameters():
width = 0
scale = 1
def __init__(self, width, scale):
self.width = width
self.scale = scale
def getIconName(self):
scaleString = "" if self.scale == 1 else f"@{self.scale}x"
return f"icon_{self.width}x{self.width}{scaleString}.png"
# create a list of all the sizes (5 actual sizes, but 10 files)
ListOfIconParameters = [
IconParameters(16, 1),
IconParameters(16, 2),
IconParameters(32, 1),
IconParameters(32, 2),
IconParameters(128, 1),
IconParameters(128, 2),
IconParameters(256, 1),
IconParameters(256, 2),
IconParameters(512, 1),
IconParameters(512, 2)
]
# generate iconset folder by calling sips utility for each item in the list (so it's 10 times)
for ip in ListOfIconParameters:
subprocess.run(
[
"sips",
"-z",
str(ip.width * ip.scale),
str(ip.width * ip.scale),
originalPicture,
"--out",
iconsetDir / ip.getIconName()
],
capture_output=True,
text=True
)
The full script is published here. There is also a PyPI package.
As an example, I prepared a square picture with a resolution of 2048x2048 and 150 pixel per inch, so there is plenty room to prevent upscaling:
Pass picture path to the script like that:
python generate-iconset.py ~/Desktop/apple.png
The script will:
- Create a folder
~/Desktop/apple.iconset
; - Generate 10 files with different dimensions and save those into that folder;
- Call
iconutil
on this folder and put resultingapple.icns
to~/Desktop/
.
Here’s how the final apple.icns
looks like in Preview:
So everything from that folder is bundled into one file.
Setting icon for a Qt-based application on Mac OS
And now the bonus part - how to use .icns
as an icon for a Qt-based application.
As I said, it’s deadly simple: put apple.icns
into your Qt project folder and add the following line into your-project.pro
:
ICON = apple.icns
And that’s it:
Social networks
Zuck: Just ask
Zuck: I have over 4,000 emails, pictures, addresses, SNS
smb: What? How'd you manage that one?
Zuck: People just submitted it.
Zuck: I don't know why.
Zuck: They "trust me"
Zuck: Dumb fucks