python - 由于现有解决方案有异常(exception),需要专家建议在 Python 中调整图像大小

标签 python image python-imaging-library

现在有 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')

对于情况,第一个问题是错误“无法将 RGBA 模式写入为 JPEG”, 对于第二个,它是“坏的透明度蒙版”,第三个的问题是它在所有情况下都有效,但是调整大小后具有透明度的图像将其背景变为黑色,这是 Not Acceptable ,而且在边缘附近可以看到扭曲的颜色像素。 那么什么是解决这些问题的通用方法呢?

注意:(所需的输出格式为.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.png RhombicAlpha.png

这里是输出图像,RhombicPlain.jpg 和 RhombicAlpha.jpg

RhombicPlain.jpg RhombicAlpha.jpg

关于python - 由于现有解决方案有异常(exception),需要专家建议在 Python 中调整图像大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51349907/

相关文章:

python - 如何避免Python中Gtk.Dialog关闭?

css - 背景图片在手机上看起来很糟糕

image - Kinect,使用深度图像获取Z值

python - PIL/Pillow 看似任意反转透明度

python - DeepFace verify() 可以接受图像数组或 PIL Image 对象吗?

python - 使用延迟 (DASK) 读取大型 CSV 文件

python - 将 pandas 中的行转换为列

python - 在python中将二进制缓冲区写入文件

javascript - 如何使用javascript onload 下载多个图像?

python - 如何将 PIL 与 Tkinter 一起使用?