使用 python 的 pil 處理圖片,原圖是 png 想另存為 JPG, 顯示錯誤訊息:
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/PIL/JpegImagePlugin.py", line 632, in _save
raise OSError(f"cannot write mode {im.mode} as JPEG") from e
OSError: cannot write mode RGBA as JPEG
解法:
https://stackoverflow.com/questions/48248405/cannot-write-mode-rgba-as-jpeg
JPG does not support transparency – RGBA means Red, Green, Blue, Alpha – Alpha is transparency.
You need to discard the Alpha Channel or save as something that supports transparency – like PNG.
The Image class has a method convert which can be used to convert RGBA to RGB – after that you will be able to save as JPG.
Have a look here: the image class doku
im = Image.open("audacious.png")
rgb_im = im.convert('RGB')
rgb_im.save('audacious.jpg')
上面的解決,不太好用,因為透明的 alpha 會變成黑色,不是一般預期的白色。
請改用下面的解法:
https://stackoverflow.com/questions/9166400/convert-rgba-png-to-rgb-with-pil
Here’s a version that’s much simpler – not sure how performant it is. Heavily based on some django snippet I found while building RGBA -> JPG + BG support for sorl thumbnails.
from PIL import Image
png = Image.open(object.logo.path)
png.load() # required for png.split()
background = Image.new("RGB", png.size, (255, 255, 255))
background.paste(png, mask=png.split()[3]) # 3 is the alpha channel
background.save('foo.jpg', 'JPEG', quality=80)
直接使用上面的 code, 如果是 PNG 檔不會出錯,但遇到 jpg 檔會出錯,錯誤訊息:
background.paste(nim, mask=nim.split()[3]) IndexError: tuple index out of range
image.mode: returns a str containing the mode of the data read. Typical values are"RGB"and"L"for RGB and gray-scale images respectively. Modes are presented here.im2.info: which returns a dict containing various information about the image. This is image format specific. For jpg images for example it (possibly) contains fields with keys:dpi,jfif,jfif_density,exifetc. More information about jpg images can be found here.image.getbands(): which returns a tuple (even a 1 element one) containing all different channel present in the data. For a typical RGB image this would be('R', 'G', 'B')and for a typical gray-scale image would be('L',).
解法:
if nim.mode == "RGBA":
background = Image.new("RGB", nim.size, (255, 255, 255))
background.paste(nim, mask=nim.split()[3])