【问题标题】:In Python, Python Image Library 1.1.6, how can I expand the canvas without resizing?在 Python,Python Image Library 1.1.6 中,如何在不调整大小的情况下扩展画布?
【发布时间】:2020-11-19 14:22:35
【问题描述】:

我可能在手册中寻找错误的内容,但我希望获取一个图像对象并在不调整(拉伸/挤压)原始图像的情况下对其进行扩展。

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

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

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

【问题讨论】:

    标签: python python-imaging-library


    【解决方案1】:

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

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

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

    如果性能有问题,请将原始图像设置得比需要的大,并在绘制完成后对其进行裁剪。

    【讨论】:

    • 如果图像被调色板(srcImage.mode == "P"),调色板也必须被复制:newImage.putpalette( srcImage.palette.getdata()[ 1 ] )
    【解决方案2】:

    根据 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()
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        使用 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
        

        【讨论】:

          猜你喜欢
          • 2013-07-20
          • 1970-01-01
          • 2013-10-17
          • 2023-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多