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:
http://github.com/overviewer/Minecraft-Overviewer
Blog:
http://mcoverviewer.blogspot.com/
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

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
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
.. _customrendermodes:

View File

@@ -6,10 +6,12 @@
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
.. _Updates Blog: http://mcoverviewer.blogspot.com/
Introduction
============
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
: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 the Textures

View File

@@ -101,6 +101,8 @@ def main():
# Parse for basic options
parser = OptionParser(usage=helptext)
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:
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.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:
config = mw_parser.get_validated_config()
except Exception:
@@ -332,7 +340,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# multiprocessing dispatcher
dispatch = dispatcher.MultiprocessingDispatcher()
dispatch = dispatcher.MultiprocessingDispatcher(local_procs=config['processes'])
def print_status(*args):
logging.info("Status callback: %r", args)
dispatch.render_all(tilesets, print_status)

View File

@@ -18,6 +18,8 @@ import os
import codecs
import locale
import time
import logging
from PIL import Image
import world
@@ -46,11 +48,13 @@ directory.
self.POI = dict()
# 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:
overviewerConfig_str = "{" + "\n".join(c.readlines()[1:-1]) + "}"
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())
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
# settingsDefinition.py
self._settings = {}
for settingname in settingsDefinition.__all__:
for settingname in dir(settingsDefinition):
setting = getattr(settingsDefinition, settingname)
assert isinstance(setting, settingsValidators.Setting)
if not isinstance(setting, settingsValidators.Setting):
continue
self._settings[settingname] = setting

View File

@@ -19,6 +19,7 @@ import multiprocessing.managers
import cPickle as pickle
import Queue
import time
import logging
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 *
# 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
# configuration for that render. Therefore, the validator for 'render' is set
# 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)
processes = Setting(required=True, validator=int, default=-1)

View File

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

View File

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

View File

@@ -27,7 +27,7 @@ import logging
import functools
import util
import composite
from c_overviewer import alpha_over
##
## Textures object
@@ -455,7 +455,7 @@ class Textures(object):
top = self.transform_image_top(top)
if not side:
composite.alpha_over(img, top, (0,0), top)
alpha_over(img, top, (0,0), top)
return img
side = self.transform_image_side(side)
@@ -471,9 +471,9 @@ class Textures(object):
otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
otherside.putalpha(othersidealpha)
composite.alpha_over(img, top, (0,0), top)
composite.alpha_over(img, side, (0,6), side)
composite.alpha_over(img, otherside, (12,6), otherside)
alpha_over(img, top, (0,0), top)
alpha_over(img, side, (0,6), side)
alpha_over(img, otherside, (12,6), otherside)
# Manually touch up 6 pixels that leave a gap because of how the
# 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.putalpha(sidealpha)
composite.alpha_over(img, side1, (0,0), side1)
alpha_over(img, side1, (0,0), side1)
if side2 != None :
@@ -550,11 +550,11 @@ class Textures(object):
side2 = ImageEnhance.Brightness(side2).enhance(0.8)
side2.putalpha(sidealpha2)
composite.alpha_over(img, side2, (12,0), side2)
alpha_over(img, side2, (12,0), side2)
if bottom != None :
bottom = self.transform_image_top(bottom)
composite.alpha_over(img, bottom, (0,12), bottom)
alpha_over(img, bottom, (0,12), bottom)
# front sides
if side3 != None :
@@ -565,7 +565,7 @@ class Textures(object):
side3 = ImageEnhance.Brightness(side3).enhance(0.9)
side3.putalpha(sidealpha)
composite.alpha_over(img, side3, (0,6), side3)
alpha_over(img, side3, (0,6), side3)
if side4 != None :
side4 = self.transform_image_side(side4)
@@ -576,11 +576,11 @@ class Textures(object):
side4 = ImageEnhance.Brightness(side4).enhance(0.8)
side4.putalpha(sidealpha)
composite.alpha_over(img, side4, (12,6), side4)
alpha_over(img, side4, (12,6), side4)
if top != None :
top = self.transform_image_top(top)
composite.alpha_over(img, top, (0, increment), top)
alpha_over(img, top, (0, increment), top)
return img
@@ -592,8 +592,8 @@ class Textures(object):
side = self.transform_image_side(side)
otherside = side.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, side, (6,3), side)
composite.alpha_over(img, otherside, (6,3), otherside)
alpha_over(img, side, (6,3), side)
alpha_over(img, otherside, (6,3), otherside)
return img
def build_billboard(self, tex):
@@ -603,7 +603,7 @@ class Textures(object):
img = Image.new("RGBA", (24,24), self.bgcolor)
front = tex.resize((14, 11), Image.ANTIALIAS)
composite.alpha_over(img, front, (5,9))
alpha_over(img, front, (5,9))
return img
def generate_opaque_mask(self, img):
@@ -627,96 +627,6 @@ class Textures(object):
return None
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
##
@@ -840,7 +750,7 @@ def grass(self, blockid, data):
side_img = self.terrain_images[68]
img = self.build_block(self.terrain_images[0], side_img)
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
# dirt
@@ -1124,29 +1034,29 @@ def rails(self, blockid, data):
## use transform_image to scale and shear
if data == 0:
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:
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:
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:
# flip
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:
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:
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
elif data == 2: # slope going up in +x direction
track = self.transform_image_slope(raw_straight)
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
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!
elif data == 4: # slope going up in -y direction
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
# 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)
temp = self.transform_image_side(interior_t)
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
img = self.build_full_block(side_t.rotate(90) ,None ,None , None, side_t.rotate(270))
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
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
h_stick = Image.new("RGBA", (24,24), self.bgcolor)
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))
composite.alpha_over(h_stick, temp, (1,1), temp)
alpha_over(h_stick, temp, (1,1), temp)
# Darken it
sidealpha = h_stick.split()[3]
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
v_stick = Image.new("RGBA", (24,24), self.bgcolor)
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)
composite.alpha_over(v_stick, temp, (1,6), temp)
alpha_over(v_stick, temp, (1,6), temp)
# Darken it
sidealpha = v_stick.split()[3]
v_stick = ImageEnhance.Brightness(v_stick).enhance(0.85)
@@ -1299,32 +1209,32 @@ def piston_extension(self, blockid, data):
if data & 0x07 == 0x0: # down
side_t = side_t.rotate(180)
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
img = Image.new("RGBA", (24,24), self.bgcolor)
img2 = self.build_full_block(piston_t ,None ,None ,side_t, side_t)
composite.alpha_over(img, v_stick, (0,4), v_stick)
composite.alpha_over(img, img2, (0,0), img2)
alpha_over(img, v_stick, (0,4), v_stick)
alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x2: # east
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)
composite.alpha_over(img, temp, (2,2), temp)
composite.alpha_over(img, h_stick, (6,3), h_stick)
alpha_over(img, temp, (2,2), temp)
alpha_over(img, h_stick, (6,3), h_stick)
elif data & 0x07 == 0x3: # west
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)
composite.alpha_over(img, h_stick, (0,0), h_stick)
composite.alpha_over(img, img2, (0,0), img2)
alpha_over(img, h_stick, (0,0), h_stick)
alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x4: # north
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
img = Image.new("RGBA", (24,24), self.bgcolor)
img2 = self.build_full_block(side_t.rotate(270) ,None ,None ,None, side_t.rotate(90))
temp = self.transform_image_side(back_t)
composite.alpha_over(img2, temp, (10,2), temp)
composite.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(img2, temp, (10,2), temp)
alpha_over(img, img2, (0,0), img2)
alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (-3,2), h_stick.transpose(Image.FLIP_LEFT_RIGHT))
return img
@@ -1419,7 +1329,7 @@ def slabs(self, blockid, data):
# cut the side texture in half
mask = side.crop((0,8,16,16))
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
top = self.transform_image_top(top)
@@ -1434,9 +1344,9 @@ def slabs(self, blockid, data):
otherside.putalpha(othersidealpha)
img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, side, (0,12), side)
composite.alpha_over(img, otherside, (12,12), otherside)
composite.alpha_over(img, top, (0,6), top)
alpha_over(img, side, (0,12), side)
alpha_over(img, otherside, (12,12), otherside)
alpha_over(img, top, (0,6), top)
return img
@@ -1482,9 +1392,9 @@ def torches(self, blockid, data):
# compose a torch bigger than the normal
# (better for doing transformations)
torch = Image.new("RGBA", (16,16), self.bgcolor)
composite.alpha_over(torch,small,(-4,-3))
composite.alpha_over(torch,small,(-5,-2))
composite.alpha_over(torch,small,(-3,-2))
alpha_over(torch,small,(-4,-3))
alpha_over(torch,small,(-5,-2))
alpha_over(torch,small,(-3,-2))
# angle of inclination of the texture
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((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0))
composite.alpha_over(img, slice, (7,5))
composite.alpha_over(img, small_crop, (6,6))
composite.alpha_over(img, small_crop, (7,6))
composite.alpha_over(img, slice, (7,7))
alpha_over(img, slice, (7,5))
alpha_over(img, small_crop, (6,6))
alpha_over(img, small_crop, (7,6))
alpha_over(img, slice, (7,7))
return img
@@ -1530,11 +1440,11 @@ def fire(self, blockid, data):
img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, side1, (12,0), side1)
composite.alpha_over(img, side2, (0,0), side2)
alpha_over(img, side1, (12,0), side1)
alpha_over(img, side2, (0,0), side2)
composite.alpha_over(img, side1, (0,6), side1)
composite.alpha_over(img, side2, (12,6), side2)
alpha_over(img, side1, (0,6), side1)
alpha_over(img, side2, (12,6), side2)
return img
@@ -1596,24 +1506,24 @@ def stairs(self, blockid, data):
tmp1 = ImageEnhance.Brightness(tmp1).enhance(0.8)
tmp1.putalpha(sidealpha)
composite.alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
composite.alpha_over(img, tmp1, (6,3))
alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
alpha_over(img, tmp1, (6,3))
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
img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back
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)
composite.alpha_over(img, tmp2)
alpha_over(img, tmp2)
elif data == 2: # ascending west
img = Image.new("RGBA", (24,24), self.bgcolor) # first paste the texture in the back
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)
composite.alpha_over(img, tmp2)
alpha_over(img, tmp2)
elif data == 3: # ascending east
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.putalpha(sidealpha)
composite.alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
composite.alpha_over(img, tmp1, (6,3))
alpha_over(img, tmp1, (6,4)) #workaround, fixes a hole
alpha_over(img, tmp1, (6,3))
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
img.putpixel((18,3),(0,0,0,0))
@@ -1736,16 +1646,16 @@ def wire(self, blockid, data):
else:
bottom = Image.new("RGBA", (16,16), self.bgcolor)
if (data & 0b0001) == 1:
composite.alpha_over(bottom,branch_top_left)
alpha_over(bottom,branch_top_left)
if (data & 0b1000) == 8:
composite.alpha_over(bottom,branch_top_right)
alpha_over(bottom,branch_top_right)
if (data & 0b0010) == 2:
composite.alpha_over(bottom,branch_bottom_left)
alpha_over(bottom,branch_bottom_left)
if (data & 0b0100) == 4:
composite.alpha_over(bottom,branch_bottom_right)
alpha_over(bottom,branch_bottom_right)
# check for going up redstone wire
if data & 0b100000 == 32:
@@ -1787,9 +1697,9 @@ def crops(self, blockid, data):
crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT)
img = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(img, crop1, (0,12), crop1)
composite.alpha_over(img, crop2, (6,3), crop2)
composite.alpha_over(img, crop3, (6,3), crop3)
alpha_over(img, crop1, (0,12), crop1)
alpha_over(img, crop2, (6,3), crop2)
alpha_over(img, crop3, (6,3), crop3)
return img
# farmland
@@ -1843,12 +1753,12 @@ def signpost(self, blockid, data):
elif data in (3,4,5,11,12,13):
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,
# gives to the signpost some 3D effect.
post2 = ImageEnhance.Brightness(post).enhance(1.2)
composite.alpha_over(img, post2,(incrementx, -3),post2)
composite.alpha_over(img, post, (0,-2), post)
alpha_over(img, post2,(incrementx, -3),post2)
alpha_over(img, post, (0,-2), post)
return img
@@ -1890,36 +1800,36 @@ def door(self, blockid, data):
if (data & 0x03) == 0: # northeast corner
if not swung:
tex = self.transform_image_side(raw_door)
composite.alpha_over(img, tex, (0,6), tex)
alpha_over(img, tex, (0,6), tex)
else:
# flip first to set the doornob on the correct side
tex = self.transform_image_side(raw_door.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 not swung:
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:
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 not swung:
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:
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 not swung:
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:
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
@@ -1952,19 +1862,19 @@ def ladder(self, blockid, data):
# but since ladders can apparently be placed on transparent blocks, we
# have to render this thing anyway. same for data == 2
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)
if data == 2:
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)
if data == 3:
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)
if data == 4:
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)
@@ -2020,8 +1930,8 @@ def wall_sign(self, blockid, data): # wall sign
sign = self.build_full_block(None, None, None, texture, None)
sign2 = ImageEnhance.Brightness(sign).enhance(1.2)
composite.alpha_over(img, sign2,(incrementx, 2),sign2)
composite.alpha_over(img, sign, (0,3), sign)
alpha_over(img, sign2,(incrementx, 2),sign2)
alpha_over(img, sign, (0,3), sign)
return img
@@ -2071,8 +1981,8 @@ def levers(self, blockid, data):
c_stick = Image.new("RGBA", (16,16), self.bgcolor)
tmp = ImageEnhance.Brightness(stick).enhance(0.8)
composite.alpha_over(c_stick, tmp, (1,0), tmp)
composite.alpha_over(c_stick, stick, (0,0), stick)
alpha_over(c_stick, tmp, (1,0), tmp)
alpha_over(c_stick, stick, (0,0), stick)
t_stick = self.transform_image_side(c_stick.rotate(45, Image.NEAREST))
# where the lever will be composed
@@ -2088,33 +1998,33 @@ def levers(self, blockid, data):
base = self.transform_image_side(t_base)
# 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]
base = ImageEnhance.Brightness(base).enhance(0.9)
base.putalpha(alpha)
composite.alpha_over(img, base, (11,0), base)
alpha_over(img, base, (11,0), base)
# paste the lever stick
pos = (7,-7)
if powered:
t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM)
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
base = self.transform_image_side(t_base)
# paste it twice with different brightness to make a fake 3D effect
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]
base = ImageEnhance.Brightness(base).enhance(0.9)
base.putalpha(alpha)
composite.alpha_over(img, base, (1,0), base)
alpha_over(img, base, (1,0), base)
# paste the lever stick
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
@@ -2122,7 +2032,7 @@ def levers(self, blockid, data):
if powered:
t_stick = t_stick.transpose(Image.FLIP_TOP_BOTTOM)
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
# 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.putalpha(alpha)
composite.alpha_over(img, tmp, (0,12), tmp)
composite.alpha_over(img, base, (0,11), base)
alpha_over(img, tmp, (0,12), tmp)
alpha_over(img, base, (0,11), base)
# lever stick
pos = (3,2)
if not powered:
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
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
# lever base, fake 3d again
@@ -2156,15 +2066,15 @@ def levers(self, blockid, data):
tmp = ImageEnhance.Brightness(base).enhance(0.8)
tmp.putalpha(alpha)
composite.alpha_over(img, tmp, (0,12), tmp)
composite.alpha_over(img, base, (0,11), base)
alpha_over(img, tmp, (0,12), tmp)
alpha_over(img, base, (0,11), base)
# lever stick
pos = (2,3)
if not powered:
t_stick = t_stick.transpose(Image.FLIP_LEFT_RIGHT)
pos = (10,2)
composite.alpha_over(img, t_stick, pos, t_stick)
alpha_over(img, t_stick, pos, t_stick)
return img
@@ -2192,10 +2102,10 @@ def pressure_plate(self, blockid, data):
#show it 3d or 2d if unpressed or pressed
if data == 0:
composite.alpha_over(img,topd, (0,12),topd)
composite.alpha_over(img,top, (0,11),top)
alpha_over(img,topd, (0,12),topd)
alpha_over(img,top, (0,11),top)
elif data == 1:
composite.alpha_over(img,top, (0,12),top)
alpha_over(img,top, (0,12),top)
return img
@@ -2244,24 +2154,24 @@ def buttons(self, blockid, data):
elif data == 2: # facing NORTH
# 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]
button = ImageEnhance.Brightness(button).enhance(0.9)
button.putalpha(alpha)
composite.alpha_over(img, button, (11,0), button)
alpha_over(img, button, (11,0), button)
elif data == 3: # facing WEST
# paste it twice with different brightness to make a 3D effect
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]
button = ImageEnhance.Brightness(button).enhance(0.9)
button.putalpha(alpha)
composite.alpha_over(img, button, (1,0), button)
alpha_over(img, button, (1,0), button)
elif data == 4: # facing EAST
# 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
mask = tex.crop((0,12,16,16))
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)
@@ -2288,9 +2198,9 @@ def snow(self, blockid, data):
side = self.transform_image_side(sidetex)
otherside = side.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, side, (0,6), side)
composite.alpha_over(img, otherside, (12,6), otherside)
composite.alpha_over(img, top, (0,9), top)
alpha_over(img, side, (0,6), side)
alpha_over(img, otherside, (12,6), otherside)
alpha_over(img, top, (0,9), top)
return img
@@ -2316,9 +2226,9 @@ def cactus(self, blockid, data):
otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
otherside.putalpha(othersidealpha)
composite.alpha_over(img, side, (1,6), side)
composite.alpha_over(img, otherside, (11,6), otherside)
composite.alpha_over(img, top, (0,0), top)
alpha_over(img, side, (1,6), side)
alpha_over(img, otherside, (11,6), otherside)
alpha_over(img, top, (0,0), top)
return img
@@ -2377,9 +2287,9 @@ def fence(self, blockid, data):
# Compose the fence big stick
fence_big = Image.new("RGBA", (24,24), self.bgcolor)
composite.alpha_over(fence_big,fence_side, (5,4),fence_side)
composite.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_side, (5,4),fence_side)
alpha_over(fence_big,fence_other_side, (7,4),fence_other_side)
alpha_over(fence_big,fence_top, (0,0),fence_top)
# Now render the small sticks.
# Create needed images
@@ -2420,16 +2330,16 @@ def fence(self, blockid, data):
# then big stick and thecn small sticks in the front.
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:
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:
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:
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
@@ -2490,10 +2400,10 @@ def portal(self, blockid, data):
otherside = side.transpose(Image.FLIP_TOP_BOTTOM)
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):
composite.alpha_over(img, otherside, (5,4), otherside)
alpha_over(img, otherside, (5,4), otherside)
return img
@@ -2520,10 +2430,10 @@ def cake(self, blockid, data):
img = Image.new("RGBA", (24,24), self.bgcolor)
# composite the cake
composite.alpha_over(img, side, (1,6), side)
composite.alpha_over(img, otherside, (11,7), otherside) # workaround, fixes a hole
composite.alpha_over(img, otherside, (12,6), otherside)
composite.alpha_over(img, top, (0,6), top)
alpha_over(img, side, (1,6), side)
alpha_over(img, otherside, (11,7), otherside) # workaround, fixes a hole
alpha_over(img, otherside, (12,6), otherside)
alpha_over(img, top, (0,6), top)
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((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0))
composite.alpha_over(torch, slice, (6,4))
composite.alpha_over(torch, t_crop, (5,5))
composite.alpha_over(torch, t_crop, (6,5))
composite.alpha_over(torch, slice, (6,6))
alpha_over(torch, slice, (6,4))
alpha_over(torch, t_crop, (5,5))
alpha_over(torch, t_crop, (6,5))
alpha_over(torch, slice, (6,6))
# paste redstone torches everywhere!
# 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
# but it's wrong for north and west orientations. But using the
# default texture pack the torches are small enough to no overlap.
composite.alpha_over(img, torch, static_torch, torch)
composite.alpha_over(img, torch, moving_torch, torch)
alpha_over(img, torch, static_torch, torch)
alpha_over(img, torch, moving_torch, torch)
return img
@@ -2849,13 +2759,13 @@ def panes(self, blockid, data):
# then things in the front.
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:
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:
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:
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
@@ -2875,7 +2785,7 @@ def stem(self, blockid, data):
# straight up stem
t = self.terrain_images[111].copy()
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)
if data & 7 == 7:
# fully grown stem gets brown color!
@@ -2981,17 +2891,17 @@ def fence_gate(self, blockid, data):
# opened
data = data & 0x3
if data == 0:
composite.alpha_over(img, gate_side, (2,8), gate_side)
composite.alpha_over(img, gate_side, (13,3), gate_side)
alpha_over(img, gate_side, (2,8), gate_side)
alpha_over(img, gate_side, (13,3), gate_side)
elif data == 1:
composite.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, (-1,3), gate_other_side)
alpha_over(img, gate_other_side, (10,8), gate_other_side)
elif data == 2:
composite.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, (-1,7), mirror_gate_side)
alpha_over(img, mirror_gate_side, (10,2), mirror_gate_side)
elif data == 3:
composite.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, (2,1), mirror_gate_other_side)
alpha_over(img, mirror_gate_other_side, (13,7), mirror_gate_other_side)
else:
# closed
@@ -3002,11 +2912,11 @@ def fence_gate(self, blockid, data):
pos_bottom_left = (2,7)
if data == 0 or data == 2:
composite.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, gate_other_side, pos_top_right, gate_other_side)
alpha_over(img, mirror_gate_other_side, pos_bottom_left, mirror_gate_other_side)
elif data == 1 or data == 3:
composite.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, gate_side, pos_top_left, gate_side)
alpha_over(img, mirror_gate_side, pos_bottom_right, mirror_gate_side)
return img
@@ -3094,19 +3004,19 @@ def cauldron(self, blockid, data):
img = self.build_full_block(top, side, side, side, side)
if data == 1: # 1/3 filled
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)
composite.alpha_over(img, img2, (0,0), img2)
alpha_over(img, img2, (0,0), img2)
if data == 2: # 2/3 filled
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)
composite.alpha_over(img, img2, (0,0), img2)
alpha_over(img, img2, (0,0), img2)
if data == 3: # 3/3 filled
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)
composite.alpha_over(img, img2, (0,0), img2)
alpha_over(img, img2, (0,0), img2)
return img
@@ -3123,7 +3033,7 @@ def end_portal(self, blockid, data):
t.putpixel((x,y),color)
t = self.transform_image_top(t)
composite.alpha_over(img, t, (0,0), t)
alpha_over(img, t, (0,0), t)
return img
@@ -3147,9 +3057,9 @@ def end_portal_frame(self, blockid, data):
eye = self.transform_image_top(eye_t)
eye_s = self.transform_image_side(eye_t_s)
eye_os = eye_s.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, eye_s, (5,5), eye_s)
composite.alpha_over(img, eye_os, (9,5), eye_os)
composite.alpha_over(img, eye, (0,0), eye)
alpha_over(img, eye_s, (5,5), eye_s)
alpha_over(img, eye_os, (9,5), eye_os)
alpha_over(img, eye, (0,0), eye)
return img