]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Use NetPBM .pam as an intermediate format in the icon makefile.
authorSimon Tatham <anakin@pobox.com>
Wed, 23 Mar 2016 06:41:27 +0000 (06:41 +0000)
committerSimon Tatham <anakin@pobox.com>
Wed, 23 Mar 2016 06:58:56 +0000 (06:58 +0000)
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.)

.gitignore
icons/Makefile
icons/macicon.py
icons/mkicon.py

index 200dc4c3852b7e533827eb316d65bf87d990a593..05f52c67965324a29ea05298e8cc0992e48463d6 100644 (file)
@@ -83,6 +83,7 @@
 /doc/*.hhk
 /doc/licence.but
 /doc/copy.but
+/icons/*.pam
 /icons/*.png
 /icons/*.ico
 /icons/*.icns
index 5e845b27c88929b434ba81cb23cad7c291259e74..c5d1fde9793ddfa907c7283cb2846f0b3c8c691a 100644 (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
index 9dfc87ffd817f48cf4deaea453dbfc2d04790cab..b7fed6b2c59f4af3bad59b23d1f1a439c5074d55 100755 (executable)
@@ -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 = ""
 
index 3e6d81c9352cfc38842bb5af542f2491d3bf8368..30f41b6a7f6c2587d0d101cfb1991410e6933175 100755 (executable)
@@ -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:]