Read/Save RGB webp as RGB (instead of RGBX)

This commit is contained in:
Konstantin Kopachev 2018-08-03 14:21:47 -07:00
parent 43f860fce6
commit 84b32a0388
No known key found for this signature in database
GPG Key ID: CECF757E656F4F62
5 changed files with 24 additions and 22 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -16,8 +16,7 @@ class TestFileWebp(PillowTestCase):
self.skipTest('WebP support not installed') self.skipTest('WebP support not installed')
return return
# WebPAnimDecoder only returns RGBA or RGBX, never RGB self.rgb_mode = "RGB"
self.rgb_mode = "RGBX" if _webp.HAVE_WEBPANIM else "RGB"
def test_version(self): def test_version(self):
_webp.WebPDecoderVersion() _webp.WebPDecoderVersion()
@ -29,8 +28,7 @@ class TestFileWebp(PillowTestCase):
Does it have the bits we expect? Does it have the bits we expect?
""" """
file_path = "Tests/images/hopper.webp" image = Image.open("Tests/images/hopper.webp")
image = Image.open(file_path)
self.assertEqual(image.mode, self.rgb_mode) self.assertEqual(image.mode, self.rgb_mode)
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
@ -40,9 +38,7 @@ class TestFileWebp(PillowTestCase):
# generated with: # generated with:
# dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm # dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm
target = Image.open('Tests/images/hopper_webp_bits.ppm') self.assert_image_similar_tofile(image, 'Tests/images/hopper_webp_bits.ppm', 1.0)
target = target.convert(self.rgb_mode)
self.assert_image_similar(image, target, 20.0)
def test_write_rgb(self): def test_write_rgb(self):
""" """
@ -61,13 +57,8 @@ class TestFileWebp(PillowTestCase):
image.load() image.load()
image.getdata() image.getdata()
# If we're using the exact same version of WebP, this test should pass.
# but it doesn't if the WebP is generated on Ubuntu and tested on
# Fedora.
# generated with: dwebp -ppm temp.webp -o hopper_webp_write.ppm # generated with: dwebp -ppm temp.webp -o hopper_webp_write.ppm
# target = Image.open('Tests/images/hopper_webp_write.ppm') self.assert_image_similar_tofile(image, 'Tests/images/hopper_webp_write.ppm', 12.0)
# self.assert_image_equal(image, target)
# This test asserts that the images are similar. If the average pixel # This test asserts that the images are similar. If the average pixel
# difference between the two images is less than the epsilon value, # difference between the two images is less than the epsilon value,

View File

@ -19,8 +19,7 @@ class TestFileWebpLossless(PillowTestCase):
if (_webp.WebPDecoderVersion() < 0x0200): if (_webp.WebPDecoderVersion() < 0x0200):
self.skipTest('lossless not included') self.skipTest('lossless not included')
# WebPAnimDecoder only returns RGBA or RGBX, never RGB self.rgb_mode = "RGB"
self.rgb_mode = "RGBX" if _webp.HAVE_WEBPANIM else "RGB"
def test_write_lossless_rgb(self): def test_write_lossless_rgb(self):
temp_file = self.tempfile("temp.webp") temp_file = self.tempfile("temp.webp")

View File

@ -5,6 +5,7 @@ from io import BytesIO
_VALID_WEBP_MODES = { _VALID_WEBP_MODES = {
"RGBX": True, "RGBX": True,
"RGBA": True, "RGBA": True,
"RGB": True,
} }
_VALID_WEBP_LEGACY_MODES = { _VALID_WEBP_LEGACY_MODES = {
@ -63,7 +64,8 @@ class WebPImageFile(ImageFile.ImageFile):
bgcolor & 0xFF bgcolor & 0xFF
self.info["background"] = (bg_r, bg_g, bg_b, bg_a) self.info["background"] = (bg_r, bg_g, bg_b, bg_a)
self._n_frames = frame_count self._n_frames = frame_count
self.mode = mode self.mode = 'RGB' if mode == 'RGBX' else mode
self.rawmode = mode
self.tile = [] self.tile = []
# Attempt to read ICC / EXIF / XMP chunks from file # Attempt to read ICC / EXIF / XMP chunks from file
@ -154,7 +156,7 @@ class WebPImageFile(ImageFile.ImageFile):
# Set tile # Set tile
self.fp = BytesIO(data) self.fp = BytesIO(data)
self.tile = [("raw", (0, 0) + self.size, 0, self.mode)] self.tile = [("raw", (0, 0) + self.size, 0, self.rawmode)]
return super(WebPImageFile, self).load() return super(WebPImageFile, self).load()
@ -240,16 +242,23 @@ def _save_all(im, fp, filename):
# Make sure image mode is supported # Make sure image mode is supported
frame = ims frame = ims
rawmode = ims.mode
if ims.mode not in _VALID_WEBP_MODES: if ims.mode not in _VALID_WEBP_MODES:
alpha = ims.mode == 'P' and 'A' in ims.im.getpalettemode() alpha = 'A' in ims.mode or 'a' in ims.mode \
frame = ims.convert('RGBA' if alpha else 'RGBX') or ims.mode == 'P' and 'A' in ims.im.getpalettemode()
rawmode = 'RGBA' if alpha else 'RGBX'
frame = ims.convert(rawmode)
if rawmode == 'RGB':
# For faster conversion, use RGBX
rawmode = 'RGBX'
# Append the frame to the animation encoder # Append the frame to the animation encoder
enc.add( enc.add(
frame.tobytes(), frame.tobytes('raw', rawmode),
timestamp, timestamp,
frame.size[0], frame.size[1], frame.size[0], frame.size[1],
frame.mode, rawmode,
lossless, lossless,
quality, quality,
method method
@ -288,7 +297,8 @@ def _save(im, fp, filename):
xmp = im.encoderinfo.get("xmp", "") xmp = im.encoderinfo.get("xmp", "")
if im.mode not in _VALID_WEBP_LEGACY_MODES: if im.mode not in _VALID_WEBP_LEGACY_MODES:
alpha = im.mode == 'P' and 'A' in im.im.getpalettemode() alpha = 'A' in im.mode or 'a' in im.mode \
or im.mode == 'P' and 'A' in im.im.getpalettemode()
im = im.convert('RGBA' if alpha else 'RGB') im = im.convert('RGBA' if alpha else 'RGB')
data = _webp.WebPEncode( data = _webp.WebPEncode(

View File

@ -216,6 +216,8 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
WebPPictureImportRGBA(frame, rgb, 4 * width); WebPPictureImportRGBA(frame, rgb, 4 * width);
} else if (strcmp(mode, "RGBX")==0) { } else if (strcmp(mode, "RGBX")==0) {
WebPPictureImportRGBX(frame, rgb, 4 * width); WebPPictureImportRGBX(frame, rgb, 4 * width);
} else {
WebPPictureImportRGB(frame, rgb, 3 * width);
} }
// Add the frame to the encoder // Add the frame to the encoder