Sorl-thumbnail: «OSError: cannot write mode RGBA as JPEG» when get_thumbnail for PNG in mode=P

Created on 16 Sep 2018  ·  7Comments  ·  Source: jazzband/sorl-thumbnail

What did I do?

Tried to get thumbnail (JPEG without transparency) for PNG image in mode=P (indexed colours?).
(It works good for PNG with mode=RGBA but not mode=P)

What did I expect to happen?

Saving thumbnail without any exceptions, flattened alpha-channel into solid background of some colour (eg THUMBNAIL_PADDING_COLOR, some specific colour from settings or 'white').

Test image

5847e9aacef1014c0b5e4828
https://user-images.githubusercontent.com/244666/45594613-a5aba780-b9a6-11e8-9321-da6710f9fb4f.png

What actually happened?

>>> i = Image.open('forbes.png')
>>> i
<PIL.PngImagePlugin.PngImageFile image mode=P size=400x400 at 0x7FE650252CC0>

>>> get_thumbnail(i, '100x106', crop='center', quality=99, format='PNG')
<sorl.thumbnail.images.ImageFile at 0x7fe6501d6390>

>>> get_thumbnail(i, '100x100', crop='center', quality=99, format='JPEG')
OSError: cannot write mode RGBA as JPEG

Versions

Python == 3.6.5
Pillow == 5.2.0 (or any versions >= 4.2.0)
sorl-thumbnail == 12.4.1

Related issue

https://github.com/python-pillow/Pillow/issues/2609

How to fix it?

You need to make a background image with certain colour and merge source image into background:

    def _colorspace(self, image, colorspace, format):
        if colorspace == 'RGB':
            # Pillow JPEG doesn't allow RGBA anymore. It was converted to RGB before.
            if image.mode == 'RGBA' and format != 'JPEG':
                return image  # RGBA is just RGB + Alpha
            if image.mode == 'LA' or (image.mode == 'P' and 'transparency' in image.info):
                if format == 'JPEG':
                    newimage = Image.new('RGB', image.size, '#eebbaa')
                    mask = image.convert('RGBA').split()[-1]
                    newimage.paste(image.convert('RGBA'), (0, 0), mask)
                else:
                    newimage = image.convert('RGBA')
                    transparency = image.info.get('transparency')
                    if transparency is not None:
                        mask = image.convert('RGBA').split()[-1]
                        newimage.putalpha(mask)
                return newimage
            return image.convert('RGB')
        if colorspace == 'GRAY':
            return image.convert('L')
        return image

Correct result

cor

Most helpful comment

This comment is not related to the issue but might help people like me looking for a solution. If you don't mind having PNG format thumbnails you can use the following setting

THUMBNAIL_PRESERVE_FORMAT = True

This saves PNG images as PNG thumbnails and thus bypasses the RGBA problem completely.

All 7 comments

Is there going to be a PR for this?

I have the same issue when saving an image through django rest framework. Where should I put this piece of code @stopdesign ?

This comment is not related to the issue but might help people like me looking for a solution. If you don't mind having PNG format thumbnails you can use the following setting

THUMBNAIL_PRESERVE_FORMAT = True

This saves PNG images as PNG thumbnails and thus bypasses the RGBA problem completely.

Still relevant :)

I'm curious as to why sorl worked fine before and now it doesn't in this case. Maybe it was better to just throw a warning?

So part of the issue for me is in the fact that sorl uses the file extension to determine the output format instead of actually reading the headers of the file like Pillow does to determine format. That means that the workaround THUMBNAIL_PRESERVE_FORMAT = True does not work for me when a user has misnamed a jpg file as a png file. I assume that any patch to fix this would be engine dependent, I'd love a pointer as to how to start on this to get this done.

Should this be an independent issue?

Same problem here. Will be there a fix for this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DarwinSurvivor picture DarwinSurvivor  ·  3Comments

jplehmann picture jplehmann  ·  7Comments

Flimm picture Flimm  ·  10Comments

awidgery picture awidgery  ·  5Comments

dbrgn picture dbrgn  ·  14Comments