0

added a command line interface

This commit is contained in:
Andrew Brown
2010-08-27 23:44:29 -04:00
parent 08a86a52ab
commit 8817689276
3 changed files with 81 additions and 7 deletions

View File

@@ -71,6 +71,11 @@ class ChunkRenderer(object):
"""Finds a hash of the block array"""
h = hashlib.md5()
h.update(self.level['Blocks'])
# If the render algorithm changes, change this line to re-generate all
# the chunks automatically:
#h.update("1")
digest = h.hexdigest()
# 6 digits ought to be plenty
return digest[:6]

66
render.py Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/python
import os
import sys
import os.path
from optparse import OptionParser
import re
import world
helptext = """
%prog [-c] <Path to World> <image out.png>
%prog -d [-c] <Path to World>"""
def remove_images(worlddir, cavemode):
if cavemode:
cavestr = "cave"
else:
cavestr = "nocave"
imgre = r"img\.[^.]+\.[^.]+\.{0}\.\w+\.png$".format(cavestr)
matcher = re.compile(imgre)
for dirpath, dirnames, filenames in os.walk(worlddir):
for f in filenames:
if matcher.match(f):
filepath = os.path.join(dirpath, f)
print "Deleting {0}".format(filepath)
os.unlink(filepath)
def confirm(imgfile):
answer = raw_input("Overwrite existing image at %r? [Y/n]" % imgfile).strip()
if not answer or answer.lower().startswith("y"):
return True
return False
def main():
parser = OptionParser(usage=helptext)
parser.add_option("-c", "--caves", dest="caves", help="Render only caves", action="store_true")
parser.add_option("-d", "--delete-cache", dest="delete", help="Deletes the image files cached in your world directory", action="store_true")
parser.add_option("-p", "--processes", dest="procs", help="How many chunks to render in parallel. A good number for this is 1 more than the number of cores in your computer. Default 2", default=2, action="store", type="int")
options, args = parser.parse_args()
if len(args) < 1:
print "You need to give me your world directory"
parser.print_help()
sys.exit(1)
worlddir = args[0]
if options.delete:
remove_images(worlddir, options.caves)
else:
if len(args) != 2:
parser.error("What do you want to save the image as?")
imageout = args[1]
if not imageout.endswith(".png"):
imageout = imageout + ".png"
if os.path.exists(imageout) and not confirm(imageout):
return
imageobj = world.render_world(worlddir, options.caves, options.procs)
print "Saving image..."
imageobj.save(imageout)
print "Saved as", imageout
if __name__ == "__main__":
main()

View File

@@ -38,12 +38,13 @@ def find_chunkfiles(worlddir):
for dirpath, dirnames, filenames in os.walk(worlddir):
if not dirnames and filenames:
for f in filenames:
p = f.split(".")
all_chunks.append((base36decode(p[1]), base36decode(p[2]),
os.path.join(dirpath, f)))
if f.startswith("c.") and f.endswith(".dat"):
p = f.split(".")
all_chunks.append((base36decode(p[1]), base36decode(p[2]),
os.path.join(dirpath, f)))
return all_chunks
def render_world(worlddir, cavemode=False):
def render_world(worlddir, cavemode=False, procs=2):
print "Scanning chunks..."
all_chunks = find_chunkfiles(worlddir)
@@ -101,6 +102,8 @@ def render_world(worlddir, cavemode=False):
print "Final image will be {0}x{1}. (That's {2} bytes!)".format(
width, height, width*height*4)
print "Don't worry though, that's just the memory requirements"
print "The final png will be much smaller"
# Oh god create a giant ass image
worldimg = Image.new("RGBA", (width, height))
@@ -110,8 +113,8 @@ def render_world(worlddir, cavemode=False):
print "Sorting chunks..."
all_chunks.sort(key=lambda x: x[1]-x[0])
print "Starting chunk processors..."
pool = multiprocessing.Pool(processes=3)
print "Starting up {0} chunk processors...".format(procs)
pool = multiprocessing.Pool(processes=procs)
resultsmap = {}
for chunkx, chunky, chunkfile in all_chunks:
result = pool.apply_async(chunk.render_and_save, args=(chunkfile,),
@@ -143,7 +146,7 @@ def render_world(worlddir, cavemode=False):
# Draw the image sans alpha layer, using the alpha layer as a mask. (We
# don't want the alpha layer actually drawn on the image, this pastes
# it as if it was a layer)
worldimg.paste(chunkimg.convert("RGB"), (imgx, imgy), chunkimg.split()[3])
worldimg.paste(chunkimg.convert("RGB"), (imgx, imgy), chunkimg)
processed += 1