25

我可能在手册中寻找错误的东西,但我正在寻找一个图像对象并扩展它而不调整(拉伸/挤压)原始图像的大小。

玩具示例:想象一个 200 x 100 的蓝色矩形,然后我执行一些操作,我有一个新的图像对象,400 x 300,它由一个白色背景组成,一个 200 x 100 的蓝色矩形位于其上。如果我可以控制其扩展的方向或新的背景颜色等,则可以加分。

本质上,我有一个图像,我将对其进行迭代添加,并且我不知道一开始它的大小。

我想我可以抓住原始对象,制作一个新的,稍大的对象,将原始对象粘贴到那里,再画一点,然后重复。看起来它可能在计算上很昂贵。但是,我认为会有一个功能,因为我认为这是一个常见的操作。也许我猜错了。

4

4 回答 4

33

ImageOps.expand 函数将扩展图像,但它在每个方向上添加相同数量的像素。

最好的方法是简单地制作一个新图像并粘贴:

newImage = Image.new(mode, (newWidth,newHeight))
newImage.paste(srcImage, (x1,y1,x1+oldWidth,y1+oldHeight))

如果性能是一个问题,请使您的原始图像比需要的大,并在绘图完成后对其进行裁剪。

于 2009-10-15T15:03:47.237 回答
17

根据 interjays 的回答:

#!/usr/bin/env python

from PIL import Image
import math


def resize_canvas(old_image_path="314.jpg", new_image_path="save.jpg",
                  canvas_width=500, canvas_height=500):
    """
    Resize the canvas of old_image_path.

    Store the new image in new_image_path. Center the image on the new canvas.

    Parameters
    ----------
    old_image_path : str
    new_image_path : str
    canvas_width : int
    canvas_height : int
    """
    im = Image.open(old_image_path)
    old_width, old_height = im.size

    # Center the image
    x1 = int(math.floor((canvas_width - old_width) / 2))
    y1 = int(math.floor((canvas_height - old_height) / 2))

    mode = im.mode
    if len(mode) == 1:  # L, 1
        new_background = (255)
    if len(mode) == 3:  # RGB
        new_background = (255, 255, 255)
    if len(mode) == 4:  # RGBA, CMYK
        new_background = (255, 255, 255, 255)

    newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
    newImage.paste(im, (x1, y1, x1 + old_width, y1 + old_height))
    newImage.save(new_image_path)

resize_canvas()
于 2015-01-05T16:52:45.943 回答
6

您可能会考虑使用一种完全不同的方法来处理您的图像......用固定大小的图块构建它。这样,当您需要扩展时,您只需添加新的图像图块。完成所有计算后,您可以确定图像的最终尺寸,创建该尺寸的空白图像,并将图块粘贴到其中。这应该会减少您为完成任务而寻找的复制量。

(当然,您可能希望将这样的平铺图像封装到一个对象中,以隐藏其他代码层的平铺方面。)

于 2009-10-15T16:55:26.030 回答
0

此代码将放大较小的图像,保留纵横比,然后将其居中放置在标准尺寸的画布上。还保留透明度,或默认为灰色背景。

使用 P 模式 PNG 文件进行测试。

编码调试final.show()break测试。删除行和主题标签final.save(...)以循环和保存。

可以参数化画布比例并提高灵活性,但这符合我的目的。

"""
Resize ... and reconfigures. images in a specified directory

Use case:  Images of varying size, need to be enlarged to exaxtly 1200 x 1200
"""
import os
import glob

from PIL import Image

# Source directory plus Glob file reference (Windows)
source_path = os.path.join('C:', os.sep, 'path', 'to', 'source', '*.png')

# List of UNC Image File paths
images = glob.glob(source_path)

# Destination directory of modified image (Windows)
destination_path = os.path.join('C:', os.sep, 'path', 'to', 'destination')

for image in images:
    
    original = Image.open(image)

    # Retain original attributes (ancillary chunks)
    info = original.info
    
    # Retain original mode
    mode = original.mode

    # Retain original palette
    if original.palette is not None:
        palette = original.palette.getdata()[1]
    else:
        palette = False

    # Match original aspect ratio
    dimensions = original.getbbox()

    # Identify destination image background color
    if 'transparency' in info.keys():
        background = original.info['transparency']
    else:
        # Image does not have transparency set
        print(image)
        background = (64)

    # Get base filename and extension for destination
    filename, extension = os.path.basename(image).split('.')
    
    # Calculate matched aspect ratio
    if dimensions[2] > dimensions[3]:
        width = int(1200)
        modifier = width / dimensions[2]
        length = int(dimensions[3] * modifier)
    elif dimensions[3] > dimensions[2]:
        length = int(1200)
        modifier = length / dimensions[3]
        width = int(dimensions[2] * modifier)
    else:
        width, length = (1200, 1200)
    
    size = (width, length)

    # Set desired final image size
    canvas = (1200, 1200)
    
    # Calculate center position
    position = (
        int((1200 - width)/2),
        int((1200 - length)/2),
        int((1200 - width)/2) + width,
        int((1200 - length)/2) + length
    )

    # Enlarge original image proportionally
    resized = original.resize(size, Image.LANCZOS)

    # Then create sized canvas
    final = Image.new(mode, canvas, background)

    # Replicate original properties
    final.info = info

    # Replicate original palatte
    if palette:
        final.putpalette(palette)

     # Cemter paste resized image to final canvas
    final.paste(resized, position)

    # Save final image to destination directory
    final.show()

    #final.save("{}\\{}.{}".format(destination_path, filename, extension))

    break
于 2020-11-19T06:04:08.873 回答