From b08895f02cc34f2a3f5e1281f929fe33a0dff657 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 6 Sep 2015 09:50:09 +0100 Subject: [PATCH] New script to generate OS X icon files. The Xcode icon composer doesn't seem to exist any more in modern versions of Xcode, or at least if it does then it's well hidden and certainly doesn't live at the top-level path at /Developer where web pages still claim it can be found. There is a free software 'libicns' and associated command-line tools, but they're large, complicated, picky about the exact format of PNGs they get as input, and in any case a needless extra build dependency when it turns out the important parts of the file format can be done in a few dozen lines of Python. So here's a new macicon.py, and icons/Makefile additions to build a demo icon for OS X PuTTY, as and when I finally get it working. Also I've deleted the static icon file in the neglected 'macosx' source directory, because this one is better anyway - the old one was appalling quality, and must have been autogenerated from a single image in some way. --- .gitignore | 1 + icons/Makefile | 18 +++++- icons/macicon.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++ macosx/putty.icns | Bin 44796 -> 0 bytes mksrcarc.sh | 2 +- 5 files changed, 167 insertions(+), 4 deletions(-) create mode 100755 icons/macicon.py delete mode 100644 macosx/putty.icns diff --git a/.gitignore b/.gitignore index bea01d86..48dceab4 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,7 @@ /doc/*.hhk /icons/*.png /icons/*.ico +/icons/*.icns /icons/*.xpm /icons/*.c /macosx/Makefile diff --git a/icons/Makefile b/icons/Makefile index 1074303e..5e845b27 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -1,7 +1,7 @@ # Makefile for the PuTTY icon suite. ICONS = putty puttycfg puttygen pscp pageant pterm ptermcfg puttyins -SIZES = 16 32 48 +SIZES = 16 32 48 128 MODE = # override to -it on command line for opaque testing @@ -11,17 +11,19 @@ TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png)) ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \ puttyins.ico +ICNS = PuTTY.icns CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c base: icos cicons -all: pngs monopngs base # truepngs currently disabled by default +all: pngs monopngs base icns # truepngs currently disabled by default pngs: $(PNGS) monopngs: $(MONOPNGS) truepngs: $(TRUEPNGS) icos: $(ICOS) +icns: $(ICNS) cicons: $(CICONS) install: icos cicons @@ -88,5 +90,15 @@ xpmpterm.c: pterm-16.png pterm-32.png pterm-48.png xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png ./cicon.pl cfg_icon $^ > $@ +PuTTY.icns: putty-16-mono.png putty-16.png \ + putty-32-mono.png putty-32.png \ + putty-48-mono.png putty-48.png \ + putty-128.png + ./macicon.py mono:putty-16-mono.png colour:putty-16.png \ + mono:putty-32-mono.png colour:putty-32.png \ + mono:putty-48-mono.png colour:putty-48.png \ + colour:putty-128.png \ + output:$@ + clean: - rm -f *.png *.ico *.c + rm -f *.png *.ico *.icns *.c diff --git a/icons/macicon.py b/icons/macicon.py new file mode 100755 index 00000000..9dfc87ff --- /dev/null +++ b/icons/macicon.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python + +# Generate Mac OS X .icns files, or at least the simple subformats +# that don't involve JPEG encoding and the like. +# +# Sources: https://en.wikipedia.org/wiki/Apple_Icon_Image_format and +# some details implicitly documented by the source code of 'libicns'. + +import sys +import struct +import subprocess + +# The file format has a typical IFF-style (type, length, data) chunk +# structure, with one outer chunk containing subchunks for various +# different icon sizes and formats. +def make_chunk(chunkid, data): + assert len(chunkid) == 4 + return chunkid + struct.pack(">I", len(data) + 8) + data + +# Monochrome icons: a single chunk containing a 1 bpp image followed +# by a 1 bpp transparency mask. Both uncompressed, unless you count +# packing the bits into bytes. +def make_mono_icon(size, rgba): + assert len(rgba) == size * size + + # We assume our input image was monochrome, so that the R,G,B + # channels are all the same; we want the image and then the mask, + # so we take the R channel followed by the alpha channel. However, + # we have to flip the former, because in the output format the + # image has 0=white and 1=black, while the mask has 0=transparent + # and 1=opaque. + pixels = [rgba[index][chan] ^ flip for (chan, flip) in [(0,0xFF),(3,0)] + for index in range(len(rgba))] + + # Encode in 1-bit big-endian format. + data = "" + for i in range(0, len(pixels), 8): + byte = 0 + for j in range(8): + if pixels[i+j] >= 0x80: + byte |= 0x80 >> j + data += chr(byte) + + # This size-32 chunk id is an anomaly in what would otherwise be a + # consistent system of using {s,l,h,t} for {16,32,48,128}-pixel + # icon sizes. + chunkid = { 16: "ics#", 32: "ICN#", 48: "ich#" }[size] + return make_chunk(chunkid, data) + +# Mask for full-colour icons: a chunk containing an 8 bpp alpha +# bitmap, uncompressed. The RGB data appears in a separate chunk. +def make_colour_mask(size, rgba): + assert len(rgba) == size * size + + data = "".join(map(lambda pix: chr(pix[3]), rgba)) + + chunkid = { 16: "s8mk", 32: "l8mk", 48: "h8mk", 128: "t8mk" }[size] + return make_chunk(chunkid, data) + +# Helper routine for deciding when to start and stop run-length +# encoding. +def runof3(string, position): + return (position < len(string) and + string[position:position+3] == string[position] * 3) + +# RGB data for full-colour icons: a chunk containing 8 bpp red, green +# and blue images, each run-length encoded (see comment inside the +# function), and then concatenated. +def make_colour_icon(size, rgba): + assert len(rgba) == size * size + + data = "" + + # Mysterious extra zero header word appearing only in the size-128 + # icon chunk. libicns doesn't know what it's for, and neither do + # I. + if size == 128: + data += "\0\0\0\0" + + # Handle R,G,B channels in sequence. (Ignore the alpha channel; it + # goes into the separate mask chunk constructed above.) + for chan in range(3): + pixels = "".join([chr(rgba[index][chan]) + for index in range(len(rgba))]) + + # Run-length encode each channel using the following format: + # * byte 0x80-0xFF followed by one literal byte means repeat + # that byte 3-130 times + # * byte 0x00-0x7F followed by n+1 literal bytes means emit + # those bytes once each. + pos = 0 + while pos < len(pixels): + start = pos + if runof3(pixels, start): + pos += 3 + pixval = pixels[start] + while (pos - start < 130 and + pos < len(pixels) and + pixels[pos] == pixval): + pos += 1 + data += chr(0x80 + pos-start - 3) + pixval + else: + while (pos - start < 128 and + pos < len(pixels) and + not runof3(pixels, pos)): + pos += 1 + data += chr(0x00 + pos-start - 1) + pixels[start:pos] + + chunkid = { 16: "is32", 32: "il32", 48: "ih32", 128: "it32" }[size] + return make_chunk(chunkid, data) + +# Load an image file from disk and turn it into a simple list of +# 4-tuples giving 8-bit R,G,B,A values for each pixel. +# +# My icon-building makefile already depends on ImageMagick, so I use +# identify and convert here in place of more sensible Python libraries +# so as to add no build dependency that wasn't already needed. +def load_rgba(filename): + size = subprocess.check_output(["identify", "-format", "%wx%h", filename]) + width, height = map(int, size.split("x")) + assert width == height + data = subprocess.check_output(["convert", "-depth", "8", + filename, "rgba:-"]) + assert len(data) == width*height*4 + rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)] + return width, rgba + +data = "" + +# Trivial argument format: each argument is a filename prefixed with +# "mono:", "colour:" or "output:". The first two indicate image files +# to use as part of the icon, and the last gives the output file name. +# Icon subformat chunks are written out in the order of the arguments. +for arg in sys.argv[1:]: + kind, filename = arg.split(":", 2) + if kind == "output": + outfile = filename + else: + size, rgba = load_rgba(filename) + if kind == "mono": + data += make_mono_icon(size, rgba) + elif kind == "colour": + data += make_colour_icon(size, rgba) + make_colour_mask(size, rgba) + else: + assert False, "bad argument '%s'" % arg + +data = make_chunk("icns", data) + +with open(outfile, "w") as f: + f.write(data) diff --git a/macosx/putty.icns b/macosx/putty.icns deleted file mode 100644 index 72eab295e018508b0bc932860e84e66c624ea8cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44796 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 diff --git a/mksrcarc.sh b/mksrcarc.sh index 87327df7..a8b01b5b 100755 --- a/mksrcarc.sh +++ b/mksrcarc.sh @@ -20,7 +20,7 @@ text=`{ find . -name CVS -prune -o \ # files. bintext=testdata/*.txt # These are actual binary files which we don't want transforming. -bin=`{ ls -1 windows/*.ico windows/putty.iss windows/website.url macosx/*.icns; \ +bin=`{ ls -1 windows/*.ico windows/putty.iss windows/website.url; \ find . -name '*.dsp' -print -o -name '*.dsw' -print; }` verbosely() { -- 2.45.2