added a command line interface
This commit is contained in:
5
chunk.py
5
chunk.py
@@ -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
66
render.py
Normal 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()
|
||||
17
world.py
17
world.py
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user