Skip to content

Commit

Permalink
Allow plugins to specify their supported modes
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Jun 30, 2018
1 parent 7ee1aa6 commit 5f3043f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 35 deletions.
31 changes: 27 additions & 4 deletions Tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

from PIL import Image, TiffImagePlugin
from PIL._util import py3

from io import BytesIO
import os
import sys


class TestImage(PillowTestCase):
Expand Down Expand Up @@ -62,8 +65,7 @@ def test_width_height(self):

def test_invalid_image(self):
if py3:
import io
im = io.BytesIO(b'')
im = BytesIO(b'')
else:
import StringIO
im = StringIO.StringIO('')
Expand Down Expand Up @@ -324,8 +326,29 @@ def test_registered_extensions(self):
for ext in ['.cur', '.icns', '.tif', '.tiff']:
self.assertIn(ext, extensions)

def test_no_convert_mode(self):
self.assertTrue(not hasattr(TiffImagePlugin, '_convert_mode'))
def test_supported_modes(self):
for format in Image.MIME.keys():
try:
save_handler = Image.SAVE[format]
except KeyError:
continue
plugin = sys.modules[save_handler.__module__]
if not hasattr(plugin, '_supported_modes'):
continue

# Check that the supported modes list is accurate
supported_modes = plugin._supported_modes()
for mode in ['1', 'L', 'P', 'RGB', 'RGBA', 'CMYK', 'YCbCr', 'LAB',
'HSV', 'I', 'F', 'LA', 'La', 'RGBX', 'RGBa']:
out = BytesIO()
im = Image.new(mode, (100, 100))
if mode in supported_modes:
im.save(out, format)
else:
self.assertRaises(Exception, im.save, out, format)

def test_no_supported_modes_method(self):
self.assertTrue(not hasattr(TiffImagePlugin, '_supported_modes'))

temp_file = self.tempfile("temp.tiff")

Expand Down
7 changes: 2 additions & 5 deletions src/PIL/GifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,11 +798,8 @@ def write(self, data):
return fp.data


def _convert_mode(im):
return {
'LA':'P',
'CMYK':'RGB'
}.get(im.mode)
def _supported_modes():
return ['RGB', 'RGBA', 'P', 'I', 'F', 'LA', 'L', '1']


# --------------------------------------------------------------------
Expand Down
24 changes: 22 additions & 2 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -1956,9 +1956,29 @@ def save(self, fp, format=None, **params):
fp.close()

def _convert_mode(self, plugin, params):
if not hasattr(plugin, '_convert_mode'):
if not hasattr(plugin, '_supported_modes'):
return
new_mode = plugin._convert_mode(self)
supported_modes = plugin._supported_modes()
if not supported_modes or self.mode in supported_modes:
return
if self.mode == 'P':
preferred_modes = []
if 'A' in self.im.getpalettemode():
preferred_modes.append('RGBA')
preferred_modes.append('RGB')
else:
preferred_modes = {
'RGBA': ['RGB'],
'LA': ['RGBA', 'P', 'L'],
'L': ['RGB'],
'I': ['L', 'RGB'],
'CMYK': ['RGB']
}.get(self.mode, [])
for new_mode in preferred_modes:
if new_mode in supported_modes:
break
else:
new_mode = supported_modes[0]
if self.mode == 'LA' and new_mode == 'P':
alpha = self.getchannel('A')
# Convert the image into P mode but only use 255 colors
Expand Down
11 changes: 2 additions & 9 deletions src/PIL/JpegImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,15 +792,8 @@ def jpeg_factory(fp=None, filename=None):
return im


def _convert_mode(im):
mode = im.mode
if mode == 'P':
return 'RGBA' if 'A' in im.im.getpalettemode() else 'RGB'
return {
'RGBA':'RGB',
'LA':'L',
'I':'L'
}.get(mode)
def _supported_modes():
return ['RGB', 'CMYK', 'YCbCr', 'RGBX', 'L', '1']


# -------------------------------------------------------------------q-
Expand Down
6 changes: 2 additions & 4 deletions src/PIL/PngImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,10 +859,8 @@ def append(fp, cid, *data):
return fp.data


def _convert_mode(im):
return {
'CMYK':'RGB'
}.get(im.mode)
def _supported_modes():
return ['RGB', 'RGBA', 'P', 'I', 'LA', 'L', '1']


# --------------------------------------------------------------------
Expand Down
13 changes: 2 additions & 11 deletions src/PIL/WebPImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,8 @@ def _save(im, fp, filename):
fp.write(data)


def _convert_mode(im):
mode = im.mode
if mode == 'P':
return 'RGBA' if 'A' in im.im.getpalettemode() else 'RGB'
return {
# Pillow doesn't support L modes for webp for now.
'L':'RGB',
'LA':'RGBA',
'I':'RGB',
'CMYK':'RGB'
}.get(mode)
def _supported_modes():
return ['RGB', 'RGBA', 'RGBX', 'CMYK', 'YCbCr', 'HSV', 'I', 'F', 'P', 'LA', 'L', '1']


Image.register_open(WebPImageFile.format, WebPImageFile, _accept)
Expand Down

0 comments on commit 5f3043f

Please sign in to comment.