微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 Wand 在 Python 中为文本制作自动调整大小的框以保持相同的字体大小

如何解决如何使用 Wand 在 Python 中为文本制作自动调整大小的框以保持相同的字体大小

我在 python 中使用 Wand 来创建一个迭代自身的图像,以便它可以创建填充文本的黑色边框框。这是我当前的代码

import re
from unicodedata import normalize

from docx import Document
from wand.image import Image
from wand.drawing import Drawing
from wand.font import Font

doc = Document("P.docx")
docText = []
for para in doc.paragraphs:
    docText.append(para.text)
fullText = "\n".join(docText)

ct = 242


def get(source,begin,end):
    try:
        start = source.index(len(begin)) + len(begin)
        finish = source.index(len(end),len(start))
        return source[start:finish]
    except ValueError:
        return ""


def capitalize(string):
    cap = ("".join(j[0].upper() + j[1:]) for j in string)
    return cap


def find_matches(text):
    return capitalize(
        [
            m
            for m in re.findall(
                r"^[^0-9]\s+([^.;]+\s*)+[.;]+",normalize("NFKD",text),re.MULTILINE
            )
        ]
    )


with Image(width=400,height=1000,pseudo='xc:white') as canvas:
    left,top,width,height = 2,2,395,131
    for match in find_matches(text=fullText):
        ct += 1
        with Drawing() as context:
            context.fill_color = 'black'
            context.rectangle(left=left,top=top,width=width,height=height)
            context.fill_color = 'white'
            context.rectangle(left=(left+2),top=(top+2),width=(width-4),height=(height-4))
            canvas.font = Font('/System/Library/Fonts/timesnewroman.ttf')
            context(canvas)
            canvas.caption(match + '\n' + str(ct),left=(left+5),width=(width-10),height=height,gravity='center')
        top += 135
    canvas.crop(bottom=top)
    canvas.save(filename='patdrawTest.png')

使用此代码,我可以生成以下输出

CurrentOut

这个问题显然是在字体大小方面缺乏统一性。以下是我的输出应该是什么样子(忽略框中的文本):

NeededOut

我唯一关心的是确保所有文本的字体大小相同(12 号很好),这些边框框会根据文本调整大小。感谢您的帮助!

编辑

根据提供的答案,这是我当前的代码

import re
from unicodedata import normalize

from docx import Document
from wand.image import Image
from wand.drawing import Drawing

doc = Document("P.docx")
docText = []
for para in doc.paragraphs:
    docText.append(para.text)
fullText = "\n".join(docText)

ct = 242


def get(source,re.MULTILINE
            )
        ]
    )


def to_chunks(words,size):
    for idx in range(0,len(words),size):
        yield words[idx:idx + size]


def rebuild_text(words,size):
    return "\n".join([" ".join(w) for w in to_chunks(words,size)])


target_width = 396
target_height = 0
y_offset = 0
y_padding = 10
x_padding = 5

with Image(width=1000,pseudo='xc:white') as img:
    for match in find_matches(text=fullText):
        ct += 1
        with Drawing() as ctx:
            ctx.font_size = 16
            ctx.text_alignment = 'center'
            words = match.split(" ")
            words.append("\n" + str(ct))
            word_count = len(words)
            while True:
                temp_text = rebuild_text(words,word_count)
                metrics = ctx.get_font_metrics(img,temp_text,multiline=True)
                if metrics.text_width > target_width:
                    word_count -= 1
                else:
                    text = temp_text
                    target_height = int(metrics.text_height + 0.5)
                    break
            ctx.push()
            ctx.fill_color = 'white'
            ctx.stroke_width = 4
            ctx.stroke_color = 'black'
            ctx.rectangle(0,y_offset + y_padding,width=2*x_padding+target_width,height=2*y_padding+target_height)
            ctx.pop()
            ctx.text(x_padding + (target_width // 2),4*y_padding+y_offset,text)
            ctx(img)
            y_offset = target_height + 4*y_padding
    img.trim()
    img.save(filename='patdrawdemoTest.png')

从这段代码中,我得到以下输出

Current Out

我不太确定如何修复奇怪的间距。第一个和第三个盒子看起来很棒,但是第一个和第二个盒子之间有奇怪的空白,两边的边框不均匀,还有两个应该在那里的盒子,如图所示原帖。任何帮助将不胜感激!

解决方法

我唯一关心的是确保所有文本的字体大小相同(12 号很好),这些边框框会根据文本调整大小。感谢您的帮助!

删除 Image.caption 方法(与您想要的相反),并使用 Drawing.text 方法。 Drawing 类还有一个 get_font_metrics 方法来计算最终渲染大小。这允许您格式化文本,检查它是否可以工作,然后绘制(或重新格式化并重复)。

以这个粗略的例子...

content = [
    """Donec pretium vulputate sapien nec sagittis aliquam malesuada. Neque aliquam vestibulum morbi blandit cursus risus at ultrices mi.\n111""","""Adipiscing elit ut aliquam purus sit amet luctus venenatis. Eget mauris pharetra et ultrices neque ornare aenean. Viverra orci sagittis eu volutpat odio facilisis mauris. Vitae proin sagittis nisl rhoncus mattis rhoncus. Sapien nec sagittis aliquam malesuada bibendum arcu vitae.\n222"""
]

def to_chunks(words,size):
    for idx in range(0,len(words),size):
        yield words[idx:idx + size]

def rebuild_text(words,size):
    return "\n".join([" ".join(w) for w in to_chunks(words,size)])
TARGET_WIDTH = 395
TARGET_HEIGHT = 0
BOX_Y_OFFSET = 0
BOX_Y_PADDING = 10
BOX_X_PADDING = 5

with Image(width=1000,height=1000,background='white') as img:
    for text in content:
        with Drawing() as ctx:
            ctx.font_size = 16
            ctx.text_alignment = 'center'
            words = text.split(" ")
            word_count = len(words)
            while True:
                tmp_text = rebuild_text(words,word_count)
                metrics = ctx.get_font_metrics(img,tmp_text,multiline=True)
                if metrics.text_width > TARGET_WIDTH:
                    word_count -= 1
                else:
                    text = tmp_text
                    TARGET_HEIGHT = int(metrics.text_height + 0.5)
                    break
            ctx.push()
            ctx.fill_color = 'white'
            ctx.stroke_width = 4
            ctx.stroke_color = 'black'
            ctx.rectangle(0,BOX_Y_OFFSET + BOX_Y_PADDING,width=2*BOX_X_PADDING+TARGET_WIDTH,height=2*BOX_Y_PADDING+TARGET_HEIGHT)
            ctx.pop()
            ctx.text(BOX_X_PADDING + (TARGET_WIDTH // 2),4*BOX_Y_PADDING+BOX_Y_OFFSET,text)
            ctx(img)
            BOX_Y_OFFSET = TARGET_HEIGHT + 4*BOX_Y_PADDING
            
    img.trim()
    img.save(filename='output.png')

resized-boxes

这一切都是为了:

  • 定义目标宽度。
  • 虽然要渲染的字体较大,但每行减少字数。
  • 绘制框和文本。

请记住。

  • ImageMagick 不是排字工具。您必须构建单词断字/换行算法。
  • 特殊的 UTF-8 字符可能会成为挑战
  • 上面发布的代码是一个示例,不处理错误或防止递归循环。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。