From: Eric Branlund Date: Wed, 20 Jan 2021 02:42:17 +0000 (-0800) Subject: Copy over the bmp to png conversion script from sil-q (lib/xtra/graf/osx_bmp2png... X-Git-Tag: vmacos1.6.2-b~4 X-Git-Url: http://git.osdn.net/view?p=hengbandforosx%2Fhengbandosx.git;a=commitdiff_plain;h=1994cd1521d698c283559115b5093dc8e2720251 Copy over the bmp to png conversion script from sil-q (lib/xtra/graf/osx_bmp2png.py as of 2020/8/24) so can adapt it to convert Hengband's versions of the tiles rather than reusing Angband 4's versions. --- diff --git a/lib/xtra/graf/osx_bmp2png.py b/lib/xtra/graf/osx_bmp2png.py new file mode 100644 index 000000000..49517b166 --- /dev/null +++ b/lib/xtra/graf/osx_bmp2png.py @@ -0,0 +1,130 @@ +""" +Converts a tile set from bmp to png for use with the Mac OS X frontend. + +Usage + python osx_bmp2png.py input_file output_file [options] + +Options +--tcoord hcoord vcoord + Reads the color to be treated as transparent for non-terrain tiles + from the position (hcoord, vcoord) in the tile set. Both coordinates + are non-negative integers indexed from zero. Is overridden by + --transparent if that option is set. When not set, the default is to + read the color to be treated as transparent from (0,0). + +--terrain lx1 ly1 ux1 uy1 ... + Sets bounding boxes for parts of the tile set that are to be treated + as completely opaque (i.e. as background terrain). Each bound box is + given by the coordinates for the lower corner, (lx,ly), and upper + corner, (ux,uy), with ux > lx and uy > ly. If not set, the default + is to use two bounding boxes, (0,0) to (496,16) and (192,192) to + (224,208), which are the terrain tiles in Michrochasm's tile set. + +--transparent red green blue + Sets the color, as RGB values between 0 and 255, which will be treated + as completely transparent for non-terrain tiles. If not set, uses + --tcoord or its default to get the color. + +Example +This is the conversion that was used to ready Microchasm's tile set for +the OS X front end: + python osx_bmp2png.py 16x16.bmp 16x16_microchasm.png +That is equivalent to + python osx_bmp2png.py 16x16.bmp 16x16_microchasm.png --tcoord 0 0 \ + --terrain 0 0 496 16 192 192 224 208 + +Requirements +argparse, PIL (Python imaging library) or equivalent, and +numpy (1.7 or later) + +For Michrochasm's tile set the conversion is required because +CGImageSourceCreateWithURL() does not handle the bmp format and because +there appears to be no NSCompositingOperation which is equivalent to +'composite this image with the background treating x as transparent'. +""" + +import argparse +import PIL.Image +import numpy + +aparser = argparse.ArgumentParser(description='Converts bmp tile set to png.') +aparser.add_argument('input_file', type=str, + help='the path to the input tile set') +aparser.add_argument('output_file', type=str, + help='the path to the converted tile set') +aparser.add_argument('--tcoord', type=int, nargs=2, default=(0,0), + help='Position to be read for transparent color') +aparser.add_argument('--terrain', type=int, nargs='+', + default=(0,0,496,16,192,192,224,208), + help='Bounding box coordinates for terrain tiles') +aparser.add_argument('--transparent', type=int, nargs=3, + help='RGB value to be treated as transparent') + +args = aparser.parse_args() + +tin = PIL.Image.open(args.input_file) + +if len(args.terrain) % 4 != 0: + raise IndexError('Need four values for each bounding box.') +for i in range(0, len(args.terrain), 4): + if (args.terrain[i] > args.terrain[i + 2] or + args.terrain[i + 1] > args.terrain[i + 3]): + raise RuntimeError('Lower bounding box coordinate exceeds the upper one') + if (args.terrain[i] < 0 or args.terrain[i + 2] > tin.width or + args.terrain[i + 1] < 0 or + args.terrain[i + 3] > tin.height): + raise IndexError('Bounding box outside of image bounds') + +palette = tin.getpalette() + +if args.transparent: + trind = None + trarr = numpy.array(args.transparent) +else: + if (args.tcoord[0] < 0 or args.tcoord[0] >= tin.width or + args.tcoord[1] < 0 or args.tcoord[1] >= tin.height): + raise IndexError('Coordinates for transparent pixel are out of bounds') + if palette: + trind = tin.getpixel(tuple(args.tcoord)) + else: + trarr = numpy.array(tin.getpixel(args.tcoord)[0:3]) + +# Set up the mask for the portions of the tile set not containing terrain. +arrt = numpy.ones((tin.height, tin.width), dtype=numpy.dtype(bool)) +ind0, ind1 = numpy.meshgrid(numpy.linspace(0, tin.height - 1, tin.height), + numpy.linspace(0, tin.width - 1, tin.width), indexing='ij') +for i in range(0, len(args.terrain), 4): + arrt = numpy.logical_and(arrt, numpy.logical_or(numpy.logical_or( + ind1 < args.terrain[i], ind0 < args.terrain[i + 1]), + numpy.logical_or(ind1 >= args.terrain[i + 2], + ind0 >= args.terrain[i + 3]))) +del ind0, ind1 + +arrin = numpy.array(tin) +arrout = numpy.empty((tin.height,tin.width,4), dtype='u1') +if palette: + parr = numpy.reshape(numpy.array(palette), (len(palette) // 3, 3)) + arrout[:,:,0:3] = parr[arrin] + if trind: + arrout[:,:,3] = numpy.where( + numpy.logical_and(arrt, arrin == trind), + numpy.zeros((tin.height, tin.width), dtype='u1'), + 255 * numpy.ones((tin.height, tin.width), dtype='u1')) + else: + arrout[:,:,3] = numpy.where( + numpy.logical_and(arrt, numpy.logical_and( + arrout[:,:,0] == trarr[0], numpy.logical_and( + arrout[:,:,1] == trarr[1], arrout[:,:,2] == trarr[2]))), + numpy.zeros((tin.height, tin.width), dtype='u1'), + 255 * numpy.ones((tin.height, tin.width), dtype='u1')) +else: + arrout[:,:,0:3] = arrin[:,:,0:3] + arrout[:,:,3] = numpy.where( + numpy.logical_and(arrt, numpy.logical_and( + arrin[:,:,0] == trarr[0], numpy.logical_and( + arrin[:,:,1] == trarr[1], arrin[:,:,2] == trarr[2]))), + numpy.zeros((tin.height, tin.width), dtype='u1'), + 255 * numpy.ones((tin.height, tin.width), dtype='u1')) + +tout = PIL.Image.fromarray(arrout) +tout.save(args.output_file)