Use rsvg-convert instead of GIMP for converting SVG to PNG.
[pspp] / build-aux / png-add-comment
1 #! /usr/bin/python3
2
3 import codecs
4 import os
5 import struct
6 import sys
7 import zlib
8
9 if len(sys.argv) != 3 or '--help' in sys.argv:
10     sys.stdout.write("""\
11 %s: adds a comment to a PNG file
12 usage: png-add-comment KEYWORD TEXT < INPUT.PNG > OUTPUT.PNG
13 where KEYWORD is the comment type, e.g. "Comment" or "Copyright"
14   and TEXT is the comment's content (encoded in Latin-1).
15 """ % sys.argv[0])
16     sys.exit(0)
17
18 if os.isatty(1):
19     sys.stderr.write("%s: not writing binary data to a terminal "
20                      "(use --help for help)\n")
21     sys.exit(1)
22
23 infile = sys.stdin.buffer
24 outfile = sys.stdout.buffer
25
26 encoded_keyword = codecs.encode(sys.argv[1], "ASCII")
27 if len(encoded_keyword) > 79:
28     sys.stderr.write("%s: keyword must be 79 bytes or less\n" % sys.argv[0])
29
30 encoded_comment = codecs.encode(sys.argv[2], "Latin-1")
31 comment_data = encoded_keyword + bytes([0]) + encoded_comment
32 comment_crc = zlib.crc32(b'tEXt' + comment_data, 0)
33 comment_chunk = struct.pack('!L', len(comment_data)) + b'tEXt' + comment_data + struct.pack('!L', comment_crc)
34
35 def read_fully(stream, n):
36     data = stream.read(n)
37     if len(data) != n:
38         sys.stderr.write("%s: unexpected end of input\n" % sys.argv[0])
39         sys.exit(1)
40     return data
41
42 # Copy signature and verify that we're working with a PNG file.
43 signature = read_fully(infile, 8)
44 if signature != bytes([137, 80, 78, 71, 13, 10, 26, 10]):
45     sys.stderr.write("%s: input is not a PNG file\n" % sys.argv[0])
46     sys.exit(1)
47 outfile.write(signature)
48
49 comment_written = False
50 while True:
51     header = read_fully(infile, 8)
52     chunk_len, chunk_type = struct.unpack('!L 4s', header)
53     chunk_data = read_fully(infile, chunk_len)
54     chunk_crc = read_fully(infile, 4)
55
56     if (chunk_type in (b'iCCP', b'sRGB', b'sBIT', b'gAMA', b'cHRM',
57                        b'PLTE', b'tRNS', b'hIST', b'bKGD', b'IDAT',
58                        b'IEND')) and not comment_written:
59         outfile.write(comment_chunk)
60         comment_written = True
61
62     outfile.write(header)
63     outfile.write(chunk_data)
64     outfile.write(chunk_crc)
65     crc = struct.unpack('!L', chunk_crc)[0]
66     expected_crc = zlib.crc32(header[4:8] + chunk_data, 0)
67     if crc != expected_crc:
68         sys.stderr.write("%s: bad crc reading PNG chunk\n"
69                          % sys.argv[0])
70     if chunk_type == b'IEND':
71         break
72 assert comment_written