.icns Icon-Dateien via Terminal erstellen

Für ein Skript, welches mir automatisch Partition mit Image-Dateien bespielt, brauchte ich einen Mechanismus, über den ich dynamisch VolumeIcons auf die fertigen Volumes anwenden konnte. Normalerweise würde ich hierfür

  • Im Programm Vorschau ein entsprechendes Bilds (idealerweise 512x512px) öffnen, auswählen und kopieren
  • Das gewünschte Objekt im Finder auswählen und mir die Information anzeigen lassen
  • tab drücken und mit cmd+V das Bild aus der Zwischenablage als Icon festlegen


Nur wie macht man so etwas per Skript und am besten ohne GUI-Skripting via Shell?

Dynamische SVG Grafik erstellen

Nun, die Grafik (in den Icons sollte ein Textbaustein sich immer ändern) habe ich als SVG-Datei gestalltet (svg-edit war dafür ideal). Die nötige Änderung konnte ich dann in der svg-Datei ganz einfach via sed einbauen.
do shell script "sed 's/XXX/" & asdNR & "/g' " & svg_file & ">/tmp/tempasd.svg"
Es wurde also einfach XXX gegen die gewünschte Nummer ersetzt.

Die SVG-Grafik als PNG speichern

Das Konvertieren der SVG-Grafik zu einer Bild-Datei kann auch mit OSX-Bordmitteln erledigt werden, indem man Quicklook etwas zweckentfremdet.
do shell script "qlmanage -t -s 512 -o /tmp/ /tmp/tempasd.svg"
Mit dem Code erstellt man ziemlich unkompliziert eine 512 Pixel große PNG-Version der SVG-Datei unter /tmp/tempasd.svg.png .

Aus dem PNG-Bild nun ein icns-Datei erstellen

Das ist etwas tricky, da es seit 10.7 bzw. den Mac Book Pro Retina Icons mit einer Auflösung von bis zu 1024×1024 Pixel gibt.
Diese Highres-Icons kann man seit 10.7 recht einfach mit dem ab Werk installierten iconutil aus einem .iconset erstellen.
.iconset ist eigentlich nur ein Ordner der die unterschiedlichen icon-Größen als PNG-Datein beinhaltet. Mehr Infos dazu gibt es bei Apple, oder man schnappt sich einfach zum Test eine Highres-icns-Datei z.B. von Text-Edit und lässt sich daraus ein .iconset erstellen.
iconutil --convert iconset /Applications/TextEdit.app/Contents/Resources/rtf.icns --out ~/demo.iconset;open ~/demo.iconset
Und genau so ein Set brauchte ich also mit der SVG-Datei als Ausgangsquelle

##HIGHRES VERSION
set outputfolder to "/tmp/temp_icon.iconset/"
do shell script "qlmanage -t -s 1024 -o " & outputfolder & "  /tmp/tempasd.svg"

##Erstelle daraus ein iConset
do shell script "cd " & outputfolder & ";mv tempasd.svg.png icon_512x512@2x.png"

do shell script "sips -s format png -Z 512 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_512x512.png"
do shell script "sips -s format png -Z 256 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_256x256.png"
do shell script "sips -s format png -Z 128 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_128x128.png"
do shell script "sips -s format png -Z 64 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_32x32@2x.png"
do shell script "sips -s format png -Z 32 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_32x32.png"
do shell script "sips -s format png -Z 16 " & outputfolder & "icon_512x512@2x.png --out " & outputfolder & "icon_16x16.png"

do shell script "cp " & outputfolder & "icon_512x512.png " & outputfolder & "icon_256x256@2x.png"
do shell script "cp " & outputfolder & "icon_256x256.png " & outputfolder & "icon_128x128@2x.png"
do shell script "cp " & outputfolder & "icon_32x32.png " & outputfolder & "icon_16x16@2x.png"

do shell script "iconutil -c icns -o /tmp/asd.icns " & outputfolder
									


Dieser Applescript Code erstellt eine png Datei in der entsprechenden Auflösung und baut sich ein .iconset, mit dem iconutil wiederum ein passendes Highres-Icon erstellen kann.

Das Problem bei Highres-Icons

Und da lag dann auch das Problem. Da ich die Icons brauchte, um beim Start mit gedrückter ALT-Taste (Efi-Boot) die einzelnen Laufwerk zu unterscheiden, wäre alles toll gewesen, wenn das EFI bei nicht-Retina Macs sich nicht weigern würde diese HighRes-Icons darzustellen. iconutil erstellt aber nur HighRes-Icons auch wenn es rein technisch noch möglich ist .icns-Dateien mit nur 512x512px Auflösung zu erstellen.
Nach einiger Suche wurde ich dann aber fündig, via Python kann man unter OSX cocoa Funktionen ausführen und Cocoa bietet Funktionen, um incs-Dateien aus Bildern zu erzeugen. Den Code selbst zu schreiben war nicht mal notwenig, da ein kleines Skript mit den Namen makeicns schon fertig programmiert vorliegt. Das Skript ist Bestandteil von decorator, einem Icon-Tool.
Damit war das Skript auch deutlich schlanker, da das iconset wegfällt:

do shell script "sed 's/XXX/" & asdNR & "/g' " & svg_file & ">/tmp/tempasd.svg"
##convertiere die SVG Datei in ein PNG mit 1024er Auflösung
do shell script "qlmanage -t -s 512 -o /tmp/ /tmp/tempasd.svg"
do shell script makeicnspath & " -in /tmp/tempasd.svg.png"
									

Das Icon auf ein Volumen anwenden

Nun ist das 512px große icon fertig und musste nur noch mit dem Namen .VolumeIcon.icns auf das Zielvolumen kopiert werden… denkste. Natürlich muss noch ein Finder-Flag gesetzt werden, was leider wieder nicht mit Bordmittel funktioniert, sondern ein Tool aus dem Developer Tools benötigt SetFile. Das Tool gibt es seit Xcode 5, läuft also erst ab MacOS 10.7. (Es müsste da eigentlich noch ein anderes Werkzeug geben, um diesen CustomIcon Flag zu setzen, also rein damit in die Kommentare).
So sieht der Code zum anwenden des iCons dann aus:
##copy the icon file
do shell script "cp -f /tmp/tempasd.svg.icns /Volumes/" & quoted form of volume_name & "/.VolumeIcon.icns"
##set the custom icon flag so the icon shows up
do shell script setfilepath & " -a C /Volumes/" & quoted form of volume_name

Die Alternative

Diese Lösung benötigt 2 zusätzliche Programme, um icns zu erstellen und um das CustomIcon Attribut zu setzen. Nur um das zu erledigend, was der Finder durch das Einfügen einer Zwischenablage erledigt. Aus diesem Grund ist die Lösung alles andere als perfekt und dürfte mit einigen Cocoa-Aufrufen via Python auch bestimmt leichter umzusetzen sein. Bis dahin, ist das aber wohl meine Lösung.

Leave a Reply