Image Conversion - Cannot write mode RGBA as JPEG

后端 未结 2 440
无人及你
无人及你 2020-12-11 12:16

I\'m trying to resize & reduce quality of image before upload in project. Here\'s what I tried,

def save(self):
    im = Image.open(self.image)
    outpu         


        
2条回答
  •  旧巷少年郎
    2020-12-11 12:57

    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
        # 
        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

提交回复
热议问题