图像转换 - 无法将RGBA模式写为JPEG

时间:2018-01-11 11:31:54

标签: python django

我正在尝试调整大小在项目上传之前降低图像质量。这是我试过的,

def save(self):
    im = Image.open(self.image)
    output = BytesIO()
    im = im.resize(240, 240)
    im.save(output, format='JPEG', quality=95)
    output.seek(0)
    self.image = InMemoryUploadedFile(output, 'ImageField', "%s.jpg" % self.image.name.split('.')[0], 'image/jpeg', sys.getsizeof(output), None)
    super(Model, self).save()

如果我上传了jpg图片,但是如果我上传了png或任何其他图片类型,那么它工作得很好,但它不起作用会引发cannot write mode RGBA as JPEG& cannot write mode P as JPEG等。

我们如何解决这个问题?谢谢!

2 个答案:

答案 0 :(得分:0)

如果你的image.mode是" P"或" RGBA"并且您想将其转换为jpeg然后您需要先转换image.mode,因为jpeg不支持以前的模式

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

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

答案 1 :(得分:0)

摘要timop2

  • 背景

    • JPG不支持alpha = transparency
    • RGBAPalpha = transparency
      • RGBA = Red Green Blue Alpha
  • 结果

    • cannot write mode RGBA as JPEG
    • cannot write mode P as JPEG
  • 解决方案

    • 在保存为JPG之前,丢弃alpha = transparency
      • 例如:将Image转换为RGB
    • 然后保存到JPG
  • 您的代码

    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)
    
  • 为您提供的更多信息:

关于resize & reduce quality of image,我已经实现了一个功能,供您(和其他人)参考:

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

最新代码可在此处找到:

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