1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Use NetPBM .pam as an intermediate format in the icon makefile.

mkicon.py now outputs .pam by hand, rather than using ImageMagick to
go straight to .png. For most purposes the main makefile then uses
ImageMagick anyway, to convert those .pams straight to the .pngs that
the rest of the scripts were expecting. But one script that doesn't do
that is macicon.py, which builds the MacOS .icns file by directly
reading those .pam files back in.

This allows the 'make icns' target in the icons directory to build
from a clean checkout on vanilla MacOS, without requiring a user to
install ImageMagick or any other non-core Python image handling
module.

(I could probably take this change at least a little bit further. I
don't see any reason why icon.pl - generating the Windows .ico files -
couldn't read the .pam files directly, about as easily as macicon.py
did, if anyone had a use case for building the Windows icons in the
presence of Python and Perl but in the absence of ImageMagick. But the
.png files are directly useful outputs for Unix, so _some_ PNG-writing
will have to remain here.)
This commit is contained in:
Simon Tatham 2016-03-23 06:41:27 +00:00
parent eac66b0281
commit 450a995f05
4 changed files with 73 additions and 50 deletions

1
.gitignore vendored
View File

@ -83,6 +83,7 @@
/doc/*.hhk
/doc/licence.but
/doc/copy.but
/icons/*.pam
/icons/*.png
/icons/*.ico
/icons/*.icns

View File

@ -5,9 +5,13 @@ SIZES = 16 32 48 128
MODE = # override to -it on command line for opaque testing
PNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).png))
MONOPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.png))
TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png))
PAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).pam))
MONOPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.pam))
TRUEPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.pam))
PNGS = $(patsubst %.pam,%.png,$(PAMS))
MONOPNGS = $(patsubst %.pam,%.png,$(MONOPAMS))
TRUEPNGS = $(patsubst %.pam,%.png,$(TRUEPAMS))
ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \
puttyins.ico
@ -30,13 +34,16 @@ install: icos cicons
cp $(ICOS) ../windows
cp $(CICONS) ../unix
$(PNGS): %.png: mkicon.py
$(PAMS): %.pam: mkicon.py
./mkicon.py $(MODE) $(join $(subst -, ,$(basename $@)),_icon) $@
$(MONOPNGS): %.png: mkicon.py
$(PNGS) $(MONOPNGS) $(TRUEPNGS): %.png: %.pam
convert $< $@
$(MONOPAMS): %.pam: mkicon.py
./mkicon.py -2 $(MODE) $(join $(subst -, ,$(subst -mono,,$(basename $@))),_icon) $@
$(TRUEPNGS): %.png: mkicon.py
$(TRUEPAMS): %.pam: mkicon.py
./mkicon.py -T $(MODE) $(join $(subst -, ,$(subst -true,,$(basename $@))),_icon) $@
putty.ico: putty-16.png putty-32.png putty-48.png \
@ -90,15 +97,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 \
PuTTY.icns: putty-16-mono.pam putty-16.pam \
putty-32-mono.pam putty-32.pam \
putty-48-mono.pam putty-48.pam \
putty-128.pam
./macicon.py mono:putty-16-mono.pam colour:putty-16.pam \
mono:putty-32-mono.pam colour:putty-32.pam \
mono:putty-48-mono.pam colour:putty-48.pam \
colour:putty-128.pam \
output:$@
clean:
rm -f *.png *.ico *.icns *.c
rm -f *.pam *.png *.ico *.icns *.c

View File

@ -112,18 +112,31 @@ def make_colour_icon(size, rgba):
# 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.
# To avoid adding any build dependency on ImageMagick or Python
# imaging libraries, none of which comes as standard on OS X, I insist
# here that the file is in RGBA .pam format (as mkicon.py will have
# generated it).
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
with open(filename) as f:
assert f.readline() == "P7\n"
for line in iter(f.readline, ''):
words = line.rstrip("\n").split()
if words[0] == "WIDTH":
width = int(words[1])
elif words[0] == "HEIGHT":
height = int(words[1])
elif words[0] == "DEPTH":
assert int(words[1]) == 4
elif words[0] == "TUPLTYPE":
assert words[1] == "RGB_ALPHA"
elif words[0] == "ENDHDR":
break
assert width == height
data = f.read()
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 = ""

View File

@ -893,17 +893,18 @@ def testrun(func, fname):
for canvas in canvases:
minx, miny, maxx, maxy = bbox(canvas)
block.extend(render(canvas, minx-2, miny-2, minx-2+wid, maxy+2))
p = os.popen("convert -depth 8 -size %dx%d rgb:- %s" % (wid,ht,fname), "w")
assert len(block) == ht
for line in block:
assert len(line) == wid
for r, g, b, a in line:
# Composite on to orange.
r = int(round((r * a + 255 * (255-a)) / 255.0))
g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0))
p.write("%c%c%c" % (r,g,b))
p.close()
with open(fname, "w") as f:
f.write(("P7\nWIDTH %d\nHEIGHT %d\nDEPTH 3\nMAXVAL 255\n" +
"TUPLTYPE RGB\nENDHDR\n") % (wid, ht))
assert len(block) == ht
for line in block:
assert len(line) == wid
for r, g, b, a in line:
# Composite on to orange.
r = int(round((r * a + 255 * (255-a)) / 255.0))
g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0))
f.write("%c%c%c" % (r,g,b))
def drawicon(func, width, fname, orangebackground = 0):
canvas = func(width / 32.0)
@ -912,19 +913,20 @@ def drawicon(func, width, fname, orangebackground = 0):
assert minx >= 0 and miny >= 0 and maxx <= width and maxy <= width
block = render(canvas, 0, 0, width, width)
p = os.popen("convert -depth 8 -size %dx%d rgba:- %s" % (width,width,fname), "w")
assert len(block) == width
for line in block:
assert len(line) == width
for r, g, b, a in line:
if orangebackground:
# Composite on to orange.
r = int(round((r * a + 255 * (255-a)) / 255.0))
g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0))
a = 255
p.write("%c%c%c%c" % (r,g,b,a))
p.close()
with open(fname, "w") as f:
f.write(("P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n" +
"TUPLTYPE RGB_ALPHA\nENDHDR\n") % (width, width))
assert len(block) == width
for line in block:
assert len(line) == width
for r, g, b, a in line:
if orangebackground:
# Composite on to orange.
r = int(round((r * a + 255 * (255-a)) / 255.0))
g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0))
a = 255
f.write("%c%c%c%c" % (r,g,b,a))
args = sys.argv[1:]