对 JPG 图像进行操作时出现“无法将模式 P 写入 JPEG”
Posted
技术标签:
【中文标题】对 JPG 图像进行操作时出现“无法将模式 P 写入 JPEG”【英文标题】:Getting "cannot write mode P as JPEG" while operating on JPG image 【发布时间】: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。我该如何解决这个问题?
【问题讨论】:
【参考方案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】:总结1和2:
背景JPG
不支持alpha = transparency
RGBA
, P
有 alpha = 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')
【讨论】:
以上是关于对 JPG 图像进行操作时出现“无法将模式 P 写入 JPEG”的主要内容,如果未能解决你的问题,请参考以下文章
PCA图像识别时出现File "d:\matlab\work\ts21\1.jpg" does not exist.的错误