mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
Merge pull request #2661 from uploadcare/get-channel
New Image.getchannel method
This commit is contained in:
commit
e2602452f4
25
PIL/Image.py
25
PIL/Image.py
|
@ -1948,6 +1948,9 @@ class Image(object):
|
|||
containing a copy of one of the original bands (red, green,
|
||||
blue).
|
||||
|
||||
If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
|
||||
method can be more convenient and faster.
|
||||
|
||||
:returns: A tuple containing bands.
|
||||
"""
|
||||
|
||||
|
@ -1960,6 +1963,28 @@ class Image(object):
|
|||
ims.append(self._new(self.im.getband(i)))
|
||||
return tuple(ims)
|
||||
|
||||
def getchannel(self, channel):
|
||||
"""
|
||||
Returns an image containing a single channel of the source image.
|
||||
|
||||
:param channel: What channel to return. Could be index
|
||||
(0 for "R" channel of "RGB") or channel name
|
||||
("A" for alpha channel of "RGBA").
|
||||
:returns: An image in "L" mode.
|
||||
|
||||
.. versionadded:: 4.3.0
|
||||
"""
|
||||
self.load()
|
||||
|
||||
if isStringType(channel):
|
||||
try:
|
||||
channel = self.getbands().index(channel)
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
'The image has no channel "{}"'.format(channel))
|
||||
|
||||
return self._new(self.im.getband(channel))
|
||||
|
||||
def tell(self):
|
||||
"""
|
||||
Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
|
||||
|
|
|
@ -67,7 +67,7 @@ class Contrast(_Enhance):
|
|||
self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
|
||||
|
||||
if 'A' in image.getbands():
|
||||
self.degenerate.putalpha(image.split()[-1])
|
||||
self.degenerate.putalpha(image.getchannel('A'))
|
||||
|
||||
|
||||
class Brightness(_Enhance):
|
||||
|
@ -82,7 +82,7 @@ class Brightness(_Enhance):
|
|||
self.degenerate = Image.new(image.mode, image.size, 0)
|
||||
|
||||
if 'A' in image.getbands():
|
||||
self.degenerate.putalpha(image.split()[-1])
|
||||
self.degenerate.putalpha(image.getchannel('A'))
|
||||
|
||||
|
||||
class Sharpness(_Enhance):
|
||||
|
@ -97,4 +97,4 @@ class Sharpness(_Enhance):
|
|||
self.degenerate = image.filter(ImageFilter.SMOOTH)
|
||||
|
||||
if 'A' in image.getbands():
|
||||
self.degenerate.putalpha(image.split()[-1])
|
||||
self.degenerate.putalpha(image.getchannel('A'))
|
||||
|
|
|
@ -200,7 +200,7 @@ class TestFilePng(PillowTestCase):
|
|||
self.assert_image(im, "RGBA", (162, 150))
|
||||
|
||||
# image has 124 unique alpha values
|
||||
self.assertEqual(len(im.split()[3].getcolors()), 124)
|
||||
self.assertEqual(len(im.getchannel('A').getcolors()), 124)
|
||||
|
||||
def test_load_transparent_rgb(self):
|
||||
test_file = "Tests/images/rgb_trns.png"
|
||||
|
@ -212,7 +212,7 @@ class TestFilePng(PillowTestCase):
|
|||
self.assert_image(im, "RGBA", (64, 64))
|
||||
|
||||
# image has 876 transparent pixels
|
||||
self.assertEqual(im.split()[3].getcolors()[0][0], 876)
|
||||
self.assertEqual(im.getchannel('A').getcolors()[0][0], 876)
|
||||
|
||||
def test_save_p_transparent_palette(self):
|
||||
in_file = "Tests/images/pil123p.png"
|
||||
|
@ -234,7 +234,7 @@ class TestFilePng(PillowTestCase):
|
|||
self.assert_image(im, "RGBA", (162, 150))
|
||||
|
||||
# image has 124 unique alpha values
|
||||
self.assertEqual(len(im.split()[3].getcolors()), 124)
|
||||
self.assertEqual(len(im.getchannel('A').getcolors()), 124)
|
||||
|
||||
def test_save_p_single_transparency(self):
|
||||
in_file = "Tests/images/p_trns_single.png"
|
||||
|
@ -258,7 +258,7 @@ class TestFilePng(PillowTestCase):
|
|||
self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))
|
||||
|
||||
# image has 876 transparent pixels
|
||||
self.assertEqual(im.split()[3].getcolors()[0][0], 876)
|
||||
self.assertEqual(im.getchannel('A').getcolors()[0][0], 876)
|
||||
|
||||
def test_save_p_transparent_black(self):
|
||||
# check if solid black image with full transparency
|
||||
|
@ -287,7 +287,7 @@ class TestFilePng(PillowTestCase):
|
|||
|
||||
# There are 559 transparent pixels.
|
||||
im = im.convert('RGBA')
|
||||
self.assertEqual(im.split()[3].getcolors()[0][0], 559)
|
||||
self.assertEqual(im.getchannel('A').getcolors()[0][0], 559)
|
||||
|
||||
def test_save_rgb_single_transparency(self):
|
||||
in_file = "Tests/images/caption_6_33_22.png"
|
||||
|
@ -550,7 +550,7 @@ class TestTruncatedPngPLeaks(PillowTestCase):
|
|||
# linux
|
||||
# man 2 getrusage
|
||||
# ru_maxrss (since Linux 2.6.32)
|
||||
# This is the maximum resident set size used (in kilobytes).
|
||||
# This is the maximum resident set size used (in kilobytes).
|
||||
return mem / 1024 # megs
|
||||
|
||||
def test_leak_load(self):
|
||||
|
|
|
@ -103,11 +103,11 @@ class TestFormatHSV(PillowTestCase):
|
|||
# im.split()[0].show()
|
||||
# comparable.split()[0].show()
|
||||
|
||||
self.assert_image_similar(im.split()[0], comparable.split()[0],
|
||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
||||
1, "Hue conversion is wrong")
|
||||
self.assert_image_similar(im.split()[1], comparable.split()[1],
|
||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
||||
1, "Saturation conversion is wrong")
|
||||
self.assert_image_similar(im.split()[2], comparable.split()[2],
|
||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
||||
1, "Value conversion is wrong")
|
||||
|
||||
# print(im.getpixel((192, 64)))
|
||||
|
@ -120,11 +120,11 @@ class TestFormatHSV(PillowTestCase):
|
|||
# print(im.getpixel((192, 64)))
|
||||
# print(comparable.getpixel((192, 64)))
|
||||
|
||||
self.assert_image_similar(im.split()[0], comparable.split()[0],
|
||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
||||
3, "R conversion is wrong")
|
||||
self.assert_image_similar(im.split()[1], comparable.split()[1],
|
||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
||||
3, "G conversion is wrong")
|
||||
self.assert_image_similar(im.split()[2], comparable.split()[2],
|
||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
||||
3, "B conversion is wrong")
|
||||
|
||||
def test_convert(self):
|
||||
|
@ -137,11 +137,11 @@ class TestFormatHSV(PillowTestCase):
|
|||
# print(im.split()[0].histogram())
|
||||
# print(comparable.split()[0].histogram())
|
||||
|
||||
self.assert_image_similar(im.split()[0], comparable.split()[0],
|
||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
||||
1, "Hue conversion is wrong")
|
||||
self.assert_image_similar(im.split()[1], comparable.split()[1],
|
||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
||||
1, "Saturation conversion is wrong")
|
||||
self.assert_image_similar(im.split()[2], comparable.split()[2],
|
||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
||||
1, "Value conversion is wrong")
|
||||
|
||||
def test_hsv_to_rgb(self):
|
||||
|
@ -155,11 +155,14 @@ class TestFormatHSV(PillowTestCase):
|
|||
# print([ord(x) for x in target.split()[1].tobytes()[:80]])
|
||||
# print([ord(x) for x in converted.split()[1].tobytes()[:80]])
|
||||
|
||||
self.assert_image_similar(converted.split()[0], comparable.split()[0],
|
||||
self.assert_image_similar(converted.getchannel(0),
|
||||
comparable.getchannel(0),
|
||||
3, "R conversion is wrong")
|
||||
self.assert_image_similar(converted.split()[1], comparable.split()[1],
|
||||
self.assert_image_similar(converted.getchannel(1),
|
||||
comparable.getchannel(1),
|
||||
3, "G conversion is wrong")
|
||||
self.assert_image_similar(converted.split()[2], comparable.split()[2],
|
||||
self.assert_image_similar(converted.getchannel(2),
|
||||
comparable.getchannel(2),
|
||||
3, "B conversion is wrong")
|
||||
|
||||
|
||||
|
|
|
@ -164,14 +164,28 @@ class TestImage(PillowTestCase):
|
|||
self.assertEqual(im.size[1], orig_size[1] + 2*ymargin)
|
||||
|
||||
def test_getbands(self):
|
||||
# Arrange
|
||||
# Assert
|
||||
self.assertEqual(hopper('RGB').getbands(), ('R', 'G', 'B'))
|
||||
self.assertEqual(hopper('YCbCr').getbands(), ('Y', 'Cb', 'Cr'))
|
||||
|
||||
def test_getchannel_wrong_params(self):
|
||||
im = hopper()
|
||||
|
||||
# Act
|
||||
bands = im.getbands()
|
||||
self.assertRaises(ValueError, im.getchannel, -1)
|
||||
self.assertRaises(ValueError, im.getchannel, 3)
|
||||
self.assertRaises(ValueError, im.getchannel, 'Z')
|
||||
self.assertRaises(ValueError, im.getchannel, '1')
|
||||
|
||||
# Assert
|
||||
self.assertEqual(bands, ('R', 'G', 'B'))
|
||||
def test_getchannel(self):
|
||||
im = hopper('YCbCr')
|
||||
Y, Cb, Cr = im.split()
|
||||
|
||||
self.assert_image_equal(Y, im.getchannel(0))
|
||||
self.assert_image_equal(Y, im.getchannel('Y'))
|
||||
self.assert_image_equal(Cb, im.getchannel(1))
|
||||
self.assert_image_equal(Cb, im.getchannel('Cb'))
|
||||
self.assert_image_equal(Cr, im.getchannel(2))
|
||||
self.assert_image_equal(Cr, im.getchannel('Cr'))
|
||||
|
||||
def test_getbbox(self):
|
||||
# Arrange
|
||||
|
|
|
@ -133,7 +133,7 @@ class TestImageConvert(PillowTestCase):
|
|||
alpha = hopper('L')
|
||||
im.putalpha(alpha)
|
||||
|
||||
comparable = im.convert('P').convert('LA').split()[1]
|
||||
comparable = im.convert('P').convert('LA').getchannel('A')
|
||||
|
||||
self.assert_image_similar(alpha, comparable, 5)
|
||||
|
||||
|
@ -185,7 +185,7 @@ class TestImageConvert(PillowTestCase):
|
|||
if converted_im.mode == 'RGB':
|
||||
self.assert_image_similar(converted_im, target, 3)
|
||||
else:
|
||||
self.assert_image_similar(converted_im, target.split()[0], 1)
|
||||
self.assert_image_similar(converted_im, target.getchannel(0), 1)
|
||||
|
||||
matrix_convert('RGB')
|
||||
matrix_convert('L')
|
||||
|
|
|
@ -360,8 +360,7 @@ class TestImageCms(PillowTestCase):
|
|||
return Image.merge(mode, chans)
|
||||
|
||||
source_image = create_test_image()
|
||||
preserved_channel_ndx = source_image.getbands().index(preserved_channel)
|
||||
source_image_aux = source_image.split()[preserved_channel_ndx]
|
||||
source_image_aux = source_image.getchannel(preserved_channel)
|
||||
|
||||
# create some transform, it doesn't matter which one
|
||||
source_profile = ImageCms.createProfile("sRGB")
|
||||
|
@ -374,7 +373,7 @@ class TestImageCms(PillowTestCase):
|
|||
result_image = source_image
|
||||
else:
|
||||
result_image = ImageCms.applyTransform(source_image, t, inPlace=False)
|
||||
result_image_aux = result_image.split()[preserved_channel_ndx]
|
||||
result_image_aux = result_image.getchannel(preserved_channel)
|
||||
|
||||
self.assert_image_equal(source_image_aux, result_image_aux)
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class TestImageEnhance(PillowTestCase):
|
|||
|
||||
def _check_alpha(self, im, original, op, amount):
|
||||
self.assertEqual(im.getbands(), original.getbands())
|
||||
self.assert_image_equal(im.split()[-1], original.split()[-1],
|
||||
self.assert_image_equal(im.getchannel('A'), original.getchannel('A'),
|
||||
"Diff on %s: %s" % (op, amount))
|
||||
|
||||
def test_alpha(self):
|
||||
|
|
|
@ -52,7 +52,7 @@ class TestNumpy(PillowTestCase):
|
|||
a = numpy.array([[x]*bands for x in data], dtype=dtype)
|
||||
a.shape = TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], bands
|
||||
i = Image.fromarray(a)
|
||||
if list(i.split()[0].getdata()) != list(range(100)):
|
||||
if list(i.getchannel(0).getdata()) != list(range(100)):
|
||||
print("data mismatch for", dtype)
|
||||
# print(dtype, list(i.getdata()))
|
||||
return i
|
||||
|
|
|
@ -146,6 +146,7 @@ ITU-R 709, using the D65 luminant) to the CIE XYZ color space:
|
|||
.. automethod:: PIL.Image.Image.seek
|
||||
.. automethod:: PIL.Image.Image.show
|
||||
.. automethod:: PIL.Image.Image.split
|
||||
.. automethod:: PIL.Image.Image.getchannel
|
||||
.. automethod:: PIL.Image.Image.tell
|
||||
.. automethod:: PIL.Image.Image.thumbnail
|
||||
.. automethod:: PIL.Image.Image.tobitmap
|
||||
|
|
9
docs/releasenotes/4.3.0.rst
Normal file
9
docs/releasenotes/4.3.0.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
4.3.0
|
||||
-----
|
||||
|
||||
Get One Channel From Image
|
||||
==========================
|
||||
|
||||
New method :py:meth:`PIL.Image.Image.getchannel` added.
|
||||
It returns single channel by index or name. For example,
|
||||
``image.getchannel("A")`` will return alpha channel as seperate image.
|
|
@ -6,6 +6,7 @@ Release Notes
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
4.3.0
|
||||
4.2.1
|
||||
4.2.0
|
||||
4.1.1
|
||||
|
@ -21,5 +22,3 @@ Release Notes
|
|||
3.0.0
|
||||
2.8.0
|
||||
2.7.0
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user