terom@79: #!/usr/bin/env python terom@79: terom@79: """ terom@79: Python clone of the pngtile binary. terom@79: """ terom@79: terom@88: import optparse, sys terom@79: terom@79: import pypngtile as pt terom@79: terom@79: # CLI options terom@79: options = None terom@79: terom@88: def log (fmt, args) : terom@88: print >>sys.stderr, fmt % args terom@88: terom@79: def log_debug (fmt, *args) : terom@79: if options.debug or options.verbose : terom@88: log(fmt, args) terom@79: terom@79: def log_info (fmt, *args) : terom@79: if not options.quiet : terom@88: log(fmt, args) terom@79: terom@79: def log_warn (fmt, *args) : terom@88: log(fmt, args) terom@79: terom@79: terom@79: def parse_hex (hex) : terom@79: """ terom@79: Parse a 0xHH.. style string as a raw bytestring terom@79: """ terom@79: terom@79: if not hex.startswith("0x") : terom@79: raise ValueError(hex) terom@79: terom@79: return hex[2:].decode("hex") terom@79: terom@79: def parse_args (args) : terom@79: """ terom@79: Parse given argv[1:] terom@79: """ terom@79: terom@79: global options terom@79: terom@79: parser = optparse.OptionParser( terom@79: usage = "Usage: %prog [options] [...]", terom@79: ) terom@79: terom@79: # build opts list terom@79: parser.add_option('-q', "--quiet", help="Supress informational output", action='store_true') terom@79: parser.add_option('-v', "--verbose", help="Display more output", action='store_true') terom@79: parser.add_option('-D', "--debug", help="Equivalent to -v", action='store_true') terom@79: parser.add_option('-U', "--force-update", help="Unconditionally update the image caches", action='store_true') terom@79: parser.add_option('-N', "--no-update", help="Do not update the image caches, even if unusable", action='store_true') terom@79: parser.add_option('-B', "--background", help="Background pattern for sparse cache file", metavar="0xHH..") terom@88: parser.add_option('-W', "--width", help="Output tile width", metavar="PX", type='int', default=800) terom@88: parser.add_option('-H', "--height", help="Output tile height", metavar="PX", type='int', default=600) terom@88: parser.add_option('-x', "--x", help="Tile x offset", metavar="PX", type='int', default=0) terom@88: parser.add_option('-y', "--y", help="Tile y offset", metavar="PX", type='int', default=0) terom@88: parser.add_option('-z', "--zoom", help="Tile zoom level, -n", metavar="ZL", type='int', default=0) terom@88: parser.add_option('-o', "--out", help="Render tile to output file, or -", metavar="FILE") terom@88: terom@79: # parse terom@79: options, args = parser.parse_args(args=args) terom@79: terom@79: # decode terom@79: if options.background : terom@79: try : terom@79: options.background = parse_hex(options.background) terom@79: terom@79: except ValueError : terom@79: raise ValueError("Invalid value for --background: %s" % options.background) terom@79: terom@79: return args terom@79: terom@79: terom@88: def process_tile (image) : terom@88: """ terom@88: Process output tile for given image terom@88: """ terom@88: terom@88: # parse out terom@88: if options.out == '-' : terom@88: log_debug("\tUsing stdout as output...") terom@88: terom@88: # use stdout terom@88: out = sys.stdout terom@88: terom@88: else : terom@88: log_debug("\tOpening file for output: %s", options.out) terom@88: terom@88: # open file terom@88: out = open(options.out, "wb") terom@88: terom@88: log_info("\tRender tile %dx%d@(%d:%d)@%d -> %s...", options.width, options.height, options.x, options.y, options.zoom, options.out) terom@88: terom@88: # render terom@88: image.tile_file(options.width, options.height, options.x, options.y, options.zoom, out) terom@88: terom@88: log_debug("Rendered tile: %s", options.out) terom@88: terom@88: terom@79: def process_image (image) : terom@79: """ terom@79: Process given image terom@79: """ terom@79: terom@79: # check cache status terom@79: status = image.status() terom@79: terom@79: # update if stale? terom@79: if status != pt.CACHE_FRESH or options.force_update : terom@79: # decode status terom@79: if status == pt.CACHE_NONE : terom@79: log_info("\tImage cache is missing") terom@79: terom@79: elif status == pt.CACHE_STALE : terom@79: log_info("\tImage cache is stale") terom@79: terom@79: elif status == pt.CACHE_INCOMPAT : terom@79: log_info("\tImage cache is incompatible") terom@79: terom@79: elif status == pt.CACHE_FRESH : terom@79: log_info("\tImage cache is fresh") terom@79: terom@79: else : terom@79: log_warn("\tImage cache status unknown: %d", status) terom@79: terom@79: terom@79: # update unless supressed terom@79: if not options.no_update : terom@79: log_info("\tUpdating image cache...") terom@79: terom@79: # update with optional background color terom@79: image.update(background_color=options.background) terom@79: terom@79: log_debug("\tUpdated image cache") terom@79: terom@79: else : terom@79: # warn terom@79: log_warn("\tSupressing cache update even though it is needed") terom@79: terom@79: else: terom@79: log_debug("\tImage cache is fresh") terom@79: terom@88: # open it terom@88: image.open() terom@88: terom@79: # show info terom@79: info = image.info() terom@79: terom@79: log_info("\tImage dimensions: %d x %d (%d bpp)", info['img_width'], info['img_height'], info['img_bpp']) terom@79: log_info("\tImage mtime=%d, bytes=%d", info['image_mtime'], info['image_bytes']) terom@79: log_info("\tCache mtime=%d, bytes=%d, blocks=%d (%d bytes), version=%d", terom@79: info['cache_mtime'], info['cache_bytes'], info['cache_blocks'], info['cache_blocks'] * 512, info['cache_version'] terom@79: ) terom@88: terom@79: terom@88: # render tile? terom@88: if options.out : terom@88: log_debug("\tRendering output tile") terom@88: terom@88: process_tile(image) terom@88: terom@88: else : terom@88: log_debug("\tNot rendering output tile") terom@79: terom@79: def process_images (image_paths) : terom@79: """ terom@79: Open up each image_path and process using process_image terom@79: """ terom@79: terom@79: for image_path in image_paths : terom@79: log_debug("Loading image: %s", image_path) terom@79: terom@79: # open up terom@79: image = pt.Image(image_path, pt.OPEN_UPDATE) terom@79: terom@79: log_info("Opened image: %s", image_path); terom@79: terom@79: # process terom@79: process_image(image) terom@79: terom@79: terom@79: def main (args) : terom@79: """ terom@79: Operate on given argv[1:] terom@79: """ terom@79: terom@79: # parse opts/args terom@79: args = parse_args(args) terom@79: terom@79: # handle each image terom@79: process_images(args) terom@79: terom@79: terom@79: if __name__ == '__main__' : terom@79: from sys import argv terom@79: terom@79: main(argv[1:]) terom@79: