Python枕头图像组合

2024-09-27 00:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将页面上具有给定高度的图像列表组合在一起,以便它们首先沿页面向下流动,然后穿过页面,例如:

Image1 Image4 Image7
Image2 Image5 Image8
Image3 Image6 Image9

最大列数为3。问题是这些图像是动态传递的,但都有固定的宽度,即它们只能跨1/2/3列,因此可能会发生类似的情况:

Image1 Image4-Image4
Image2-Image2-Image2
Image3 Image5 Image6

此外,我的列表中每个图像的高度都是可变的,这意味着没有固定数量的行。因此,如果一个图像超出页面或与另一个图像重叠。还必须将其存储以备将来使用。允许空白,例如:

Image1        Image4
Image2-Image2 Image4
Image2-Image2 Image5

在上面的例子中,Image3占据了整个页面,或者可能占据了页面的3/4,这意味着它不适合,因此它被保留在另一个新页面上

如何实现这种组合图像的方法


Tags: 图像列表高度动态页面列数image1image2
3条回答

你有一套相当复杂的规则。我认为,如果您想要实现这种精确的行为,可能需要编写一些代码

我试图避免做任何实际工作,因此我编写了一个小python来为您布局页面:

#!/usr/bin/python3

import sys
import math
import pyvips

column_width = 256
row_height = 256
background_colour = 255 # you could use eg. [128, 255, 128] as well

# pop enough tiles from the argument to fill a page
def layout(tiles):
    # we insert an image (at its top-left), or "x" if a tile is covered by an
    # image up and left of itself
    page = [[None for x in range(3)] for y in range(3)]

    # where we put the next tile
    current_x = 0
    current_y = 0

    # loop to fill page
    page_filled = False
    while not page_filled:
        # used up all the tiles?
        if tiles == []:
            break

        this_tile = tiles[0]
        tiles_across = math.ceil(this_tile.width / column_width)
        tiles_down = math.ceil(this_tile.height / row_height)

        # image too large for page
        if tiles_across > 3 or tiles_down > 3:
                raise Exception(f"tile too large - {this_tile}")

        # loop to find the next free space this tile fits
        while True:
            # too tall for this column?
            if tiles_down > 3 - current_y:
                current_y = 0
                current_x += 1

            # too wide for this row? 
            if tiles_across > 3 - current_x:
                # we've filled the page
                page_filled = True
                break

            # is this set of tiles clear?
            all_clear = True
            for y in range(tiles_down):
                for x in range(tiles_across):
                    if page[current_y + y][current_x + x]:
                        all_clear = False

            if all_clear:
                break

            # try the next slot down
            current_y += 1

        # did we find a spot?
        if not page_filled:
            # place the tile here and mark the spaces it covers in the page
            for y in range(tiles_down):
                for x in range(tiles_across):
                    page[current_y + y][current_x + x] = "x"
            page[current_y][current_x] = this_tile
            tiles.pop(0)

    # the page has filled -- draw!
    image = pyvips.Image.black(3 * column_width, 3 * row_height) \
            + background_colour
    for y in range(3):
        for x in range(3):
            if isinstance(page[y][x], pyvips.Image):
                image = image.insert(page[y][x], \
                        x * column_width, y * row_height)

    return image

# a source of tiles .. we just load the command-line arguments
all_tiles = [pyvips.Image.new_from_file(filename, access="sequential")
             for filename in sys.argv[1:]]

page_number = 0
while all_tiles != []:
    filename = f"page-{page_number}.jpg"
    print(f"generating {filename} ...")
    page = layout(all_tiles)
    page.write_to_file(filename)
    page_number += 1

您可以这样运行它:

$ ./layout.py ~/pics/shark.jpg ~/pics/k2.jpg ~/pics/shark.jpg ~/pics/shark.jpg ~/pics/shark.jpg ~/pics/shark.jpg ~/pics/shark.jpg ~/pics/shark.jpg
generating page-0.jpg ...
generating page-1.jpg ...
$

它似乎对我有用,并且实现了你所有的规则(我想)。我使用pyvips来进行页面渲染,因为我对它很熟悉,但是将它换成其他东西很简单

你可以通过一个技巧让ImageMagick在蒙太奇中首先垂直放置图像。首先对图像进行转置,蒙太奇,然后对结果进行转置

convert logo3.jpg lena2.jpg hatching.jpg zelda3.jpg -transpose miff:- |\
montage - -geometry +2+2 -tile 2x2 miff:- |\
convert - -transpose montage_columns.jpg

enter image description here

如果您不关心结果中图像的顺序,也不关心网格编号,只想获得给定输出大小的最佳匹配,那么ImageMagick有一个新功能来实现这一点。见ASHLAR:ouput.png,网址https://imagemagick.org/script/formats.php#pseudo

magick lena.jpg barn.jpg mandril3.jpg monet2.jpg zelda1.jpg redhat.jpg -background black -define ashlar:best-fit=true ASHLAR:x.png[600x400+0+0]

enter image description here

相关问题 更多 >

    热门问题