【问题标题】:Getting "cannot write mode P as JPEG" while operating on JPG image对 JPG 图像进行操作时出现“无法将模式 P 写入 JPEG”
【发布时间】:2014-03-07 08:07:39
【问题描述】:

我正在尝试调整一些图像的大小,其中大部分是 JPG。但在一些图像中,我收到了错误:

Traceback (most recent call last):
  File "image_operation_new.py", line 168, in modifyImage
    tempImage.save(finalName);
  File "/Users/kshitiz/.virtualenvs/django_project/lib/python2.7/site-     packages/PIL/Image.py", line 1465, in save
   save_handler(self, fp, filename)
  File "/Users/kshitiz/.virtualenvs/django_project/lib/python2.7/site-   packages/PIL/JpegImagePlugin.py", line 455, in _save
    raise IOError("cannot write mode %s as JPEG" % im.mode)
IOError: cannot write mode P as JPEG

我没有更改图像类型,而是使用枕头库。我的操作系统是 Mac OS X。我该如何解决这个问题?

【问题讨论】:

    标签: python macos python-imaging-library pillow


    【解决方案1】:

    您需要将图像转换为 RGB 模式。

    Image.open('old.jpeg').convert('RGB').save('new.jpeg')
    

    【讨论】:

    • 我在一个 .png 文件上试过这个,结果 .jpg 比它大 5 倍多。
    • @Bentley4 PNG 可以比 JPEG 更好地压缩某些类型的图像
    • @Bentley4 您可以在重新采样后将其转换回P
    • 像魅力一样工作!
    【解决方案2】:

    这个答案已经很老了,但是,我想我会通过在转换之前检查模式来提供更好的方法:

    if img.mode != 'RGB':
        img = img.convert('RGB')
    

    这是将图像保存为 JPEG 格式所必需的。

    【讨论】:

    • 这与当前投票率最高的答案相结合,让我的项目重回正轨,谢谢!
    【解决方案3】:

    总结12

    • 背景
      • JPG不支持alpha = transparency
      • RGBA, Palpha = 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("xxx.jpg")
        # in most case, resulting jpg file is resized small one
    elif rgba_or_p_im.mode in ["RGBA", "P"]:
        rgb_im = rgba_or_p_im.convert("RGB")
        rgb_im.save("xxx.jpg")
        # some minor case, resulting jpg file is larger one, should meet your expectation
    
    • 为您做更多:

    关于调整imgae文件大小,我已经实现了一个功能,供大家参考:

    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/python3/crifanLib/thirdParty/crifanPillow.py

    【讨论】:

      【解决方案4】:

      JPEG 不支持 alpha = 透明度 所以在保存到 JPEG 之前丢弃 alpha = 透明度

      如果您使用不同的格式,您可以检查扩展名并专门为 JPEG 使用隐蔽。

      extension = str(imgName).split('.')[-1]
      
      if extension == "png":
          bg_image.save(imgName, "PNG")
      else:
          if bg_image.mode in ("RGBA", "P"):
              bg_image = bg_image.convert("RGB")
          bg_image.save(imgName, "JPEG")
      

      【讨论】:

        【解决方案5】:

        quantize() 方法之后遇到了同样的错误。

        解决方法同上:转为RGB

        image.quantize(colors=256, method=2).convert('RGB')

        【讨论】:

          猜你喜欢
          • 2018-06-23
          • 1970-01-01
          • 2013-05-19
          • 1970-01-01
          • 2014-06-18
          • 2018-08-16
          • 1970-01-01
          相关资源
          最近更新 更多