TrimColor processor

This commit is contained in:
Matthew Tretter 2011-11-15 23:42:43 -05:00
parent 8c64307e5a
commit cfd503a2eb
2 changed files with 64 additions and 1 deletions

View file

@ -1,7 +1,8 @@
# Required PIL classes may or may not be available from the root namespace
# depending on the installation method used.
try:
from PIL import Image, ImageColor, ImageChops, ImageEnhance, ImageFile, ImageFilter
from PIL import Image, ImageColor, ImageChops, ImageEnhance, ImageFile, \
ImageFilter, ImageDraw, ImageStat
except ImportError:
try:
import Image
@ -10,5 +11,7 @@ except ImportError:
import ImageEnhance
import ImageFile
import ImageFilter
import ImageDraw
import ImageStat
except ImportError:
raise ImportError('ImageKit was unable to import the Python Imaging Library. Please confirm it`s installed and available on your current Python path.')

View file

@ -0,0 +1,60 @@
from ..lib import Image, ImageChops, ImageDraw, ImageStat
class Side(object):
TOP = 't'
RIGHT = 'r'
BOTTOM = 'b'
LEFT = 'l'
ALL = (TOP, RIGHT, BOTTOM, LEFT)
def crop(img, bbox, sides=Side.ALL):
bbox = (
bbox[0] if Side.LEFT in sides else 0,
bbox[1] if Side.TOP in sides else 0,
bbox[2] if Side.RIGHT in sides else img.size[0],
bbox[3] if Side.BOTTOM in sides else img.size[1],
)
return img.crop(bbox)
def detect_border_color(img):
mask = Image.new('1', img.size, 1)
w, h = img.size[0] - 2, img.size[1] - 2
if w > 0 and h > 0:
draw = ImageDraw.Draw(mask)
draw.rectangle([1, 1, w, h], 0)
return ImageStat.Stat(img.convert('RGBA').histogram(mask)).median
class TrimColor(object):
"""Trims a color from the sides of an image.
"""
def __init__(self, color=None, tolerance=0.3, sides=Side.ALL):
"""
:param color: The color to trim from the image, in a 4-tuple RGBA value,
where each component is an integer between 0 and 255, inclusive. If
no color is provided, the processor will attempt to detect the
border color automatically.
:param tolerance: A number between 0 and 1 where 0. Zero is the least
tolerant and one is the most.
:param sides: A list of sides that should be trimmed. Possible values
are provided by the :class:`Side` enum class.
"""
self.color = color
self.sides = sides
self.tolerance = tolerance
def process(self, img):
source = img.convert('RGBA')
border_color = self.color or tuple(detect_border_color(source))
bg = Image.new('RGBA', img.size, border_color)
offset = -int(self.tolerance * 255)
bbox = ImageChops.subtract(bg, source, offset=offset).getbbox()
if bbox:
img = crop(img, bbox, self.sides)
return img