python-pillow / python-pillow/Pillow

Convert image to supported mode before saving

Open
#2,663 5 comments 10 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement
Dominant language
Python
Stars
13.8k
Forks
2.5k
Avg merge
2d 8h
Merged PRs (30d)
89

Description

We need explicit method to automatically convert image to one of the supported modes for saving formats. Affects #2609 and others. Maybe it should be part of ImagePlugins.

This is a good start point:

def fix_mode(image, new_format, fill_color='white'):
    old_mode = image.mode

    if old_mode in ('RGBA', 'LA') and new_format == 'GIF':
        alpha = image.getchannel('A')
        # Convert the image into P mode but only use 255 colors
        # in the palette out of 256.
        image = image.convert(old_mode[:-1]) \
            .convert('P', palette=Image.ADAPTIVE, colors=255)
        # Set all pixel values below 128 to 255, and the rest to 0.
        mask = Image.eval(alpha, lambda px: 255 if px < 128 else 0)
        # Paste the color of index 255 and use alpha as a mask.
        image.paste(255, mask)
        # The transparency index is 255.
        image.info['transparency'] = 255
        return image

    if old_mode == 'CMYK' and new_format in ('PNG', 'WEBP', 'GIF'):
        return image.convert('RGB')

    if old_mode == 'I' and new_format in ('JPEG', 'GIF', 'WEBP'):
        image = image.point([i//256 for i in range(65536)], 'L')
        old_mode = image.mode

    if old_mode == 'P' and new_format in ('JPEG', 'WEBP'):
        # PIL loses palette attribute during crop. So we use low-level api.
        alpha = 'A' in image.im.getpalettemode()
        image = image.convert('RGBA' if alpha else 'RGB')
        old_mode = image.mode

    if old_mode in ('RGBA', 'LA') and new_format == 'JPEG':
        background = Image.new(old_mode[:-1], image.size, fill_color)
        background.paste(image, image.getchannel('A'))
        image = background
        old_mode = image.mode

    # Pillow doesn't support L modes for webp for now.
    if old_mode in ('L', 'LA') and new_format == 'WEBP':
        image = image.convert('RGB' + old_mode[1:])
        old_mode = image.mode

    return image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposed fix_mode function and the ImagePlugins area mentioned in the issue. Trace how image modes are handled before saving to GIF, PNG, WEBP, and JPEG, then determine where the conversion belongs and how each listed mode should behave. Done means supported-mode conversion is applied consistently for the affected formats, with coverage for the described cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-graphics
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.