Skip to content

Instantly share code, notes, and snippets.

@f0k
Created May 3, 2015 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f0k/57198de3cc2e9e2eebd6 to your computer and use it in GitHub Desktop.
Save f0k/57198de3cc2e9e2eebd6 to your computer and use it in GitHub Desktop.
Strip resolution information (pHYs chunk) from PNG file
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Strips the pHYs chunk (resolution information) of a .png file.
Handy if pdflatex fails with "dimension too large" due to the
PNG resolution being set to 1.
For usage information, call without any parameters.
Author: Jan Schlüter
"""
import sys
import os
import struct
KEEP_TIMESTAMP = True # whether to keep the timestamp on in-place operation
def print_usage():
print 'png_strip_pHYs.py: Removes the pHYs chunk of a .png file if present.'
print 'Usage: %s INFILE [OUTFILE]' % sys.argv[0]
print ' INFILE: .png file to read'
print ' OUTFILE: .png file to write. Defaults to INFILE if omitted.'
def read_png_chunk(f):
"""
Yields all chunks from a PNG file. Make sure to have read the magic number
(first 8 bytes of the file) first.
See http://www.w3.org/TR/PNG/#5PNG-file-signature for documentation.
@return: A tuple of byte strings of a chunk: (length, type, data, crc).
"""
while True:
chunklen = f.read(4)
if len(chunklen) != 4:
break
chunktype = f.read(4)
chunkdata = f.read(struct.unpack('>L', chunklen)[0])
chunkcrc = f.read(4)
yield chunklen, chunktype, chunkdata, chunkcrc
def main():
if len(sys.argv) not in (2,3):
print_usage()
return
# 'parse' command line
infile = sys.argv[1]
if len(sys.argv) > 2:
outfile = sys.argv[2]
else:
outfile = infile
if KEEP_TIMESTAMP:
fileinfo = os.stat(infile)
# read input file
buff = []
with open(infile, 'rb') as f:
# read magic number
magic = f.read(8)
if magic != '\x89PNG\r\n\x1a\n':
print "This is not a valid .png file. Aborting."
return
buff.append(magic)
# read input chunks
for clen, ctype, cdata, ccrc in read_png_chunk(f):
if ctype != 'pHYs':
buff.extend([clen, ctype, cdata, ccrc])
# write output file
with open(outfile, 'wb') as f:
f.writelines(buff)
# keep timestamp if needed
if KEEP_TIMESTAMP and infile == outfile:
os.utime(outfile, (fileinfo.st_atime, fileinfo.st_mtime))
if __name__=="__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment