mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +03:00
Merge pull request #364 from wiredfool/premultiply
Alpha Premultiplication support for transform and resize
This commit is contained in:
commit
056690792e
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 },
|
||||
|
|
Loading…
Reference in New Issue
Block a user