使用 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
,exif
etc. 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])