如何测量魔杖中弦的界限?

时间:2018-10-02 15:30:53

标签: python python-3.x imagemagick wand

我正在使用Wand生成其中包含自定义变量文本的JPG。 我有一个字符串数组,它们的宽度相同,但高度不同。 是否有一种方法可以将长文本自动换行到边界内或计算文本所需的高度,以便从数组中绘制文本时不会重叠。

with Drawing() as ctx:
        with Image(width=1080, height=1080, background=Color("WHITE")) as img:
            with Drawing() as draw: 
                for i,line in enumerate(lines):
                     metrics = draw.get_font_metrics(img, line, multiline=True)
                     draw.text(x=150, y=120+(i*35)+int(metrics.text_height), body=line)
                draw(img)
                img.sample(1080, 1080)
                img.save(filename="output.png")

1 个答案:

答案 0 :(得分:2)

这可能不是您要找的答案,但是希望可以使您走上正确的道路。

  

如何测量魔杖中弦的边界?

您已经在做。我建议使用一种更经典的偏移和累加器方法来映射随每次迭代更新的位置,而不是“智能n快速”单线方法。

top_margin = 120
line_offset = 0
line_padding = 35
with Drawing() as ctx:
    with Image(width=1080, height=1080, background=Color("WHITE")) as img:
        with Drawing() as draw: 
            for i,line in enumerate(lines):
                metrics = draw.get_font_metrics(img, line, multiline=True)
                draw.text(x=150, y=y=top_margin + line_offset, body=line)
                line_offset += int(metrics.text_height) + line_padding
  

是否有一种方法可以将长文本自动换行到边界内或计算文本所需的高度,以便在从数组中绘制文本时不会重叠。

简短的回答是。您将负责实现算法。幸运的是,互联网上充满了可以参考的示例和研究文章。它可以像在溢出之前找到最后一个空间一样基本...

lines = [
    'I\'m using Wand to generate a JPG with custom variable text inside it.',
    'I have an array of strings all with the same width but different heights',
    'Is there a method to word wrap a long text inside a boundary or calculate the height needed for the text so when drawing the texts from the array they don\'t overlap',
]
image_width = 540
image_height = 540
left_margin = 150
right_margin = image_width - left_margin * 2
top_margin = 120
line_padding = 35
line_offset = 0
with Drawing() as ctx:
    with Image(width=image_width, height=image_height, background=Color("LIGHTCYAN")) as img:
        with Drawing() as draw: 
            for i,line in enumerate(lines):
                metrics = draw.get_font_metrics(img, line, multiline=True)
                last_idx = 1
                # Do we need to do work?
                while metrics.text_width > right_margin:
                    last_breakpoint=0
                    # Scan text for possible breakpoints.
                    for idx in range(last_idx, len(line)):
                        if line[idx] == ' ':
                            last_breakpoint = idx
                        else:
                            # Determine if we need to insert a breakpoint.
                            metrics = draw.get_font_metrics(img, line[:idx], multiline=True)
                            if metrics.text_width >= right_margin:
                                line = line[:last_breakpoint].strip() + '\n' + line[last_breakpoint:].strip()
                                last_idx = last_breakpoint
                                break
                    # Double check any modifications to text was successful enough.
                    metrics = draw.get_font_metrics(img, line, multiline=True)
                draw.text(x=left_margin, y=top_margin + line_offset, body=line)
                line_offset += int(metrics.text_height) + line_padding
            draw(img)
            img.save(filename="output.png")

output

上面的代码可以优化,Python可能已经包含一些better methods

进一步阅读...

source code ImageMagick的CAPTION:协议就是一个很好的例子。该算法反复调用GetMultilineTypeMetricsFormatMagickCaption来调整磅值并插入换行符。 魔杖库并不真正支持字幕协议,但是您可以使用以下解决方法来解决它。

from wand.api import library
# ...
with Image(width=image_width, height=image_height, background=Color("LIGHTCYAN")) as img:
    for i,line in enumerate(lines):
        # Create a tempory image for each bounding box
        with Image() as throwaway:
            library.MagickSetSize(throwaway.wand, right_margin, line_padding)
            throwaway.read(filename='CAPTION:'+line)
            img.composite(throwaway, left_margin, top_margin + line_offset)
            line_offset += line_padding + throwaway.height
    img.save(filename="output.png")