专家建议需要调整 Python 中的图像大小,因为现有解决方案有例外
Expert Advice needed to resize image in Python as Existing solutions have exceptions
现在有 3 种调整图像大小的解决方案:
第一名:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
img = img.resize((90, 90), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
第二名:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, img)
bg = bg.resize((90, 90), Image.ANTIALIAS)
bg.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
第三个:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
img = img.convert('RGB')
img = img.resize((90, 90), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
在某些情况下,第一个问题是错误 "cannot write mode RGBA as JPEG",
第二个是 "bad transparency mask",第三个的问题是它在所有情况下都有效,但是调整大小后具有透明度的图像的背景为黑色,这是不可接受的,在边缘附近也可以看到失真的颜色像素。
那么有什么办法可以解决这些问题呢?
注意:(要求的输出格式为.jpg,要调整大小的图像在被抓取时格式会有所不同,主要是具有透明背景的.png)
更新:
根据评论,我根据 alpha 条件放置了一个 if else 为:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg")
has_alpha = img.mode == 'RGBA'
print(has_alpha)
if has_alpha == True:
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, img)
bg = bg.resize((80, 80), Image.ANTIALIAS)
bg.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
else:
img.resize((80, 80), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
工作正常,但在极少数情况下,has_alpha 为假,我会收到以下错误。
False
Traceback (most recent call last):
File "C:\Intel\lib\site-packages\PIL\JpegImagePlugin.py", line 620, in _save
rawmode = RAWMODE[im.mode]
KeyError: 'P'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "resize.py", line 33, in <module>
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
File "C:\Intel\lib\site-packages\PIL\Image.py", line 1935, in save
save_handler(self, fp, filename)
File "C:\Intel\lib\site-packages\PIL\JpegImagePlugin.py", line 622, in _save
raise IOError("cannot write mode %s as JPEG" % im.mode)
OSError: cannot write mode P as JPEG
正如 PIL 错误消息所指出的,JPEG 不支持透明度。要处理使用透明度的图像,您需要将它们粘贴到 RGB 背景图像上。这就是您的第二个选项所做的:Image.new("RGB", img.size, (255, 255, 255))
创建一个与 img
大小相同的新图像,所有像素都设置为 (255, 255, 255)
,即白色。 (您也可以使用字符串为 PIL 指定颜色)。
因此,要正确执行此调整大小和转换任务,您需要确定图像是否具有透明度。您可以通过检查 Image.mode
字符串来做到这一点。如果是“RGBA”,则图像具有透明度。这是一个简短的演示,它使用中浅灰色作为背景。我使用 pathlib
模块从输入文件名创建 JPEG 文件名。此模块在 Python 3.4+ 中可用。
更新
此代码的原始版本不处理调色板映射图像,但这个新版本可以,包括具有透明度的调色板映射图像。
def resize_to_jpg(fname, newsize, background):
img = Image.open(fname)
#img.show()
print('Resizing', fname, 'Mode =', img.mode)
if img.mode == "P":
# Handle palette-mapped images
if 'transparency' in img.info:
img = img.convert('RGBA')
else:
img = img.convert('RGB')
if img.mode == "RGBA":
# The image has transparency
out = Image.new("RGB", img.size, background)
# Use the image's own alpha channel as the mask
out.paste(img, mask=img)
else:
out = img
out = out.resize(newsize, Image.ANTIALIAS)
#out.show()
# Construct output file name
outname = str(PurePath(fname).with_suffix('.jpg'))
out.save(outname, quality=90, optimize=True)
print(outname, 'saved')
newsize = (120, 120)
background = (192, 192, 192)
files = (
'RhombicPlain.png',
'RhombicAlpha.png',
)
for fname in files:
resize_to_jpg(fname, newsize, background)
输出
Resizing RhombicPlain.png Mode = RGB
RhombicPlain.jpg saved
Resizing RhombicAlpha.png Mode = RGBA
RhombicAlpha.jpg saved
这是我使用 POV-Ray 创建的输入图像 RhombicPlain.png 和 RhombicAlpha.png。
这是输出图像,RhombicPlain.jpg 和 RhombicAlpha.jpg
现在有 3 种调整图像大小的解决方案: 第一名:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
img = img.resize((90, 90), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
第二名:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, img)
bg = bg.resize((90, 90), Image.ANTIALIAS)
bg.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
第三个:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg')
img = img.convert('RGB')
img = img.resize((90, 90), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg')
在某些情况下,第一个问题是错误 "cannot write mode RGBA as JPEG", 第二个是 "bad transparency mask",第三个的问题是它在所有情况下都有效,但是调整大小后具有透明度的图像的背景为黑色,这是不可接受的,在边缘附近也可以看到失真的颜色像素。 那么有什么办法可以解决这些问题呢?
注意:(要求的输出格式为.jpg,要调整大小的图像在被抓取时格式会有所不同,主要是具有透明背景的.png)
更新: 根据评论,我根据 alpha 条件放置了一个 if else 为:
img = Image.open('C:\Users\Vishal\Desktop\Test\xyx.jpg")
has_alpha = img.mode == 'RGBA'
print(has_alpha)
if has_alpha == True:
bg = Image.new("RGB", img.size, (255, 255, 255))
bg.paste(img, img)
bg = bg.resize((80, 80), Image.ANTIALIAS)
bg.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
else:
img.resize((80, 80), Image.ANTIALIAS)
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
工作正常,但在极少数情况下,has_alpha 为假,我会收到以下错误。
False
Traceback (most recent call last):
File "C:\Intel\lib\site-packages\PIL\JpegImagePlugin.py", line 620, in _save
rawmode = RAWMODE[im.mode]
KeyError: 'P'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "resize.py", line 33, in <module>
img.save('C:\Users\Vishal\Desktop\Test\xyz.jpg", quality=92)
File "C:\Intel\lib\site-packages\PIL\Image.py", line 1935, in save
save_handler(self, fp, filename)
File "C:\Intel\lib\site-packages\PIL\JpegImagePlugin.py", line 622, in _save
raise IOError("cannot write mode %s as JPEG" % im.mode)
OSError: cannot write mode P as JPEG
正如 PIL 错误消息所指出的,JPEG 不支持透明度。要处理使用透明度的图像,您需要将它们粘贴到 RGB 背景图像上。这就是您的第二个选项所做的:Image.new("RGB", img.size, (255, 255, 255))
创建一个与 img
大小相同的新图像,所有像素都设置为 (255, 255, 255)
,即白色。 (您也可以使用字符串为 PIL 指定颜色)。
因此,要正确执行此调整大小和转换任务,您需要确定图像是否具有透明度。您可以通过检查 Image.mode
字符串来做到这一点。如果是“RGBA”,则图像具有透明度。这是一个简短的演示,它使用中浅灰色作为背景。我使用 pathlib
模块从输入文件名创建 JPEG 文件名。此模块在 Python 3.4+ 中可用。
更新
此代码的原始版本不处理调色板映射图像,但这个新版本可以,包括具有透明度的调色板映射图像。
def resize_to_jpg(fname, newsize, background):
img = Image.open(fname)
#img.show()
print('Resizing', fname, 'Mode =', img.mode)
if img.mode == "P":
# Handle palette-mapped images
if 'transparency' in img.info:
img = img.convert('RGBA')
else:
img = img.convert('RGB')
if img.mode == "RGBA":
# The image has transparency
out = Image.new("RGB", img.size, background)
# Use the image's own alpha channel as the mask
out.paste(img, mask=img)
else:
out = img
out = out.resize(newsize, Image.ANTIALIAS)
#out.show()
# Construct output file name
outname = str(PurePath(fname).with_suffix('.jpg'))
out.save(outname, quality=90, optimize=True)
print(outname, 'saved')
newsize = (120, 120)
background = (192, 192, 192)
files = (
'RhombicPlain.png',
'RhombicAlpha.png',
)
for fname in files:
resize_to_jpg(fname, newsize, background)
输出
Resizing RhombicPlain.png Mode = RGB
RhombicPlain.jpg saved
Resizing RhombicAlpha.png Mode = RGBA
RhombicAlpha.jpg saved
这是我使用 POV-Ray 创建的输入图像 RhombicPlain.png 和 RhombicAlpha.png。
这是输出图像,RhombicPlain.jpg 和 RhombicAlpha.jpg