我正在尝试将页面上具有给定高度的图像列表组合在一起,以使它们首先沿页面向下流动,然后跨过例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Working with api's example</title>
<!--Bootstrap related things-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<link rel="stylesheet" href="css/styles.css">
<script src="js/script.js" defer></script>
</head>
<body>
<!--NAVBAR-->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Manga search</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<form class="form-inline my-2 my-lg-0 mx-auto">
<input class="form-control mr-sm-2" id="input-txt" type="search" placeholder="Place title" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" id="submit-button" type="submit">Search</button>
</form>
</div>
</nav>
<!--RESULTS-->
<div class="container-fluid">
<div class="container-results" id="container-results"> </div>
</div>
</body>
</html>
最大列数为3。问题在于这些图像是动态传递的,但是它们都具有固定的宽度,即它们只能跨越1/2/3列,因此可能会发生以下情况:
Image1 Image4 Image7
Image2 Image5 Image8
Image3 Image6 Image9
此外,列表中每张图像的高度都是可变的,这意味着没有固定的行数。因此,如果图像超过页面或与另一图像重叠。它也必须存储以备后用。允许使用空格,例如:
Image1 Image4-Image4
Image2-Image2-Image2
Image3 Image5 Image6
在上面的示例中,Image3占据了整个页面,或者占据了页面的约3/4,这意味着它不合适,因此将其保留用于另一个新页面。
如何实现这种组合图像的方法?
答案 0 :(得分:1)
您可以使ImageMagick巧妙地将图像垂直放置在蒙太奇中。首先对图像进行转置,然后进行蒙太奇,然后对结果进行转置。
convert logo3.jpg lena2.jpg hatching.jpg zelda3.jpg -transpose miff:- |\
montage - -geometry +2+2 -tile 2x2 miff:- |\
convert - -transpose montage_columns.jpg
答案 1 :(得分:1)
如果您不在乎结果中图像的顺序或网格编号,而只希望最适合给定输出大小,则ImageMagick具有执行此操作的新功能。请参见https://imagemagick.org/script/formats.php#pseudo
上的ASHLAR:ouput.pngmagick 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]
答案 2 :(得分:1)
您有一套非常复杂的规则。我想,如果您想要这种确切的行为,您可能需要编写一些代码。
我试图避免做任何实际的工作,所以我写了一些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进行页面渲染是因为我很熟悉它,但是将其换成其他东西很简单。
答案 3 :(得分:0)
您可以在Python中作为对ImageMagick montage的子过程调用来做到这一点,如下所示:
import subprocess
cmd = '/usr/local/bin/montage lena.jpg house.jpg boats3_small.jpg barn.jpg cameraman.jpg mandril3.jpg monet2.jpg zelda1.jpg redhat.jpg -tile 3x3 -geometry +0+0 -gravity north -background black montage.jpg'
subprocess.call(cmd, shell=True)