如何用ImageMagick将同尺寸PNG徽章按六边形网格排版?
ImageMagick 六边形网格排版及灰度图问题解决方案
一、六边形网格批量排版实现
核心逻辑
徽章尺寸142x163,按六边形紧凑排列时:
- 横向间距等于徽章宽度(142px)
- 纵向间距取徽章高度的3/4(约122px)
- 奇数行需偏移半个徽章宽度(71px),保证网格对齐
- A3画布按300DPI计算为3508x4961px,边缘预留20px作为打印边距,每个徽章加1px白边作为切割空间
实现步骤
- 批量给徽章加切割边:
for img in *.png; do convert "$img" -border 1 -bordercolor white "bordered_$img" done
- 用脚本生成位置参数并合成:
用Python(或其他脚本语言)根据打印清单自动计算每个徽章的位置,拼接ImageMagick命令执行:
import subprocess # 带边框后的徽章尺寸 badge_w = 142 + 2 badge_h = 163 + 2 row_offset = badge_w // 2 vertical_spacing = int(badge_h * 0.75) # A3画布尺寸(300DPI)+ 边距 canvas_w = 3508 canvas_h = 4961 margin = 20 # 打印清单:(带边框的文件名, 打印数量) badge_list = [ ("bordered_badge1.png", 5), ("bordered_badge2.png", 3), # 补充其他徽章信息 ] # 构建ImageMagick命令 cmd = ["convert", "-size", f"{canvas_w}x{canvas_h}", "xc:white"] x, y = margin + row_offset, margin current_row = 1 for badge, num in badge_list: for _ in range(num): cmd.extend(["-page", f"+{x}+{y}", badge]) x += badge_w # 换行判断:超出右侧边距则切换下一行 if x + badge_w > canvas_w - margin: current_row += 1 y += vertical_spacing x = margin + (row_offset if current_row % 2 == 1 else 0) # 超出画布高度则停止 if y + badge_h > canvas_h - margin: break # 完成合成 cmd.extend(["-flatten", "final_a3_layout.png"]) subprocess.run(cmd)
二、灰度图导致整行变灰的修复
问题根源
ImageMagick默认会继承第一个输入图像的颜色空间,若首图为灰度单通道,后续彩色图会被强制转为灰度模式。
解决方案
强制所有图像统一为RGB颜色空间,灰度图会转为RGB模式下的单通道灰度(视觉仍为黑白,不影响彩色图):
在读取每个徽章时添加-colorspace sRGB参数,修改后的命令片段示例:
convert -size 3508x4961 xc:white \ -page +71+20 \( bordered_badge_gray.png -colorspace sRGB \) \ -page +213+20 \( bordered_badge_color.png -colorspace sRGB \) \ ... \ -flatten final_a3_layout.png
对应到Python脚本中,只需修改徽章路径部分为:
cmd.extend(["-page", f"+{x}+{y}", "\\(", badge, "-colorspace sRGB", "\\)"])
内容的提问来源于stack exchange,提问作者PFB
相关产品推荐
相关产品推荐

