Merge pull request #1 from wiredfool/p_rgba_transparency

Tweak for #664
This commit is contained in:
Hugo 2014-05-20 11:20:07 +03:00
commit f8c5812154
2 changed files with 60 additions and 41 deletions

View File

@ -101,7 +101,7 @@ import collections
import numbers
# works everywhere, win for pypy, not cpython
USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info')
USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info')
try:
import cffi
HAS_CFFI=True
@ -233,7 +233,7 @@ _MODE_CONV = {
"CMYK": ('|u1', 4),
"YCbCr": ('|u1', 3),
"LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1
# I;16 == I;16L, and I;32 == I;32L
# I;16 == I;16L, and I;32 == I;32L
"I;16": ('<u2', None),
"I;16B": ('>u2', None),
"I;16L": ('<u2', None),
@ -502,7 +502,7 @@ class Image:
return self
def __exit__(self, *args):
self.close()
def close(self):
"""
Closes the file pointer, if possible.
@ -524,7 +524,7 @@ class Image:
# deferred error that will better explain that the core image
# object is gone.
self.im = deferred_error(ValueError("Operation on closed image"))
def _copy(self):
self.load()
@ -540,7 +540,7 @@ class Image:
if not file:
f, file = tempfile.mkstemp(suffix)
os.close(f)
self.load()
if not format or format == "PPM":
self.im.save_ppm(file)
@ -672,7 +672,7 @@ class Image:
normal cases, you don't need to call this method, since the
Image class automatically loads an opened image when it is
accessed for the first time. This method will close the file
associated with the image.
associated with the image.
:returns: An image access object.
"""
@ -777,7 +777,7 @@ class Image:
if "transparency" in self.info and self.info['transparency'] is not None:
if self.mode in ('L', 'RGB') and mode == 'RGBA':
# Use transparent conversion to promote from transparent
# color to an alpha channel.
# color to an alpha channel.
return self._new(self.im.convert_transparent(
mode, self.info['transparency']))
elif self.mode in ('L', 'RGB', 'P') and mode in ('L', 'RGB', 'P'):
@ -799,11 +799,12 @@ class Image:
trns_im = trns_im.convert(mode)
else:
# can't just retrieve the palette number, got to do it
# after quantization.
# after quantization.
trns_im = trns_im.convert('RGB')
trns = trns_im.getpixel((0,0))
elif self.mode == 'P' and mode == 'RGBA':
delete_trns = True
if mode == "P" and palette == ADAPTIVE:
im = self.im.quantize(colors)
new = self._new(im)
@ -811,7 +812,7 @@ class Image:
new.palette = ImagePalette.raw("RGB", new.im.getpalette("RGB"))
if delete_trns:
# This could possibly happen if we requantize to fewer colors.
# The transparency would be totally off in that case.
# The transparency would be totally off in that case.
del(new.info['transparency'])
if trns is not None:
try:
@ -826,7 +827,7 @@ class Image:
# colorspace conversion
if dither is None:
dither = FLOYDSTEINBERG
try:
im = self.im.convert(mode, dither)
except ValueError:
@ -863,7 +864,7 @@ class Image:
# quantizer interface in a later version of PIL.
self.load()
if method is None:
# defaults:
method = 0
@ -871,10 +872,10 @@ class Image:
method = 2
if self.mode == 'RGBA' and method != 2:
# Caller specified an invalid mode.
# Caller specified an invalid mode.
raise ValueError('Fast Octree (method == 2) is the ' +
' only valid method for quantizing RGBA images')
if palette:
# use palette from reference image
palette.load()
@ -928,7 +929,7 @@ class Image:
def draft(self, mode, size):
"""
NYI
Configures the image file loader so it returns a version of the
image that as closely as possible matches the given mode and
size. For example, you can use this method to convert a color
@ -1277,7 +1278,7 @@ class Image:
if self.mode in ("I", "I;16", "F"):
# check if the function can be used with point_transform
# UNDONE wiredfool -- I think this prevents us from ever doing
# a gamma function point transform on > 8bit images.
# a gamma function point transform on > 8bit images.
scale, offset = _getscaleoffset(lut)
return self._new(self.im.point_transform(scale, offset))
# for other modes, convert the function to a table
@ -1420,8 +1421,8 @@ class Image:
self._copy()
self.pyaccess = None
self.load()
if self.pyaccess:
if self.pyaccess:
return self.pyaccess.putpixel(xy,value)
return self.im.putpixel(xy, value)

View File

@ -2,6 +2,7 @@ from tester import *
from PIL import Image
def test_sanity():
def convert(im, mode):
@ -16,6 +17,7 @@ def test_sanity():
for mode in modes:
yield_test(convert, im, mode)
def test_default():
im = lena("P")
@ -26,26 +28,29 @@ def test_default():
assert_image(im, "RGB", im.size)
# ref https://github.com/python-imaging/Pillow/issues/274
def _test_float_conversion(im):
orig = im.getpixel((5,5))
converted = im.convert('F').getpixel((5,5))
orig = im.getpixel((5, 5))
converted = im.convert('F').getpixel((5, 5))
assert_equal(orig, converted)
def test_8bit():
im = Image.open('Images/lena.jpg')
_test_float_conversion(im.convert('L'))
def test_16bit():
im = Image.open('Tests/images/16bit.cropped.tif')
_test_float_conversion(im)
def test_16bit_workaround():
im = Image.open('Tests/images/16bit.cropped.tif')
_test_float_conversion(im.convert('I'))
def test_rgba_p():
im = lena('RGBA')
im.putalpha(lena('L'))
@ -54,30 +59,45 @@ def test_rgba_p():
comparable = converted.convert('RGBA')
assert_image_similar(im, comparable, 20)
def test_trns_p():
def test_trns_p():
im = lena('P')
im.info['transparency']=0
im.info['transparency'] = 0
f = tempfile('temp.png')
l = im.convert('L')
assert_equal(l.info['transparency'], 0) # undone
assert_equal(l.info['transparency'], 0) # undone
assert_no_exception(lambda: l.save(f))
rgb = im.convert('RGB')
assert_equal(rgb.info['transparency'], (0,0,0)) # undone
assert_equal(rgb.info['transparency'], (0, 0, 0)) # undone
assert_no_exception(lambda: rgb.save(f))
# ref https://github.com/python-imaging/Pillow/issues/664
def test_trns_p_rgba():
# Arrange
im = lena('P')
im.info['transparency'] = 128
# Act
rgba = im.convert('RGBA')
# Assert
assert_false('transparency' in rgba.info)
def test_trns_l():
im = lena('L')
im.info['transparency'] = 128
f = tempfile('temp.png')
rgb = im.convert('RGB')
assert_equal(rgb.info['transparency'], (128,128,128)) # undone
assert_equal(rgb.info['transparency'], (128, 128, 128)) # undone
assert_no_exception(lambda: rgb.save(f))
p = im.convert('P')
@ -85,28 +105,26 @@ def test_trns_l():
assert_no_exception(lambda: p.save(f))
p = assert_warning(UserWarning,
lambda: im.convert('P', palette = Image.ADAPTIVE))
lambda: im.convert('P', palette=Image.ADAPTIVE))
assert_false('transparency' in p.info)
assert_no_exception(lambda: p.save(f))
def test_trns_RGB():
im = lena('RGB')
im.info['transparency'] = im.getpixel((0,0))
im.info['transparency'] = im.getpixel((0, 0))
f = tempfile('temp.png')
l = im.convert('L')
assert_equal(l.info['transparency'], l.getpixel((0,0))) # undone
assert_equal(l.info['transparency'], l.getpixel((0, 0))) # undone
assert_no_exception(lambda: l.save(f))
p = im.convert('P')
assert_true('transparency' in p.info)
assert_no_exception(lambda: p.save(f))
p = assert_warning(UserWarning,
lambda: im.convert('P', palette = Image.ADAPTIVE))
lambda: im.convert('P', palette=Image.ADAPTIVE))
assert_false('transparency' in p.info)
assert_no_exception(lambda: p.save(f))