Merge pull request #364 from wiredfool/premultiply

Alpha Premultiplication support for transform and resize
This commit is contained in:
Alex Clark ☺ 2013-10-07 06:38:11 -07:00
commit 056690792e
3 changed files with 69 additions and 1 deletions

View File

@ -1309,6 +1309,9 @@ class Image:
if self.mode in ("1", "P"):
resample = NEAREST
if self.mode == 'RGBA':
return self.convert('RGBa').resize(size, resample).convert('RGBA')
if resample == ANTIALIAS:
# requires stretch support (imToolkit & PIL 1.1.3)
try:
@ -1606,6 +1609,9 @@ class Image:
:returns: An Image object.
"""
if self.mode == 'RGBA':
return self.convert('RGBa').transform(size, method, data, resample, fill).convert('RGBA')
if isinstance(method, ImageTransformHandler):
return method.transform(size, self, resample=resample, fill=fill)
if hasattr(method, "getdata"):
@ -1613,6 +1619,7 @@ class Image:
method, data = method.getdata()
if data is None:
raise ValueError("missing method data")
im = new(self.mode, size, None)
if method == MESH:
# list of quads
@ -1620,7 +1627,7 @@ class Image:
im.__transformer(box, self, QUAD, quad, resample, fill)
else:
im.__transformer((0, 0)+size, self, method, data, resample, fill)
return im
def __transformer(self, box, image, method, data,

View File

@ -57,6 +57,40 @@ def test_mesh():
assert_image_equal(blank, transformed.crop((w//2,0,w,h//2)))
assert_image_equal(blank, transformed.crop((0,h//2,w//2,h)))
def _test_alpha_premult(op):
# create image with half white, half black, with the black half transparent.
# do op,
# there should be no darkness in the white section.
im = Image.new('RGBA', (10,10), (0,0,0,0));
im2 = Image.new('RGBA', (5,10), (255,255,255,255));
im.paste(im2, (0,0))
im = op(im, (40,10))
im_background = Image.new('RGB', (40,10), (255,255,255))
im_background.paste(im, (0,0), im)
hist = im_background.histogram()
assert_equal(40*10, hist[-1])
def test_alpha_premult_resize():
def op (im, sz):
return im.resize(sz, Image.LINEAR)
_test_alpha_premult(op)
def test_alpha_premult_transform():
def op(im, sz):
(w,h) = im.size
return im.transform(sz, Image.EXTENT,
(0,0,
w,h),
Image.BILINEAR)
_test_alpha_premult(op)
def test_blank_fill():
# attempting to hit

View File

@ -289,6 +289,31 @@ rgba2rgba(UINT8* out, const UINT8* in, int xsize)
}
}
/* RGBa -> RGBA conversion to remove premultiplication
Needed for correct transforms/resizing on RGBA images */
static void
rgba2rgbA(UINT8* out, const UINT8* in, int xsize)
{
int x;
unsigned int alpha;
for (x = 0; x < xsize; x++, in+=4) {
alpha = in[3];
if (alpha) {
*out++ = CLIP((255 * in[0]) / alpha);
*out++ = CLIP((255 * in[1]) / alpha);
*out++ = CLIP((255 * in[2]) / alpha);
} else {
*out++ = in[0];
*out++ = in[1];
*out++ = in[2];
}
*out++ = in[3];
}
}
/* ---------------- */
/* CMYK conversions */
/* ---------------- */
@ -619,6 +644,8 @@ static struct {
{ "RGBA", "CMYK", rgb2cmyk },
{ "RGBA", "YCbCr", ImagingConvertRGB2YCbCr },
{ "RGBa", "RGBA", rgba2rgbA },
{ "RGBX", "1", rgb2bit },
{ "RGBX", "L", rgb2l },
{ "RGBA", "I", rgb2i },