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"""
|
"""Finds a hash of the block array"""
|
||||||
h = hashlib.md5()
|
h = hashlib.md5()
|
||||||
h.update(self.level['Blocks'])
|
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()
|
digest = h.hexdigest()
|
||||||
# 6 digits ought to be plenty
|
# 6 digits ought to be plenty
|
||||||
return digest[:6]
|
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()
|
||||||
11
world.py
11
world.py
@@ -38,12 +38,13 @@ def find_chunkfiles(worlddir):
|
|||||||
for dirpath, dirnames, filenames in os.walk(worlddir):
|
for dirpath, dirnames, filenames in os.walk(worlddir):
|
||||||
if not dirnames and filenames:
|
if not dirnames and filenames:
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
|
if f.startswith("c.") and f.endswith(".dat"):
|
||||||
p = f.split(".")
|
p = f.split(".")
|
||||||
all_chunks.append((base36decode(p[1]), base36decode(p[2]),
|
all_chunks.append((base36decode(p[1]), base36decode(p[2]),
|
||||||
os.path.join(dirpath, f)))
|
os.path.join(dirpath, f)))
|
||||||
return all_chunks
|
return all_chunks
|
||||||
|
|
||||||
def render_world(worlddir, cavemode=False):
|
def render_world(worlddir, cavemode=False, procs=2):
|
||||||
print "Scanning chunks..."
|
print "Scanning chunks..."
|
||||||
all_chunks = find_chunkfiles(worlddir)
|
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(
|
print "Final image will be {0}x{1}. (That's {2} bytes!)".format(
|
||||||
width, height, width*height*4)
|
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
|
# Oh god create a giant ass image
|
||||||
worldimg = Image.new("RGBA", (width, height))
|
worldimg = Image.new("RGBA", (width, height))
|
||||||
@@ -110,8 +113,8 @@ def render_world(worlddir, cavemode=False):
|
|||||||
print "Sorting chunks..."
|
print "Sorting chunks..."
|
||||||
all_chunks.sort(key=lambda x: x[1]-x[0])
|
all_chunks.sort(key=lambda x: x[1]-x[0])
|
||||||
|
|
||||||
print "Starting chunk processors..."
|
print "Starting up {0} chunk processors...".format(procs)
|
||||||
pool = multiprocessing.Pool(processes=3)
|
pool = multiprocessing.Pool(processes=procs)
|
||||||
resultsmap = {}
|
resultsmap = {}
|
||||||
for chunkx, chunky, chunkfile in all_chunks:
|
for chunkx, chunky, chunkfile in all_chunks:
|
||||||
result = pool.apply_async(chunk.render_and_save, args=(chunkfile,),
|
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
|
# 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
|
# don't want the alpha layer actually drawn on the image, this pastes
|
||||||
# it as if it was a layer)
|
# 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
|
processed += 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user