[Fixed]-Image Conversion – Cannot write mode RGBA as JPEG

32👍

If your image.mode is “P” or “RGBA” and you want to convert it to jpeg then you need to first convert the image.mode because the previous modes aren’t supported for jpeg

if im.mode in ("RGBA", "P"):
    im = im.convert("RGB")

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

👤timop

4👍

Summary timop and 2:

  • backgroud

    • JPG not support alpha = transparency
    • RGBA, P has alpha = transparency
      • RGBA= Red Green Blue Alpha
  • result

    • cannot write mode RGBA as JPEG
    • cannot write mode P as JPEG
  • solution

    • before save to JPG, discard alpha = transparency
      • such as: convert Image to RGB
    • then save to JPG
  • your code

    if im.mode == "JPEG":
        im.save(output, format='JPEG', quality=95)
    elif im.mode in ["RGBA", "P"]:
        im = im.convert("RGB")
        im.save(output, format='JPEG', quality=95)
    
  • More for you:

about resize & reduce quality of image, I have implement a function, for you (and others) to refer:

from PIL import Image, ImageDraw
cfgDefaultImageResample = Image.BICUBIC # Image.LANCZOS

def resizeImage(inputImage,
                newSize,
                resample=cfgDefaultImageResample,
                outputFormat=None,
                outputImageFile=None
                ):
    """
        resize input image
        resize normally means become smaller, reduce size
    :param inputImage: image file object(fp) / filename / binary bytes
    :param newSize: (width, height)
    :param resample: PIL.Image.NEAREST, PIL.Image.BILINEAR, PIL.Image.BICUBIC, or PIL.Image.LANCZOS
        https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.thumbnail
    :param outputFormat: PNG/JPEG/BMP/GIF/TIFF/WebP/..., more refer:
        https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
        if input image is filename with suffix, can omit this -> will infer from filename suffix
    :param outputImageFile: output image file filename
    :return:
        input image file filename: output resized image to outputImageFile
        input image binary bytes: resized image binary bytes
    """
    openableImage = None
    if isinstance(inputImage, str):
        openableImage = inputImage
    elif CommonUtils.isFileObject(inputImage):
        openableImage = inputImage
    elif isinstance(inputImage, bytes):
        inputImageLen = len(inputImage)
        openableImage = io.BytesIO(inputImage)

    if openableImage:
        imageFile = Image.open(openableImage)
    elif isinstance(inputImage, Image.Image):
        imageFile = inputImage
    # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=3543x3543 at 0x1065F7A20>
    imageFile.thumbnail(newSize, resample)
    if outputImageFile:
        # save to file
        imageFile.save(outputImageFile)
        imageFile.close()
    else:
        # save and return binary byte
        imageOutput = io.BytesIO()
        # imageFile.save(imageOutput)
        outputImageFormat = None
        if outputFormat:
            outputImageFormat = outputFormat
        elif imageFile.format:
            outputImageFormat = imageFile.format
        imageFile.save(imageOutput, outputImageFormat)
        imageFile.close()
        compressedImageBytes = imageOutput.getvalue()
        compressedImageLen = len(compressedImageBytes)
        compressRatio = float(compressedImageLen)/float(inputImageLen)
        print("%s -> %s, resize ratio: %d%%" % (inputImageLen, compressedImageLen, int(compressRatio * 100)))
        return compressedImageBytes

latest code can found here:

https://github.com/crifan/crifanLibPython/blob/master/crifanLib/crifanMultimedia.py

👤crifan

Leave a comment