changed most PIL paste() calls into composite.alpha_over() calls
The ones I have not changed are those where paste() is really preferred, and I've noted why in comments. Calls to "dest.paste(src, rect, mask)" were converted to calls to "composite.alpha_over(dest, src, rect, mask)".
This commit is contained in:
23
chunk.py
23
chunk.py
@@ -22,6 +22,7 @@ import logging
|
|||||||
import nbt
|
import nbt
|
||||||
import textures
|
import textures
|
||||||
import world
|
import world
|
||||||
|
import composite
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This module has routines related to rendering one particular chunk into an
|
This module has routines related to rendering one particular chunk into an
|
||||||
@@ -36,7 +37,11 @@ image
|
|||||||
# of the dest image will have its alpha channel modified. To prevent this:
|
# of the dest image will have its alpha channel modified. To prevent this:
|
||||||
# first use im.split() and take the third item which is the alpha channel and
|
# first use im.split() and take the third item which is the alpha channel and
|
||||||
# use that as the mask. Then take the image and use im.convert("RGB") to strip
|
# use that as the mask. Then take the image and use im.convert("RGB") to strip
|
||||||
# the image from its alpha channel, and use that as the source to paste()
|
# the image from its alpha channel, and use that as the source to alpha_over()
|
||||||
|
|
||||||
|
# (note that this workaround is NOT technically needed when using the
|
||||||
|
# alpha_over extension, BUT this extension may fall back to PIL's
|
||||||
|
# paste(), which DOES need the workaround.)
|
||||||
|
|
||||||
def get_lvldata(filename):
|
def get_lvldata(filename):
|
||||||
"""Takes a filename and returns the Level struct, which contains all the
|
"""Takes a filename and returns the Level struct, which contains all the
|
||||||
@@ -556,36 +561,36 @@ class ChunkRenderer(object):
|
|||||||
# tint the block with a color proportional to its depth
|
# tint the block with a color proportional to its depth
|
||||||
if cave:
|
if cave:
|
||||||
# no lighting for cave -- depth is probably more useful
|
# no lighting for cave -- depth is probably more useful
|
||||||
img.paste(Image.blend(t[0],depth_colors[z],0.3), (imgx, imgy), t[1])
|
composite.alpha_over(img, Image.blend(t[0],depth_colors[z],0.3), (imgx, imgy), t[1])
|
||||||
else:
|
else:
|
||||||
if not self.world.lighting:
|
if not self.world.lighting:
|
||||||
# no lighting at all
|
# no lighting at all
|
||||||
img.paste(t[0], (imgx, imgy), t[1])
|
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
|
||||||
elif blockid in transparent_blocks:
|
elif blockid in transparent_blocks:
|
||||||
# transparent means draw the whole
|
# transparent means draw the whole
|
||||||
# block shaded with the current
|
# block shaded with the current
|
||||||
# block's light
|
# block's light
|
||||||
black_coeff, _ = self.get_lighting_coefficient(x, y, z)
|
black_coeff, _ = self.get_lighting_coefficient(x, y, z)
|
||||||
img.paste(Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
|
composite.alpha_over(img, Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
|
||||||
else:
|
else:
|
||||||
# draw each face lit appropriately,
|
# draw each face lit appropriately,
|
||||||
# but first just draw the block
|
# but first just draw the block
|
||||||
img.paste(t[0], (imgx, imgy), t[1])
|
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
|
||||||
|
|
||||||
# top face
|
# top face
|
||||||
black_coeff, face_occlude = self.get_lighting_coefficient(x, y, z + 1)
|
black_coeff, face_occlude = self.get_lighting_coefficient(x, y, z + 1)
|
||||||
if not face_occlude:
|
if not face_occlude:
|
||||||
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
|
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
|
||||||
|
|
||||||
# left face
|
# left face
|
||||||
black_coeff, face_occlude = self.get_lighting_coefficient(x - 1, y, z)
|
black_coeff, face_occlude = self.get_lighting_coefficient(x - 1, y, z)
|
||||||
if not face_occlude:
|
if not face_occlude:
|
||||||
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
|
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
|
||||||
|
|
||||||
# right face
|
# right face
|
||||||
black_coeff, face_occlude = self.get_lighting_coefficient(x, y + 1, z)
|
black_coeff, face_occlude = self.get_lighting_coefficient(x, y + 1, z)
|
||||||
if not face_occlude:
|
if not face_occlude:
|
||||||
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
|
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
|
||||||
|
|
||||||
# Draw edge lines
|
# Draw edge lines
|
||||||
if blockid in (44,): # step block
|
if blockid in (44,): # step block
|
||||||
@@ -616,6 +621,8 @@ def generate_facemasks():
|
|||||||
toppart = textures.transform_image(white)
|
toppart = textures.transform_image(white)
|
||||||
leftpart = textures.transform_image_side(white)
|
leftpart = textures.transform_image_side(white)
|
||||||
|
|
||||||
|
# using the real PIL paste here (not alpha_over) because there is
|
||||||
|
# no alpha channel (and it's mode "L")
|
||||||
top.paste(toppart, (0,0))
|
top.paste(toppart, (0,0))
|
||||||
left.paste(leftpart, (0,6))
|
left.paste(leftpart, (0,6))
|
||||||
right = left.transpose(Image.FLIP_LEFT_RIGHT)
|
right = left.transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import util
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from optimizeimages import optimize_image
|
from optimizeimages import optimize_image
|
||||||
|
import composite
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -450,6 +451,9 @@ def render_innertile(dest, name, imgformat, optimizeimg):
|
|||||||
# Create the actual image now
|
# Create the actual image now
|
||||||
img = Image.new("RGBA", (384, 384), (38,92,255,0))
|
img = Image.new("RGBA", (384, 384), (38,92,255,0))
|
||||||
|
|
||||||
|
# we'll use paste (NOT alpha_over) for quadtree generation because
|
||||||
|
# this is just straight image stitching, not alpha blending
|
||||||
|
|
||||||
if q0path:
|
if q0path:
|
||||||
try:
|
try:
|
||||||
quad0 = Image.open(q0path).resize((192,192), Image.ANTIALIAS)
|
quad0 = Image.open(q0path).resize((192,192), Image.ANTIALIAS)
|
||||||
@@ -613,7 +617,7 @@ def render_worldtile(chunks, colstart, colend, rowstart, rowend, path, imgformat
|
|||||||
xpos = -192 + (col-colstart)*192
|
xpos = -192 + (col-colstart)*192
|
||||||
ypos = -96 + (row-rowstart)*96
|
ypos = -96 + (row-rowstart)*96
|
||||||
|
|
||||||
tileimg.paste(chunkimg.convert("RGB"), (xpos, ypos), chunkimg)
|
composite.alpha_over(tileimg, chunkimg.convert("RGB"), (xpos, ypos), chunkimg)
|
||||||
|
|
||||||
# Save them
|
# Save them
|
||||||
tileimg.save(imgpath)
|
tileimg.save(imgpath)
|
||||||
|
|||||||
79
textures.py
79
textures.py
@@ -24,6 +24,7 @@ import numpy
|
|||||||
from PIL import Image, ImageEnhance
|
from PIL import Image, ImageEnhance
|
||||||
|
|
||||||
import util
|
import util
|
||||||
|
import composite
|
||||||
|
|
||||||
def _find_file(filename, mode="rb"):
|
def _find_file(filename, mode="rb"):
|
||||||
"""Searches for the given file and returns an open handle to it.
|
"""Searches for the given file and returns an open handle to it.
|
||||||
@@ -157,13 +158,13 @@ def transform_image_side(img, blockID=None):
|
|||||||
# img to be unchanged
|
# img to be unchanged
|
||||||
mask = img.crop((0,8,16,16))
|
mask = img.crop((0,8,16,16))
|
||||||
n = Image.new(img.mode, img.size, (38,92,255,0))
|
n = Image.new(img.mode, img.size, (38,92,255,0))
|
||||||
n.paste(mask,(0,0,16,8), mask)
|
composite.alpha_over(n, mask,(0,0,16,8), mask)
|
||||||
img = n
|
img = n
|
||||||
if blockID in (78,): # snow
|
if blockID in (78,): # snow
|
||||||
# make the top three quarters transparent
|
# make the top three quarters transparent
|
||||||
mask = img.crop((0,12,16,16))
|
mask = img.crop((0,12,16,16))
|
||||||
n = Image.new(img.mode, img.size, (38,92,255,0))
|
n = Image.new(img.mode, img.size, (38,92,255,0))
|
||||||
n.paste(mask,(0,12,16,16), mask)
|
composite.alpha_over(n, mask,(0,12,16,16), mask)
|
||||||
img = n
|
img = n
|
||||||
|
|
||||||
# Size of the cube side before shear
|
# Size of the cube side before shear
|
||||||
@@ -189,7 +190,7 @@ def _build_block(top, side, blockID=None):
|
|||||||
top = transform_image(top, blockID)
|
top = transform_image(top, blockID)
|
||||||
|
|
||||||
if not side:
|
if not side:
|
||||||
img.paste(top, (0,0), top)
|
composite.alpha_over(img, top, (0,0), top)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
side = transform_image_side(side, blockID)
|
side = transform_image_side(side, blockID)
|
||||||
@@ -212,29 +213,29 @@ def _build_block(top, side, blockID=None):
|
|||||||
if blockID in (37,38,6,39,40,50,83): ## flowers, sapling, mushrooms, regular torch, reeds
|
if blockID in (37,38,6,39,40,50,83): ## flowers, sapling, mushrooms, regular torch, reeds
|
||||||
# instead of pasting these blocks at the cube edges, place them in the middle:
|
# instead of pasting these blocks at the cube edges, place them in the middle:
|
||||||
# and omit the top
|
# and omit the top
|
||||||
img.paste(side, (6,3), side)
|
composite.alpha_over(img, side, (6,3), side)
|
||||||
img.paste(otherside, (6,3), otherside)
|
composite.alpha_over(img, otherside, (6,3), otherside)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
if blockID in (81,): # cacti!
|
if blockID in (81,): # cacti!
|
||||||
img.paste(side, (2,6), side)
|
composite.alpha_over(img, side, (2,6), side)
|
||||||
img.paste(otherside, (10,6), otherside)
|
composite.alpha_over(img, otherside, (10,6), otherside)
|
||||||
img.paste(top, (0,2), top)
|
composite.alpha_over(img, top, (0,2), top)
|
||||||
elif blockID in (44,): # half step
|
elif blockID in (44,): # half step
|
||||||
# shift each texture down 6 pixels
|
# shift each texture down 6 pixels
|
||||||
img.paste(side, (0,12), side)
|
composite.alpha_over(img, side, (0,12), side)
|
||||||
img.paste(otherside, (12,12), otherside)
|
composite.alpha_over(img, otherside, (12,12), otherside)
|
||||||
img.paste(top, (0,6), top)
|
composite.alpha_over(img, top, (0,6), top)
|
||||||
elif blockID in (78,): # snow
|
elif blockID in (78,): # snow
|
||||||
# shift each texture down 9 pixels
|
# shift each texture down 9 pixels
|
||||||
img.paste(side, (0,6), side)
|
composite.alpha_over(img, side, (0,6), side)
|
||||||
img.paste(otherside, (12,6), otherside)
|
composite.alpha_over(img, otherside, (12,6), otherside)
|
||||||
img.paste(top, (0,9), top)
|
composite.alpha_over(img, top, (0,9), top)
|
||||||
else:
|
else:
|
||||||
img.paste(side, (0,6), side)
|
composite.alpha_over(img, side, (0,6), side)
|
||||||
img.paste(otherside, (12,6), otherside)
|
composite.alpha_over(img, otherside, (12,6), otherside)
|
||||||
img.paste(top, (0,0), top)
|
composite.alpha_over(img, top, (0,0), top)
|
||||||
|
|
||||||
# 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
|
||||||
@@ -366,7 +367,7 @@ def generate_special_texture(blockID, data):
|
|||||||
track = transform_image(raw_straight, blockID)
|
track = transform_image(raw_straight, blockID)
|
||||||
|
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(track, (0,12), track)
|
composite.alpha_over(img, track, (0,12), track)
|
||||||
|
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
if blockID == 59: # crops
|
if blockID == 59: # crops
|
||||||
@@ -376,9 +377,9 @@ def generate_special_texture(blockID, data):
|
|||||||
crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT)
|
crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
|
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(crop1, (0,12), crop1)
|
composite.alpha_over(img, crop1, (0,12), crop1)
|
||||||
img.paste(crop2, (6,3), crop2)
|
composite.alpha_over(img, crop2, (6,3), crop2)
|
||||||
img.paste(crop3, (6,3), crop3)
|
composite.alpha_over(img, crop3, (6,3), crop3)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
|
|
||||||
if blockID == 61: #furnace
|
if blockID == 61: #furnace
|
||||||
@@ -388,9 +389,9 @@ def generate_special_texture(blockID, data):
|
|||||||
|
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
|
|
||||||
img.paste(side1, (0,6), side1)
|
composite.alpha_over(img, side1, (0,6), side1)
|
||||||
img.paste(side2, (12,6), side2)
|
composite.alpha_over(img, side2, (12,6), side2)
|
||||||
img.paste(top, (0,0), top)
|
composite.alpha_over(img, top, (0,0), top)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
|
|
||||||
if blockID == 62: # lit furnace
|
if blockID == 62: # lit furnace
|
||||||
@@ -400,9 +401,9 @@ def generate_special_texture(blockID, data):
|
|||||||
|
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
|
|
||||||
img.paste(side1, (0,6), side1)
|
composite.alpha_over(img, side1, (0,6), side1)
|
||||||
img.paste(side2, (12,6), side2)
|
composite.alpha_over(img, side2, (12,6), side2)
|
||||||
img.paste(top, (0,0), top)
|
composite.alpha_over(img, top, (0,0), top)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
|
|
||||||
if blockID == 65: # ladder
|
if blockID == 65: # ladder
|
||||||
@@ -414,22 +415,22 @@ def generate_special_texture(blockID, data):
|
|||||||
# 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)
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(tex, (0,6), tex)
|
composite.alpha_over(img, tex, (0,6), tex)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
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)
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(tex, (12,6), tex)
|
composite.alpha_over(img, tex, (12,6), tex)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
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)
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(tex, (0,0), tex)
|
composite.alpha_over(img, tex, (0,0), tex)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
if data == 4:
|
if data == 4:
|
||||||
tex = transform_image_side(raw_texture)
|
tex = transform_image_side(raw_texture)
|
||||||
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
img = Image.new("RGBA", (24,24), (38,92,255,0))
|
||||||
img.paste(tex, (12,0), tex)
|
composite.alpha_over(img, tex, (12,0), tex)
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
|
|
||||||
if blockID in (64,71): #wooden door, or iron door
|
if blockID in (64,71): #wooden door, or iron door
|
||||||
@@ -450,36 +451,36 @@ def generate_special_texture(blockID, data):
|
|||||||
if (data & 0x03) == 0:
|
if (data & 0x03) == 0:
|
||||||
if not swung:
|
if not swung:
|
||||||
tex = transform_image_side(raw_door)
|
tex = transform_image_side(raw_door)
|
||||||
img.paste(tex, (0,6), tex)
|
composite.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 = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
||||||
tex = tex.transpose(Image.FLIP_LEFT_RIGHT)
|
tex = tex.transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
img.paste(tex, (0,0), tex)
|
composite.alpha_over(img, tex, (0,0), tex)
|
||||||
|
|
||||||
if (data & 0x03) == 1:
|
if (data & 0x03) == 1:
|
||||||
if not swung:
|
if not swung:
|
||||||
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
|
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
img.paste(tex, (0,0), tex)
|
composite.alpha_over(img, tex, (0,0), tex)
|
||||||
else:
|
else:
|
||||||
tex = transform_image_side(raw_door)
|
tex = transform_image_side(raw_door)
|
||||||
img.paste(tex, (12,0), tex)
|
composite.alpha_over(img, tex, (12,0), tex)
|
||||||
|
|
||||||
if (data & 0x03) == 2:
|
if (data & 0x03) == 2:
|
||||||
if not swung:
|
if not swung:
|
||||||
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
||||||
img.paste(tex, (12,0), tex)
|
composite.alpha_over(img, tex, (12,0), tex)
|
||||||
else:
|
else:
|
||||||
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
|
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
img.paste(tex, (12,6), tex)
|
composite.alpha_over(img, tex, (12,6), tex)
|
||||||
|
|
||||||
if (data & 0x03) == 3:
|
if (data & 0x03) == 3:
|
||||||
if not swung:
|
if not swung:
|
||||||
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT)
|
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT)
|
||||||
img.paste(tex, (12,6), tex)
|
composite.alpha_over(img, tex, (12,6), tex)
|
||||||
else:
|
else:
|
||||||
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
|
||||||
img.paste(tex, (0,6), tex)
|
composite.alpha_over(img, tex, (0,6), tex)
|
||||||
|
|
||||||
return (img.convert("RGB"), img.split()[3])
|
return (img.convert("RGB"), img.split()[3])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user