0

Merge remote-tracking branch 'origin/rewrite' into rewrite

This commit is contained in:
Andrew Chin
2012-02-11 00:33:49 -05:00
14 changed files with 228 additions and 398 deletions

View File

@@ -9,6 +9,9 @@ Documentation:
Github code repository: Github code repository:
http://github.com/overviewer/Minecraft-Overviewer http://github.com/overviewer/Minecraft-Overviewer
Blog:
http://mcoverviewer.blogspot.com/
The Minecraft Overviewer is a command-line tool for rendering high-resolution The Minecraft Overviewer is a command-line tool for rendering high-resolution
maps of Minecraft worlds. It generates a set of static html and image files and maps of Minecraft worlds. It generates a set of static html and image files and

View File

@@ -233,6 +233,15 @@ These values are set directly in the config file. Example::
This is a string indicating the path to the texture pack to use for This is a string indicating the path to the texture pack to use for
rendering. rendering.
.. _processes:
``processes = num_procs``
This specifies the number of worker processes to spawn on the local machine
to do work. It defaults to the number of CPU cores you have, if not
specified.
This can also be specified with :option:`--processes <-p>`
TODO: More to come here TODO: More to come here
.. _customrendermodes: .. _customrendermodes:

View File

@@ -6,10 +6,12 @@
The Minecraft Overviewer The Minecraft Overviewer
======================== ========================
See also the `Github Homepage`_ See also the `Github Homepage`_ and the `Updates Blog`_
.. _Github Homepage: https://github.com/overviewer/Minecraft-Overviewer .. _Github Homepage: https://github.com/overviewer/Minecraft-Overviewer
.. _Updates Blog: http://mcoverviewer.blogspot.com/
Introduction Introduction
============ ============
The Minecraft Overviewer is a command-line tool for rendering high-resolution The Minecraft Overviewer is a command-line tool for rendering high-resolution

View File

@@ -146,6 +146,14 @@ only have to use once-in-a-while.
or :option:`--check-tiles` is in effect. This option overrides or :option:`--check-tiles` is in effect. This option overrides
:option:`--forcerender` and :option:`--check-tiles`. :option:`--forcerender` and :option:`--check-tiles`.
.. cmdoption:: -p <procs>, --processes <procs>
This specifies the number of worker processes to spawn on the local machine
to do work. It defaults to the number of CPU cores you have, if not
specified.
This option can also be specified in the config file as :ref:`processes <processes>`
.. _installing-textures: .. _installing-textures:
Installing the Textures Installing the Textures

View File

@@ -101,6 +101,8 @@ def main():
# Parse for basic options # Parse for basic options
parser = OptionParser(usage=helptext) parser = OptionParser(usage=helptext)
parser.add_option("--config", dest="config", action="store", help="Specify the config file to use.") parser.add_option("--config", dest="config", action="store", help="Specify the config file to use.")
parser.add_option("-p", "--processes", dest="procs", action="store", type="int",
help="The number of local worker processes to spawn. Defaults to the number of CPU cores your computer has")
# Useful one-time render modifiers: # Useful one-time render modifiers:
parser.add_option("--forcerender", dest="forcerender", action="store_true", parser.add_option("--forcerender", dest="forcerender", action="store_true",
@@ -235,6 +237,12 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
mw_parser = configParser.MultiWorldParser() mw_parser = configParser.MultiWorldParser()
mw_parser.parse(options.config) mw_parser.parse(options.config)
# Add in the command options here, perhaps overriding values specified in
# the config
if options.procs:
mw_parser.set_config_item("processes", options.procs)
# Now parse and return the validated config
try: try:
config = mw_parser.get_validated_config() config = mw_parser.get_validated_config()
except Exception: except Exception:
@@ -332,7 +340,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# multiprocessing dispatcher # multiprocessing dispatcher
dispatch = dispatcher.MultiprocessingDispatcher() dispatch = dispatcher.MultiprocessingDispatcher(local_procs=config['processes'])
def print_status(*args): def print_status(*args):
logging.info("Status callback: %r", args) logging.info("Status callback: %r", args)
dispatch.render_all(tilesets, print_status) dispatch.render_all(tilesets, print_status)

View File

@@ -18,6 +18,8 @@ import os
import codecs import codecs
import locale import locale
import time import time
import logging
from PIL import Image from PIL import Image
import world import world
@@ -46,11 +48,13 @@ directory.
self.POI = dict() self.POI = dict()
# look for overviewerConfig in self.outputdir # look for overviewerConfig in self.outputdir
if os.path.exists(os.path.join(self.outputdir, "overviewerConfig.js")): try:
with open(os.path.join(self.outputdir, "overviewerConfig.js")) as c: with open(os.path.join(self.outputdir, "overviewerConfig.js")) as c:
overviewerConfig_str = "{" + "\n".join(c.readlines()[1:-1]) + "}" overviewerConfig_str = "{" + "\n".join(c.readlines()[1:-1]) + "}"
self.overviewerConfig = json.loads(overviewerConfig_str) self.overviewerConfig = json.loads(overviewerConfig_str)
else: except Exception, e:
if os.path.exists(os.path.join(self.outputdir, "overviewerConfig.js")):
logging.warning("A previous overviewerConfig.js was found, but I couldn't read it for some reason. Continuing with a blank config")
self.overviewerConfig = dict(tilesets=dict()) self.overviewerConfig = dict(tilesets=dict())
def get_tileset_config(self, name): def get_tileset_config(self, name):

View File

@@ -1,38 +0,0 @@
# This file is part of the Minecraft Overviewer.
#
# Minecraft Overviewer is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# Minecraft Overviewer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
import logging
from PIL import Image
"""
This module has an alpha-over function that is used throughout
Overviewer. It defaults to the PIL paste function when the custom
alpha-over extension cannot be found.
"""
from c_overviewer import alpha_over as extension_alpha_over
def alpha_over(dest, src, pos_or_rect=(0, 0), mask=None):
"""Composite src over dest, using mask as the alpha channel (if
given), otherwise using src's alpha channel. pos_or_rect can
either be a position or a rectangle, specifying where on dest to
put src. Falls back to dest.paste() if the alpha_over extension
can't be found."""
if mask is None:
mask = src
global extension_alpha_over
return extension_alpha_over(dest, src, pos_or_rect, mask)

View File

@@ -27,9 +27,10 @@ class MultiWorldParser(object):
# This maps setting names to their values as given in # This maps setting names to their values as given in
# settingsDefinition.py # settingsDefinition.py
self._settings = {} self._settings = {}
for settingname in settingsDefinition.__all__: for settingname in dir(settingsDefinition):
setting = getattr(settingsDefinition, settingname) setting = getattr(settingsDefinition, settingname)
assert isinstance(setting, settingsValidators.Setting) if not isinstance(setting, settingsValidators.Setting):
continue
self._settings[settingname] = setting self._settings[settingname] = setting

View File

@@ -19,6 +19,7 @@ import multiprocessing.managers
import cPickle as pickle import cPickle as pickle
import Queue import Queue
import time import time
import logging
from signals import Signal from signals import Signal

View File

@@ -1,84 +0,0 @@
# This file is part of the Minecraft Overviewer.
#
# Minecraft Overviewer is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# Minecraft Overviewer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
import os
import os.path
import stat
import cPickle
from PIL import Image
import shutil
from time import strftime, localtime
import json
import locale
import codecs
import util
from c_overviewer import get_render_mode_inheritance, get_render_mode_info
import overviewer_version
"""
This module has routines related to generating a Google Maps-based
interface out of a set of tiles.
"""
class MapGen(object):
def __init__(self, quadtrees, configInfo):
"""Generates a Google Maps interface for the given list of
quadtrees. All of the quadtrees must have the same destdir,
image format, and world.
Note:tiledir for each quadtree should be unique. By default the tiledir
is determined by the rendermode
"""
self.skipjs = configInfo.get('skipjs', False)
self.nosigns = configInfo.get('nosigns', False)
self.web_assets_hook = configInfo.get('web_assets_hook', None)
self.web_assets_path = configInfo.get('web_assets_path', None)
self.bg_color = configInfo.get('bg_color')
self.north_direction = configInfo.get('north_direction', 'lower-left')
if not len(quadtrees) > 0:
raise ValueError("there must be at least one quadtree to work on")
self.destdir = quadtrees[0].destdir
self.regionobj = quadtrees[0].regionobj
self.p = quadtrees[0].p
for i in quadtrees:
if i.destdir != self.destdir or i.regionobj != self.regionobj:
raise ValueError("all the given quadtrees must have the same destdir and world")
self.quadtrees = quadtrees
def go(self, procs):
"""Writes out overviewerConfig.js and does copying of the other static web assets
"""
### TODO remove this method? It has been moved into assetmanager.py
pass
def finalize(self):
"""Write out persistent data file and marker listings file
"""
### TODO remove this method? It has been moved into assetmanager.py
pass

View File

@@ -45,11 +45,6 @@
from settingsValidators import * from settingsValidators import *
# This is the export list for this module. It defines which items defined in
# this module are recognized by the config parser. Don't forget to update this
# if you add new items!
__all__ = ['render', 'world', 'outputdir']
# render is a dictionary mapping strings to dicts. These dicts describe the # render is a dictionary mapping strings to dicts. These dicts describe the
# configuration for that render. Therefore, the validator for 'render' is set # configuration for that render. Therefore, the validator for 'render' is set
# to a dict validator configured to validate keys as strings and values as... # to a dict validator configured to validate keys as strings and values as...
@@ -87,3 +82,4 @@ world = Setting(required=True, validator=make_dictValidator(validateStr, validat
outputdir = Setting(required=True, validator=validateOutputDir, default=None) outputdir = Setting(required=True, validator=validateOutputDir, default=None)
processes = Setting(required=True, validator=int, default=-1)

View File

@@ -239,25 +239,35 @@ PyObject *
alpha_over_wrap(PyObject *self, PyObject *args) alpha_over_wrap(PyObject *self, PyObject *args)
{ {
/* raw input python variables */ /* raw input python variables */
PyObject *dest, *src, *pos, *mask; PyObject *dest, *src, *pos = NULL, *mask = NULL;
/* destination position and size */ /* destination position and size */
int dx, dy, xsize, ysize; int dx, dy, xsize, ysize;
/* return value: dest image on success */ /* return value: dest image on success */
PyObject *ret; PyObject *ret;
if (!PyArg_ParseTuple(args, "OOOO", &dest, &src, &pos, &mask)) if (!PyArg_ParseTuple(args, "OO|OO", &dest, &src, &pos, &mask))
return NULL; return NULL;
if (mask == NULL)
mask = src;
/* destination position read */ /* destination position read */
if (!PyArg_ParseTuple(pos, "iiii", &dx, &dy, &xsize, &ysize)) { if (pos == NULL) {
/* try again, but this time try to read a point */
PyErr_Clear();
xsize = 0; xsize = 0;
ysize = 0; ysize = 0;
if (!PyArg_ParseTuple(pos, "ii", &dx, &dy)) { dx = 0;
PyErr_SetString(PyExc_TypeError, dy = 0;
"given blend destination rect is not valid"); } else {
return NULL; if (!PyArg_ParseTuple(pos, "iiii", &dx, &dy, &xsize, &ysize)) {
/* try again, but this time try to read a point */
PyErr_Clear();
xsize = 0;
ysize = 0;
if (!PyArg_ParseTuple(pos, "ii", &dx, &dy)) {
PyErr_SetString(PyExc_TypeError,
"given blend destination rect is not valid");
return NULL;
}
} }
} }

View File

@@ -26,7 +26,7 @@
// increment this value if you've made a change to the c extesion // increment this value if you've made a change to the c extesion
// and want to force users to rebuild // and want to force users to rebuild
#define OVERVIEWER_EXTENSION_VERSION 19 #define OVERVIEWER_EXTENSION_VERSION 20
/* Python PIL, and numpy headers */ /* Python PIL, and numpy headers */
#include <Python.h> #include <Python.h>

View File

@@ -27,7 +27,7 @@ import logging
import functools import functools
import util import util
import composite from c_overviewer import alpha_over
## ##
## Textures object ## Textures object
@@ -455,7 +455,7 @@ class Textures(object):
top = self.transform_image_top(top) top = self.transform_image_top(top)
if not side: if not side:
composite.alpha_over(img, top, (0,0), top) alpha_over(img, top, (0,0), top)
return img return img
side = self.transform_image_side(side) side = self.transform_image_side(side)
@@ -471,9 +471,9 @@ class Textures(object):
otherside = ImageEnhance.Brightness(otherside).enhance(0.8) otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
otherside.putalpha(othersidealpha) otherside.putalpha(othersidealpha)
composite.alpha_over(img, top, (0,0), top) alpha_over(img, top, (0,0), top)
composite.alpha_over(img, side, (0,6), side) alpha_over(img, side, (0,6), side)
composite.alpha_over(img, otherside, (12,6), otherside) alpha_over(img, otherside, (12,6), otherside)
# Manually touch up 6 pixels that leave a gap because of how the # Manually touch up 6 pixels that leave a gap because of how the
# shearing works out. This makes the blocks perfectly tessellate-able # shearing works out. This makes the blocks perfectly tessellate-able
@@ -539,7 +539,7 @@ class Textures(object):
side1 = ImageEnhance.Brightness(side1).enhance(0.9) side1 = ImageEnhance.Brightness(side1).enhance(0.9)
side1.putalpha(sidealpha) side1.putalpha(sidealpha)
composite.alpha_over(img, side1, (0,0), side1) alpha_over(img, side1, (0,0), side1)
if side2 != None : if side2 != None :
@@ -550,11 +550,11 @@ class Textures(object):
side2 = ImageEnhance.Brightness(side2).enhance(0.8) side2 = ImageEnhance.Brightness(side2).enhance(0.8)
side2.putalpha(sidealpha2) side2.putalpha(sidealpha2)
composite.alpha_over(img, side2, (12,0), side2) alpha_over(img, side2, (12,0), side2)
if bottom != None : if bottom != None :
bottom = self.transform_image_top(bottom) bottom = self.transform_image_top(bottom)
composite.alpha_over(img, bottom, (0,12), bottom) alpha_over(img, bottom, (0,12), bottom)
# front sides # front sides
if side3 != None : if side3 != None :
@@ -565,7 +565,7 @@ class Textures(object):
side3 = ImageEnhance.Brightness(side3).enhance(0.9) side3 = ImageEnhance.Brightness(side3).enhance(0.9)
side3.putalpha(sidealpha) side3.putalpha(sidealpha)
composite.alpha_over(img, side3, (0,6), side3) alpha_over(img, side3, (0,6), side3)
if side4 != None : if side4 != None :
side4 = self.transform_image_side(side4) side4 = self.transform_image_side(side4)
@@ -576,11 +576,11 @@ class Textures(object):
side4 = ImageEnhance.Brightness(side4).enhance(0.8) side4 = ImageEnhance.Brightness(side4).enhance(0.8)
side4.putalpha(sidealpha) side4.putalpha(sidealpha)
composite.alpha_over(img, side4, (12,6), side4) alpha_over(img, side4, (12,6), side4)
if top != None : if top != None :
top = self.transform_image_top(top) top = self.transform_image_top(top)
composite.alpha_over(img, top, (0, increment), top) alpha_over(img, top, (0, increment), top)
return img return img
@@ -592,8 +592,8 @@ class Textures(object):
side = self.transform_image_side(side) side = self.transform_image_side(side)
otherside = side.transpose(Image.FLIP_LEFT_RIGHT) otherside = side.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, side, (6,3), side) alpha_over(img, side, (6,3), side)
composite.alpha_over(img, otherside, (6,3), otherside) alpha_over(img, otherside, (6,3), otherside)
return img return img
def build_billboard(self, tex): def build_billboard(self, tex):
@@ -603,7 +603,7 @@ class Textures(object):
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
front = tex.resize((14, 11), Image.ANTIALIAS) front = tex.resize((14, 11), Image.ANTIALIAS)
composite.alpha_over(img, front, (5,9)) alpha_over(img, front, (5,9))
return img return img
def generate_opaque_mask(self, img): def generate_opaque_mask(self, img):
@@ -627,96 +627,6 @@ class Textures(object):
return None return None
return (img, self.generate_opaque_mask(img)) return (img, self.generate_opaque_mask(img))
##
## Biomes
##
currentBiomeFile = None
currentBiomeData = None
grasscolor = None
foliagecolor = None
watercolor = None
_north = None
def prepareBiomeData(worlddir):
global grasscolor, foliagecolor, watercolor
# skip if the color files are already loaded
if grasscolor and foliagecolor:
return
biomeDir = os.path.join(worlddir, "biomes")
if not os.path.exists(biomeDir):
raise Exception("biomes not found")
# try to find the biome color images. If _find_file can't locate them
# then try looking in the EXTRACTEDBIOMES folder
try:
grasscolor = list(_load_image("grasscolor.png").getdata())
foliagecolor = list(_load_image("foliagecolor.png").getdata())
# don't force the water color just yet
# since the biome extractor doesn't know about it
try:
watercolor = list(_load_image("watercolor.png").getdata())
except IOError:
pass
except IOError:
try:
grasscolor = list(Image.open(os.path.join(biomeDir,"grasscolor.png")).getdata())
foliagecolor = list(Image.open(os.path.join(biomeDir,"foliagecolor.png")).getdata())
except Exception:
# clear anything that managed to get set
grasscolor = None
foliagecolor = None
watercolor = None
def getBiomeData(worlddir, chunkX, chunkY):
'''Opens the worlddir and reads in the biome color information
from the .biome files. See also:
http://www.minecraftforum.net/viewtopic.php?f=25&t=80902
'''
global currentBiomeFile, currentBiomeData
global _north
biomeX = chunkX // 32
biomeY = chunkY // 32
rots = 0
if _north == 1:
temp = biomeX
biomeX = biomeY
biomeY = -temp-1
rots = 3
elif _north == 2:
biomeX = -biomeX-1
biomeY = -biomeY-1
rots = 2
elif _north == 3:
temp = biomeX
biomeX = -biomeY-1
biomeY = temp
rots = 1
biomeFile = "b.%d.%d.biome" % (biomeX, biomeY)
if biomeFile == currentBiomeFile:
return currentBiomeData
try:
with open(os.path.join(worlddir, "biomes", biomeFile), "rb") as f:
rawdata = f.read()
# make sure the file size is correct
if not len(rawdata) == 512 * 512 * 2:
raise Exception("Biome file %s is not valid." % (biomeFile,))
data = numpy.reshape(numpy.rot90(numpy.reshape(
numpy.frombuffer(rawdata, dtype=numpy.dtype(">u2")),
(512,512)),rots), -1)
except IOError:
data = None
pass # no biome data
currentBiomeFile = biomeFile
currentBiomeData = data
return data
## ##
## The other big one: @material and associated framework ## The other big one: @material and associated framework
## ##
@@ -840,7 +750,7 @@ def grass(self, blockid, data):
side_img = self.terrain_images[68] side_img = self.terrain_images[68]
img = self.build_block(self.terrain_images[0], side_img) img = self.build_block(self.terrain_images[0], side_img)
if not data & 0x10: if not data & 0x10:
composite.alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture)
return img return img
# dirt # dirt
@@ -1124,29 +1034,29 @@ def rails(self, blockid, data):
## use transform_image to scale and shear ## use transform_image to scale and shear
if data == 0: if data == 0:
track = self.transform_image_top(raw_straight) track = self.transform_image_top(raw_straight)
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
elif data == 6: elif data == 6:
track = self.transform_image_top(raw_corner) track = self.transform_image_top(raw_corner)
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
elif data == 7: elif data == 7:
track = self.transform_image_top(raw_corner.rotate(270)) track = self.transform_image_top(raw_corner.rotate(270))
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
elif data == 8: elif data == 8:
# flip # flip
track = self.transform_image_top(raw_corner.transpose(Image.FLIP_TOP_BOTTOM).rotate(90)) track = self.transform_image_top(raw_corner.transpose(Image.FLIP_TOP_BOTTOM).rotate(90))
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
elif data == 9: elif data == 9:
track = self.transform_image_top(raw_corner.transpose(Image.FLIP_TOP_BOTTOM)) track = self.transform_image_top(raw_corner.transpose(Image.FLIP_TOP_BOTTOM))
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
elif data == 1: elif data == 1:
track = self.transform_image_top(raw_straight.rotate(90)) track = self.transform_image_top(raw_straight.rotate(90))
composite.alpha_over(img, track, (0,12), track) alpha_over(img, track, (0,12), track)
#slopes #slopes
elif data == 2: # slope going up in +x direction elif data == 2: # slope going up in +x direction
track = self.transform_image_slope(raw_straight) track = self.transform_image_slope(raw_straight)
track = track.transpose(Image.FLIP_LEFT_RIGHT) track = track.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, track, (2,0), track) alpha_over(img, track, (2,0), track)
# the 2 pixels move is needed to fit with the adjacent tracks # the 2 pixels move is needed to fit with the adjacent tracks
elif data == 3: # slope going up in -x direction elif data == 3: # slope going up in -x direction
@@ -1157,7 +1067,7 @@ def rails(self, blockid, data):
# the track doesn't start from image corners, be carefull drawing the line! # the track doesn't start from image corners, be carefull drawing the line!
elif data == 4: # slope going up in -y direction elif data == 4: # slope going up in -y direction
track = self.transform_image_slope(raw_straight) track = self.transform_image_slope(raw_straight)
composite.alpha_over(img, track, (0,0), track) alpha_over(img, track, (0,0), track)
elif data == 5: # slope going up in +y direction elif data == 5: # slope going up in +y direction
# same as "data == 3" # same as "data == 3"
@@ -1214,12 +1124,12 @@ def piston(self, blockid, data):
img = self.build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), None) img = self.build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), None)
temp = self.transform_image_side(interior_t) temp = self.transform_image_side(interior_t)
temp = temp.transpose(Image.FLIP_LEFT_RIGHT) temp = temp.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, temp, (9,5), temp) alpha_over(img, temp, (9,5), temp)
elif data & 0x07 == 0x4: # north elif data & 0x07 == 0x4: # north
img = self.build_full_block(side_t.rotate(90) ,None ,None , None, side_t.rotate(270)) img = self.build_full_block(side_t.rotate(90) ,None ,None , None, side_t.rotate(270))
temp = self.transform_image_side(interior_t) temp = self.transform_image_side(interior_t)
composite.alpha_over(img, temp, (3,5), temp) alpha_over(img, temp, (3,5), temp)
elif data & 0x07 == 0x5: # south elif data & 0x07 == 0x5: # south
img = self.build_full_block(side_t.rotate(270) ,None , None ,back_t, side_t.rotate(90)) img = self.build_full_block(side_t.rotate(270) ,None , None ,back_t, side_t.rotate(90))
@@ -1276,9 +1186,9 @@ def piston_extension(self, blockid, data):
# generate the horizontal piston extension stick # generate the horizontal piston extension stick
h_stick = Image.new("RGBA", (24,24), self.bgcolor) h_stick = Image.new("RGBA", (24,24), self.bgcolor)
temp = self.transform_image_side(side_t) temp = self.transform_image_side(side_t)
composite.alpha_over(h_stick, temp, (1,7), temp) alpha_over(h_stick, temp, (1,7), temp)
temp = self.transform_image_top(side_t.rotate(90)) temp = self.transform_image_top(side_t.rotate(90))
composite.alpha_over(h_stick, temp, (1,1), temp) alpha_over(h_stick, temp, (1,1), temp)
# Darken it # Darken it
sidealpha = h_stick.split()[3] sidealpha = h_stick.split()[3]
h_stick = ImageEnhance.Brightness(h_stick).enhance(0.85) h_stick = ImageEnhance.Brightness(h_stick).enhance(0.85)
@@ -1287,9 +1197,9 @@ def piston_extension(self, blockid, data):
# generate the vertical piston extension stick # generate the vertical piston extension stick
v_stick = Image.new("RGBA", (24,24), self.bgcolor) v_stick = Image.new("RGBA", (24,24), self.bgcolor)
temp = self.transform_image_side(side_t.rotate(90)) temp = self.transform_image_side(side_t.rotate(90))
composite.alpha_over(v_stick, temp, (12,6), temp) alpha_over(v_stick, temp, (12,6), temp)
temp = temp.transpose(Image.FLIP_LEFT_RIGHT) temp = temp.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(v_stick, temp, (1,6), temp) alpha_over(v_stick, temp, (1,6), temp)
# Darken it # Darken it
sidealpha = v_stick.split()[3] sidealpha = v_stick.split()[3]
v_stick = ImageEnhance.Brightness(v_stick).enhance(0.85) v_stick = ImageEnhance.Brightness(v_stick).enhance(0.85)
@@ -1299,32 +1209,32 @@ def piston_extension(self, blockid, data):
if data & 0x07 == 0x0: # down if data & 0x07 == 0x0: # down
side_t = side_t.rotate(180) side_t = side_t.rotate(180)
img = self.build_full_block((back_t, 12) ,None ,None ,side_t, side_t) img = self.build_full_block((back_t, 12) ,None ,None ,side_t, side_t)
composite.alpha_over(img, v_stick, (0,-3), v_stick) alpha_over(img, v_stick, (0,-3), v_stick)
elif data & 0x07 == 0x1: # up elif data & 0x07 == 0x1: # up
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
img2 = self.build_full_block(piston_t ,None ,None ,side_t, side_t) img2 = self.build_full_block(piston_t ,None ,None ,side_t, side_t)
composite.alpha_over(img, v_stick, (0,4), v_stick) alpha_over(img, v_stick, (0,4), v_stick)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x2: # east elif data & 0x07 == 0x2: # east
img = self.build_full_block(side_t ,None ,None ,side_t.rotate(90), None) img = self.build_full_block(side_t ,None ,None ,side_t.rotate(90), None)
temp = self.transform_image_side(back_t).transpose(Image.FLIP_LEFT_RIGHT) temp = self.transform_image_side(back_t).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, temp, (2,2), temp) alpha_over(img, temp, (2,2), temp)
composite.alpha_over(img, h_stick, (6,3), h_stick) alpha_over(img, h_stick, (6,3), h_stick)
elif data & 0x07 == 0x3: # west elif data & 0x07 == 0x3: # west
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
img2 = self.build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), piston_t) img2 = self.build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), piston_t)
composite.alpha_over(img, h_stick, (0,0), h_stick) alpha_over(img, h_stick, (0,0), h_stick)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x4: # north elif data & 0x07 == 0x4: # north
img = self.build_full_block(side_t.rotate(90) ,None ,None , piston_t, side_t.rotate(270)) img = self.build_full_block(side_t.rotate(90) ,None ,None , piston_t, side_t.rotate(270))
composite.alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (0,0), h_stick.transpose(Image.FLIP_LEFT_RIGHT)) alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (0,0), h_stick.transpose(Image.FLIP_LEFT_RIGHT))
elif data & 0x07 == 0x5: # south elif data & 0x07 == 0x5: # south
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
img2 = self.build_full_block(side_t.rotate(270) ,None ,None ,None, side_t.rotate(90)) img2 = self.build_full_block(side_t.rotate(270) ,None ,None ,None, side_t.rotate(90))
temp = self.transform_image_side(back_t) temp = self.transform_image_side(back_t)
composite.alpha_over(img2, temp, (10,2), temp) alpha_over(img2, temp, (10,2), temp)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
composite.alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (-3,2), h_stick.transpose(Image.FLIP_LEFT_RIGHT)) alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (-3,2), h_stick.transpose(Image.FLIP_LEFT_RIGHT))
return img return img
@@ -1419,7 +1329,7 @@ def slabs(self, blockid, data):
# cut the side texture in half # cut the side texture in half
mask = side.crop((0,8,16,16)) mask = side.crop((0,8,16,16))
side = Image.new(side.mode, side.size, self.bgcolor) side = Image.new(side.mode, side.size, self.bgcolor)
composite.alpha_over(side, mask,(0,0,16,8), mask) alpha_over(side, mask,(0,0,16,8), mask)
# plain slab # plain slab
top = self.transform_image_top(top) top = self.transform_image_top(top)
@@ -1434,9 +1344,9 @@ def slabs(self, blockid, data):
otherside.putalpha(othersidealpha) otherside.putalpha(othersidealpha)
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, side, (0,12), side) alpha_over(img, side, (0,12), side)
composite.alpha_over(img, otherside, (12,12), otherside) alpha_over(img, otherside, (12,12), otherside)
composite.alpha_over(img, top, (0,6), top) alpha_over(img, top, (0,6), top)
return img return img
@@ -1482,9 +1392,9 @@ def torches(self, blockid, data):
# compose a torch bigger than the normal # compose a torch bigger than the normal
# (better for doing transformations) # (better for doing transformations)
torch = Image.new("RGBA", (16,16), self.bgcolor) torch = Image.new("RGBA", (16,16), self.bgcolor)
composite.alpha_over(torch,small,(-4,-3)) alpha_over(torch,small,(-4,-3))
composite.alpha_over(torch,small,(-5,-2)) alpha_over(torch,small,(-5,-2))
composite.alpha_over(torch,small,(-3,-2)) alpha_over(torch,small,(-3,-2))
# angle of inclination of the texture # angle of inclination of the texture
rotation = 15 rotation = 15
@@ -1514,10 +1424,10 @@ def torches(self, blockid, data):
ImageDraw.Draw(slice).rectangle((6,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(slice).rectangle((6,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(slice).rectangle((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(slice).rectangle((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0))
composite.alpha_over(img, slice, (7,5)) alpha_over(img, slice, (7,5))
composite.alpha_over(img, small_crop, (6,6)) alpha_over(img, small_crop, (6,6))
composite.alpha_over(img, small_crop, (7,6)) alpha_over(img, small_crop, (7,6))
composite.alpha_over(img, slice, (7,7)) alpha_over(img, slice, (7,7))
return img return img
@@ -1530,11 +1440,11 @@ def fire(self, blockid, data):
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, side1, (12,0), side1) alpha_over(img, side1, (12,0), side1)
composite.alpha_over(img, side2, (0,0), side2) alpha_over(img, side2, (0,0), side2)
composite.alpha_over(img, side1, (0,6), side1) alpha_over(img, side1, (0,6), side1)
composite.alpha_over(img, side2, (12,6), side2) alpha_over(img, side2, (12,6), side2)
return img return img
@@ -1596,24 +1506,24 @@ def stairs(self, blockid, data):
tmp1 = ImageEnhance.Brightness(tmp1).enhance(0.8) tmp1 = ImageEnhance.Brightness(tmp1).enhance(0.8)
tmp1.putalpha(sidealpha) tmp1.putalpha(sidealpha)
composite.alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
composite.alpha_over(img, tmp1, (6,3)) alpha_over(img, tmp1, (6,3))
tmp2 = self.transform_image_top(half_block_l) tmp2 = self.transform_image_top(half_block_l)
composite.alpha_over(img, tmp2, (0,6)) alpha_over(img, tmp2, (0,6))
elif data == 1: # ascending north elif data == 1: # ascending north
img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back
tmp1 = self.transform_image_top(half_block_r) tmp1 = self.transform_image_top(half_block_r)
composite.alpha_over(img, tmp1, (0,6)) alpha_over(img, tmp1, (0,6))
tmp2 = self.build_full_block(half_block_l, None, None, texture, side) tmp2 = self.build_full_block(half_block_l, None, None, texture, side)
composite.alpha_over(img, tmp2) alpha_over(img, tmp2)
elif data == 2: # ascending west elif data == 2: # ascending west
img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back
tmp1 = self.transform_image_top(half_block_u) tmp1 = self.transform_image_top(half_block_u)
composite.alpha_over(img, tmp1, (0,6)) alpha_over(img, tmp1, (0,6))
tmp2 = self.build_full_block(half_block_d, None, None, side, texture) tmp2 = self.build_full_block(half_block_d, None, None, side, texture)
composite.alpha_over(img, tmp2) alpha_over(img, tmp2)
elif data == 3: # ascending east elif data == 3: # ascending east
img = self.build_full_block(half_block_u, None, None, side.transpose(Image.FLIP_LEFT_RIGHT), half_block_d) img = self.build_full_block(half_block_u, None, None, side.transpose(Image.FLIP_LEFT_RIGHT), half_block_d)
@@ -1625,10 +1535,10 @@ def stairs(self, blockid, data):
tmp1 = ImageEnhance.Brightness(tmp1).enhance(0.7) tmp1 = ImageEnhance.Brightness(tmp1).enhance(0.7)
tmp1.putalpha(sidealpha) tmp1.putalpha(sidealpha)
composite.alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
composite.alpha_over(img, tmp1, (6,3)) alpha_over(img, tmp1, (6,3))
tmp2 = self.transform_image_top(half_block_d) tmp2 = self.transform_image_top(half_block_d)
composite.alpha_over(img, tmp2, (0,6)) alpha_over(img, tmp2, (0,6))
# touch up a (horrible) pixel # touch up a (horrible) pixel
img.putpixel((18,3),(0,0,0,0)) img.putpixel((18,3),(0,0,0,0))
@@ -1736,16 +1646,16 @@ def wire(self, blockid, data):
else: else:
bottom = Image.new("RGBA", (16,16), self.bgcolor) bottom = Image.new("RGBA", (16,16), self.bgcolor)
if (data & 0b0001) == 1: if (data & 0b0001) == 1:
composite.alpha_over(bottom,branch_top_left) alpha_over(bottom,branch_top_left)
if (data & 0b1000) == 8: if (data & 0b1000) == 8:
composite.alpha_over(bottom,branch_top_right) alpha_over(bottom,branch_top_right)
if (data & 0b0010) == 2: if (data & 0b0010) == 2:
composite.alpha_over(bottom,branch_bottom_left) alpha_over(bottom,branch_bottom_left)
if (data & 0b0100) == 4: if (data & 0b0100) == 4:
composite.alpha_over(bottom,branch_bottom_right) alpha_over(bottom,branch_bottom_right)
# check for going up redstone wire # check for going up redstone wire
if data & 0b100000 == 32: if data & 0b100000 == 32:
@@ -1787,9 +1697,9 @@ def crops(self, blockid, data):
crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT)
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, crop1, (0,12), crop1) alpha_over(img, crop1, (0,12), crop1)
composite.alpha_over(img, crop2, (6,3), crop2) alpha_over(img, crop2, (6,3), crop2)
composite.alpha_over(img, crop3, (6,3), crop3) alpha_over(img, crop3, (6,3), crop3)
return img return img
# farmland # farmland
@@ -1843,12 +1753,12 @@ def signpost(self, blockid, data):
elif data in (3,4,5,11,12,13): elif data in (3,4,5,11,12,13):
incrementx = +1 incrementx = +1
composite.alpha_over(img, texture_stick,(11, 8),texture_stick) alpha_over(img, texture_stick,(11, 8),texture_stick)
# post2 is a brighter signpost pasted with a small shift, # post2 is a brighter signpost pasted with a small shift,
# gives to the signpost some 3D effect. # gives to the signpost some 3D effect.
post2 = ImageEnhance.Brightness(post).enhance(1.2) post2 = ImageEnhance.Brightness(post).enhance(1.2)
composite.alpha_over(img, post2,(incrementx, -3),post2) alpha_over(img, post2,(incrementx, -3),post2)
composite.alpha_over(img, post, (0,-2), post) alpha_over(img, post, (0,-2), post)
return img return img
@@ -1890,36 +1800,36 @@ def door(self, blockid, data):
if (data & 0x03) == 0: # northeast corner if (data & 0x03) == 0: # northeast corner
if not swung: if not swung:
tex = self.transform_image_side(raw_door) tex = self.transform_image_side(raw_door)
composite.alpha_over(img, tex, (0,6), tex) alpha_over(img, tex, (0,6), tex)
else: else:
# flip first to set the doornob on the correct side # flip first to set the doornob on the correct side
tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)) tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
tex = tex.transpose(Image.FLIP_LEFT_RIGHT) tex = tex.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (0,0), tex) alpha_over(img, tex, (0,0), tex)
if (data & 0x03) == 1: # southeast corner if (data & 0x03) == 1: # southeast corner
if not swung: if not swung:
tex = self.transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT) tex = self.transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (0,0), tex) alpha_over(img, tex, (0,0), tex)
else: else:
tex = self.transform_image_side(raw_door) tex = self.transform_image_side(raw_door)
composite.alpha_over(img, tex, (12,0), tex) alpha_over(img, tex, (12,0), tex)
if (data & 0x03) == 2: # southwest corner if (data & 0x03) == 2: # southwest corner
if not swung: if not swung:
tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)) tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
composite.alpha_over(img, tex, (12,0), tex) alpha_over(img, tex, (12,0), tex)
else: else:
tex = self.transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT) tex = self.transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (12,6), tex) alpha_over(img, tex, (12,6), tex)
if (data & 0x03) == 3: # northwest corner if (data & 0x03) == 3: # northwest corner
if not swung: if not swung:
tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT) tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (12,6), tex) alpha_over(img, tex, (12,6), tex)
else: else:
tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)) tex = self.transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
composite.alpha_over(img, tex, (0,6), tex) alpha_over(img, tex, (0,6), tex)
return img return img
@@ -1952,19 +1862,19 @@ def ladder(self, blockid, data):
# but since ladders can apparently be placed on transparent blocks, we # but since ladders can apparently be placed on transparent blocks, we
# have to render this thing anyway. same for data == 2 # have to render this thing anyway. same for data == 2
tex = transform_image_side(raw_texture) tex = transform_image_side(raw_texture)
composite.alpha_over(img, tex, (0,6), tex) alpha_over(img, tex, (0,6), tex)
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
if data == 2: if data == 2:
tex = transform_image_side(raw_texture).transpose(Image.FLIP_LEFT_RIGHT) tex = transform_image_side(raw_texture).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (12,6), tex) alpha_over(img, tex, (12,6), tex)
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
if data == 3: if data == 3:
tex = transform_image_side(raw_texture).transpose(Image.FLIP_LEFT_RIGHT) tex = transform_image_side(raw_texture).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (0,0), tex) alpha_over(img, tex, (0,0), tex)
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
if data == 4: if data == 4:
tex = transform_image_side(raw_texture) tex = transform_image_side(raw_texture)
composite.alpha_over(img, tex, (12,0), tex) alpha_over(img, tex, (12,0), tex)
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
@@ -2020,8 +1930,8 @@ def wall_sign(self, blockid, data): # wall sign
sign = self.build_full_block(None, None, None, texture, None) sign = self.build_full_block(None, None, None, texture, None)
sign2 = ImageEnhance.Brightness(sign).enhance(1.2) sign2 = ImageEnhance.Brightness(sign).enhance(1.2)
composite.alpha_over(img, sign2,(incrementx, 2),sign2) alpha_over(img, sign2,(incrementx, 2),sign2)
composite.alpha_over(img, sign, (0,3), sign) alpha_over(img, sign, (0,3), sign)
return img return img
@@ -2071,8 +1981,8 @@ def levers(self, blockid, data):
c_stick = Image.new("RGBA", (16,16), self.bgcolor) c_stick = Image.new("RGBA", (16,16), self.bgcolor)
tmp = ImageEnhance.Brightness(stick).enhance(0.8) tmp = ImageEnhance.Brightness(stick).enhance(0.8)
composite.alpha_over(c_stick, tmp, (1,0), tmp) alpha_over(c_stick, tmp, (1,0), tmp)
composite.alpha_over(c_stick, stick, (0,0), stick) alpha_over(c_stick, stick, (0,0), stick)
t_stick = self.transform_image_side(c_stick.rotate(45, Image.NEAREST)) t_stick = self.transform_image_side(c_stick.rotate(45, Image.NEAREST))
# where the lever will be composed # where the lever will be composed
@@ -2088,33 +1998,33 @@ def levers(self, blockid, data):
base = self.transform_image_side(t_base) base = self.transform_image_side(t_base)
# paste it twice with different brightness to make a fake 3D effect # paste it twice with different brightness to make a fake 3D effect
composite.alpha_over(img, base, (12,-1), base) alpha_over(img, base, (12,-1), base)
alpha = base.split()[3] alpha = base.split()[3]
base = ImageEnhance.Brightness(base).enhance(0.9) base = ImageEnhance.Brightness(base).enhance(0.9)
base.putalpha(alpha) base.putalpha(alpha)
composite.alpha_over(img, base, (11,0), base) alpha_over(img, base, (11,0), base)
# paste the lever stick # paste the lever stick
pos = (7,-7) pos = (7,-7)
if powered: if powered:
t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM) t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM)
pos = (7,6) pos = (7,6)
composite.alpha_over(img, t_stick, pos, t_stick) alpha_over(img, t_stick, pos, t_stick)
elif data == 3: # facing WEST elif data == 3: # facing WEST
base = self.transform_image_side(t_base) base = self.transform_image_side(t_base)
# paste it twice with different brightness to make a fake 3D effect # paste it twice with different brightness to make a fake 3D effect
base = base.transpose(Image.FLIP_LEFT_RIGHT) base = base.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, base, (0,-1), base) alpha_over(img, base, (0,-1), base)
alpha = base.split()[3] alpha = base.split()[3]
base = ImageEnhance.Brightness(base).enhance(0.9) base = ImageEnhance.Brightness(base).enhance(0.9)
base.putalpha(alpha) base.putalpha(alpha)
composite.alpha_over(img, base, (1,0), base) alpha_over(img, base, (1,0), base)
# paste the lever stick # paste the lever stick
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT) t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
@@ -2122,7 +2032,7 @@ def levers(self, blockid, data):
if powered: if powered:
t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM) t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM)
pos = (6,6) pos = (6,6)
composite.alpha_over(img, t_stick, pos, t_stick) alpha_over(img, t_stick, pos, t_stick)
elif data == 4: # facing EAST elif data == 4: # facing EAST
# levers can't be placed in transparent blocks, so this # levers can't be placed in transparent blocks, so this
@@ -2138,15 +2048,15 @@ def levers(self, blockid, data):
tmp = ImageEnhance.Brightness(base).enhance(0.8) tmp = ImageEnhance.Brightness(base).enhance(0.8)
tmp.putalpha(alpha) tmp.putalpha(alpha)
composite.alpha_over(img, tmp, (0,12), tmp) alpha_over(img, tmp, (0,12), tmp)
composite.alpha_over(img, base, (0,11), base) alpha_over(img, base, (0,11), base)
# lever stick # lever stick
pos = (3,2) pos = (3,2)
if not powered: if not powered:
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT) t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
pos = (11,2) pos = (11,2)
composite.alpha_over(img, t_stick, pos, t_stick) alpha_over(img, t_stick, pos, t_stick)
elif data == 6: # pointing east when off elif data == 6: # pointing east when off
# lever base, fake 3d again # lever base, fake 3d again
@@ -2156,15 +2066,15 @@ def levers(self, blockid, data):
tmp = ImageEnhance.Brightness(base).enhance(0.8) tmp = ImageEnhance.Brightness(base).enhance(0.8)
tmp.putalpha(alpha) tmp.putalpha(alpha)
composite.alpha_over(img, tmp, (0,12), tmp) alpha_over(img, tmp, (0,12), tmp)
composite.alpha_over(img, base, (0,11), base) alpha_over(img, base, (0,11), base)
# lever stick # lever stick
pos = (2,3) pos = (2,3)
if not powered: if not powered:
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT) t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
pos = (10,2) pos = (10,2)
composite.alpha_over(img, t_stick, pos, t_stick) alpha_over(img, t_stick, pos, t_stick)
return img return img
@@ -2192,10 +2102,10 @@ def pressure_plate(self, blockid, data):
#show it 3d or 2d if unpressed or pressed #show it 3d or 2d if unpressed or pressed
if data == 0: if data == 0:
composite.alpha_over(img,topd, (0,12),topd) alpha_over(img,topd, (0,12),topd)
composite.alpha_over(img,top, (0,11),top) alpha_over(img,top, (0,11),top)
elif data == 1: elif data == 1:
composite.alpha_over(img,top, (0,12),top) alpha_over(img,top, (0,12),top)
return img return img
@@ -2244,24 +2154,24 @@ def buttons(self, blockid, data):
elif data == 2: # facing NORTH elif data == 2: # facing NORTH
# paste it twice with different brightness to make a 3D effect # paste it twice with different brightness to make a 3D effect
composite.alpha_over(img, button, (12,-1), button) alpha_over(img, button, (12,-1), button)
alpha = button.split()[3] alpha = button.split()[3]
button = ImageEnhance.Brightness(button).enhance(0.9) button = ImageEnhance.Brightness(button).enhance(0.9)
button.putalpha(alpha) button.putalpha(alpha)
composite.alpha_over(img, button, (11,0), button) alpha_over(img, button, (11,0), button)
elif data == 3: # facing WEST elif data == 3: # facing WEST
# paste it twice with different brightness to make a 3D effect # paste it twice with different brightness to make a 3D effect
button = button.transpose(Image.FLIP_LEFT_RIGHT) button = button.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, button, (0,-1), button) alpha_over(img, button, (0,-1), button)
alpha = button.split()[3] alpha = button.split()[3]
button = ImageEnhance.Brightness(button).enhance(0.9) button = ImageEnhance.Brightness(button).enhance(0.9)
button.putalpha(alpha) button.putalpha(alpha)
composite.alpha_over(img, button, (1,0), button) alpha_over(img, button, (1,0), button)
elif data == 4: # facing EAST elif data == 4: # facing EAST
# buttons can't be placed in transparent blocks, so this # buttons can't be placed in transparent blocks, so this
@@ -2280,7 +2190,7 @@ def snow(self, blockid, data):
# make the side image, top 3/4 transparent # make the side image, top 3/4 transparent
mask = tex.crop((0,12,16,16)) mask = tex.crop((0,12,16,16))
sidetex = Image.new(tex.mode, tex.size, self.bgcolor) sidetex = Image.new(tex.mode, tex.size, self.bgcolor)
composite.alpha_over(sidetex, mask, (0,12,16,16), mask) alpha_over(sidetex, mask, (0,12,16,16), mask)
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
@@ -2288,9 +2198,9 @@ def snow(self, blockid, data):
side = self.transform_image_side(sidetex) side = self.transform_image_side(sidetex)
otherside = side.transpose(Image.FLIP_LEFT_RIGHT) otherside = side.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, side, (0,6), side) alpha_over(img, side, (0,6), side)
composite.alpha_over(img, otherside, (12,6), otherside) alpha_over(img, otherside, (12,6), otherside)
composite.alpha_over(img, top, (0,9), top) alpha_over(img, top, (0,9), top)
return img return img
@@ -2316,9 +2226,9 @@ def cactus(self, blockid, data):
otherside = ImageEnhance.Brightness(otherside).enhance(0.8) otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
otherside.putalpha(othersidealpha) otherside.putalpha(othersidealpha)
composite.alpha_over(img, side, (1,6), side) alpha_over(img, side, (1,6), side)
composite.alpha_over(img, otherside, (11,6), otherside) alpha_over(img, otherside, (11,6), otherside)
composite.alpha_over(img, top, (0,0), top) alpha_over(img, top, (0,0), top)
return img return img
@@ -2377,9 +2287,9 @@ def fence(self, blockid, data):
# Compose the fence big stick # Compose the fence big stick
fence_big = Image.new("RGBA", (24,24), self.bgcolor) fence_big = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(fence_big,fence_side, (5,4),fence_side) alpha_over(fence_big,fence_side, (5,4),fence_side)
composite.alpha_over(fence_big,fence_other_side, (7,4),fence_other_side) alpha_over(fence_big,fence_other_side, (7,4),fence_other_side)
composite.alpha_over(fence_big,fence_top, (0,0),fence_top) alpha_over(fence_big,fence_top, (0,0),fence_top)
# Now render the small sticks. # Now render the small sticks.
# Create needed images # Create needed images
@@ -2420,16 +2330,16 @@ def fence(self, blockid, data):
# then big stick and thecn small sticks in the front. # then big stick and thecn small sticks in the front.
if (data & 0b0001) == 1: if (data & 0b0001) == 1:
composite.alpha_over(img,fence_small_side, pos_top_left,fence_small_side) # top left alpha_over(img,fence_small_side, pos_top_left,fence_small_side) # top left
if (data & 0b1000) == 8: if (data & 0b1000) == 8:
composite.alpha_over(img,fence_small_other_side, pos_top_right,fence_small_other_side) # top right alpha_over(img,fence_small_other_side, pos_top_right,fence_small_other_side) # top right
composite.alpha_over(img,fence_big,(0,0),fence_big) alpha_over(img,fence_big,(0,0),fence_big)
if (data & 0b0010) == 2: if (data & 0b0010) == 2:
composite.alpha_over(img,fence_small_other_side, pos_bottom_left,fence_small_other_side) # bottom left alpha_over(img,fence_small_other_side, pos_bottom_left,fence_small_other_side) # bottom left
if (data & 0b0100) == 4: if (data & 0b0100) == 4:
composite.alpha_over(img,fence_small_side, pos_bottom_right,fence_small_side) # bottom right alpha_over(img,fence_small_side, pos_bottom_right,fence_small_side) # bottom right
return img return img
@@ -2490,10 +2400,10 @@ def portal(self, blockid, data):
otherside = side.transpose(Image.FLIP_TOP_BOTTOM) otherside = side.transpose(Image.FLIP_TOP_BOTTOM)
if data in (1,4): if data in (1,4):
composite.alpha_over(img, side, (5,4), side) alpha_over(img, side, (5,4), side)
if data in (2,8): if data in (2,8):
composite.alpha_over(img, otherside, (5,4), otherside) alpha_over(img, otherside, (5,4), otherside)
return img return img
@@ -2520,10 +2430,10 @@ def cake(self, blockid, data):
img = Image.new("RGBA", (24,24), self.bgcolor) img = Image.new("RGBA", (24,24), self.bgcolor)
# composite the cake # composite the cake
composite.alpha_over(img, side, (1,6), side) alpha_over(img, side, (1,6), side)
composite.alpha_over(img, otherside, (11,7), otherside) # workaround, fixes a hole alpha_over(img, otherside, (11,7), otherside) # workaround, fixes a hole
composite.alpha_over(img, otherside, (12,6), otherside) alpha_over(img, otherside, (12,6), otherside)
composite.alpha_over(img, top, (0,6), top) alpha_over(img, top, (0,6), top)
return img return img
@@ -2576,10 +2486,10 @@ def repeater(self, blockid, data):
ImageDraw.Draw(slice).rectangle((6,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(slice).rectangle((6,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0))
ImageDraw.Draw(slice).rectangle((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(slice).rectangle((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0))
composite.alpha_over(torch, slice, (6,4)) alpha_over(torch, slice, (6,4))
composite.alpha_over(torch, t_crop, (5,5)) alpha_over(torch, t_crop, (5,5))
composite.alpha_over(torch, t_crop, (6,5)) alpha_over(torch, t_crop, (6,5))
composite.alpha_over(torch, slice, (6,6)) alpha_over(torch, slice, (6,6))
# paste redstone torches everywhere! # paste redstone torches everywhere!
# the torch is too tall for the repeater, crop the bottom. # the torch is too tall for the repeater, crop the bottom.
@@ -2667,8 +2577,8 @@ def repeater(self, blockid, data):
# this paste order it's ok for east and south orientation # this paste order it's ok for east and south orientation
# but it's wrong for north and west orientations. But using the # but it's wrong for north and west orientations. But using the
# default texture pack the torches are small enough to no overlap. # default texture pack the torches are small enough to no overlap.
composite.alpha_over(img, torch, static_torch, torch) alpha_over(img, torch, static_torch, torch)
composite.alpha_over(img, torch, moving_torch, torch) alpha_over(img, torch, moving_torch, torch)
return img return img
@@ -2849,13 +2759,13 @@ def panes(self, blockid, data):
# then things in the front. # then things in the front.
if (data & 0b0001) == 1 or data == 0: if (data & 0b0001) == 1 or data == 0:
composite.alpha_over(img,up_left, (6,3),up_left) # top left alpha_over(img,up_left, (6,3),up_left) # top left
if (data & 0b1000) == 8 or data == 0: if (data & 0b1000) == 8 or data == 0:
composite.alpha_over(img,up_right, (6,3),up_right) # top right alpha_over(img,up_right, (6,3),up_right) # top right
if (data & 0b0010) == 2 or data == 0: if (data & 0b0010) == 2 or data == 0:
composite.alpha_over(img,dw_left, (6,3),dw_left) # bottom left alpha_over(img,dw_left, (6,3),dw_left) # bottom left
if (data & 0b0100) == 4 or data == 0: if (data & 0b0100) == 4 or data == 0:
composite.alpha_over(img,dw_right, (6,3),dw_right) # bottom right alpha_over(img,dw_right, (6,3),dw_right) # bottom right
return img return img
@@ -2875,7 +2785,7 @@ def stem(self, blockid, data):
# straight up stem # straight up stem
t = self.terrain_images[111].copy() t = self.terrain_images[111].copy()
img = Image.new("RGBA", (16,16), self.bgcolor) img = Image.new("RGBA", (16,16), self.bgcolor)
composite.alpha_over(img, t, (0, int(16 - 16*((data + 1)/8.))), t) alpha_over(img, t, (0, int(16 - 16*((data + 1)/8.))), t)
img = self.build_sprite(t) img = self.build_sprite(t)
if data & 7 == 7: if data & 7 == 7:
# fully grown stem gets brown color! # fully grown stem gets brown color!
@@ -2981,17 +2891,17 @@ def fence_gate(self, blockid, data):
# opened # opened
data = data & 0x3 data = data & 0x3
if data == 0: if data == 0:
composite.alpha_over(img, gate_side, (2,8), gate_side) alpha_over(img, gate_side, (2,8), gate_side)
composite.alpha_over(img, gate_side, (13,3), gate_side) alpha_over(img, gate_side, (13,3), gate_side)
elif data == 1: elif data == 1:
composite.alpha_over(img, gate_other_side, (-1,3), gate_other_side) alpha_over(img, gate_other_side, (-1,3), gate_other_side)
composite.alpha_over(img, gate_other_side, (10,8), gate_other_side) alpha_over(img, gate_other_side, (10,8), gate_other_side)
elif data == 2: elif data == 2:
composite.alpha_over(img, mirror_gate_side, (-1,7), mirror_gate_side) alpha_over(img, mirror_gate_side, (-1,7), mirror_gate_side)
composite.alpha_over(img, mirror_gate_side, (10,2), mirror_gate_side) alpha_over(img, mirror_gate_side, (10,2), mirror_gate_side)
elif data == 3: elif data == 3:
composite.alpha_over(img, mirror_gate_other_side, (2,1), mirror_gate_other_side) alpha_over(img, mirror_gate_other_side, (2,1), mirror_gate_other_side)
composite.alpha_over(img, mirror_gate_other_side, (13,7), mirror_gate_other_side) alpha_over(img, mirror_gate_other_side, (13,7), mirror_gate_other_side)
else: else:
# closed # closed
@@ -3002,11 +2912,11 @@ def fence_gate(self, blockid, data):
pos_bottom_left = (2,7) pos_bottom_left = (2,7)
if data == 0 or data == 2: if data == 0 or data == 2:
composite.alpha_over(img, gate_other_side, pos_top_right, gate_other_side) alpha_over(img, gate_other_side, pos_top_right, gate_other_side)
composite.alpha_over(img, mirror_gate_other_side, pos_bottom_left, mirror_gate_other_side) alpha_over(img, mirror_gate_other_side, pos_bottom_left, mirror_gate_other_side)
elif data == 1 or data == 3: elif data == 1 or data == 3:
composite.alpha_over(img, gate_side, pos_top_left, gate_side) alpha_over(img, gate_side, pos_top_left, gate_side)
composite.alpha_over(img, mirror_gate_side, pos_bottom_right, mirror_gate_side) alpha_over(img, mirror_gate_side, pos_bottom_right, mirror_gate_side)
return img return img
@@ -3094,19 +3004,19 @@ def cauldron(self, blockid, data):
img = self.build_full_block(top, side, side, side, side) img = self.build_full_block(top, side, side, side, side)
if data == 1: # 1/3 filled if data == 1: # 1/3 filled
img = self.build_full_block(None , side, side, None, None) img = self.build_full_block(None , side, side, None, None)
composite.alpha_over(img, water, (0,8), water) alpha_over(img, water, (0,8), water)
img2 = self.build_full_block(top , None, None, side, side) img2 = self.build_full_block(top , None, None, side, side)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
if data == 2: # 2/3 filled if data == 2: # 2/3 filled
img = self.build_full_block(None , side, side, None, None) img = self.build_full_block(None , side, side, None, None)
composite.alpha_over(img, water, (0,4), water) alpha_over(img, water, (0,4), water)
img2 = self.build_full_block(top , None, None, side, side) img2 = self.build_full_block(top , None, None, side, side)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
if data == 3: # 3/3 filled if data == 3: # 3/3 filled
img = self.build_full_block(None , side, side, None, None) img = self.build_full_block(None , side, side, None, None)
composite.alpha_over(img, water, (0,0), water) alpha_over(img, water, (0,0), water)
img2 = self.build_full_block(top , None, None, side, side) img2 = self.build_full_block(top , None, None, side, side)
composite.alpha_over(img, img2, (0,0), img2) alpha_over(img, img2, (0,0), img2)
return img return img
@@ -3123,7 +3033,7 @@ def end_portal(self, blockid, data):
t.putpixel((x,y),color) t.putpixel((x,y),color)
t = self.transform_image_top(t) t = self.transform_image_top(t)
composite.alpha_over(img, t, (0,0), t) alpha_over(img, t, (0,0), t)
return img return img
@@ -3147,9 +3057,9 @@ def end_portal_frame(self, blockid, data):
eye = self.transform_image_top(eye_t) eye = self.transform_image_top(eye_t)
eye_s = self.transform_image_side(eye_t_s) eye_s = self.transform_image_side(eye_t_s)
eye_os = eye_s.transpose(Image.FLIP_LEFT_RIGHT) eye_os = eye_s.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, eye_s, (5,5), eye_s) alpha_over(img, eye_s, (5,5), eye_s)
composite.alpha_over(img, eye_os, (9,5), eye_os) alpha_over(img, eye_os, (9,5), eye_os)
composite.alpha_over(img, eye, (0,0), eye) alpha_over(img, eye, (0,0), eye)
return img return img