You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python实现将文本适配到图片中的指定矩形区域

文本动态适配矩形区域实现方案

核心实现逻辑

无需手动猜测字号的核心思路是用二分法迭代匹配最大可用字号,所有技术栈通用:

  • 先设定字号的上下边界:最小值设为1px,最大值直接取矩形区域的高度(单一行文本的字号不可能超过矩形高度)
  • 每次取上下边界的中间值作为测试字号,用该字号计算文本自动换行后的整体渲染高度
  • 如果渲染总高度≤矩形高度、且所有单行宽度≤矩形宽度,说明还有放大空间,将字号下边界上调到中间值;如果超出范围就把上边界下调到中间值
  • 迭代到上下边界差值小于1px为止,此时的字号就是当前矩形能容纳的最大可用字号

分场景实现示例

前端Canvas场景

function getMaxFontSize(ctx, text, rectWidth, rectHeight, fontFace = 'Verdana') {
  let minSize = 1;
  let maxSize = rectHeight;
  let bestSize = minSize;
  const lineHeightRatio = 1.2; // 可根据排版需求调整行高系数

  // 二分法迭代找最佳字号
  while (maxSize - minSize > 1) {
    const midSize = Math.floor((minSize + maxSize) / 2);
    ctx.font = `${midSize}px ${fontFace}`;
    const lines = [];
    let currentLine = '';
    // 中文按单个字符拆分,英文场景可改为按空格拆分避免单词断行
    const chars = text.split('');
    
    // 计算自动换行后的行列表
    for (const char of chars) {
      const testLine = currentLine + char;
      const lineWidth = ctx.measureText(testLine).width;
      if (lineWidth > rectWidth && currentLine !== '') {
        lines.push(currentLine);
        currentLine = char;
      } else {
        currentLine = testLine;
      }
    }
    lines.push(currentLine);

    // 校验总高度是否符合要求
    const totalHeight = lines.length * midSize * lineHeightRatio;
    if (totalHeight <= rectHeight) {
      bestSize = midSize;
      minSize = midSize;
    } else {
      maxSize = midSize;
    }
  }
  // 返回最佳字号和拆分好的行列表,直接逐行绘制到Canvas对应区域即可
  return { fontSize: bestSize, lines: lines };
}

Python Pillow 图片处理场景

from PIL import Image, ImageDraw, ImageFont

def get_max_font_size(text, rect_width, rect_height, font_path="verdana.ttf", line_height_ratio=1.2):
    min_size = 1
    max_size = rect_height
    best_size = min_size
    best_lines = []

    while max_size - min_size > 1:
        mid_size = (min_size + max_size) // 2
        font = ImageFont.truetype(font_path, mid_size)
        lines = []
        current_line = ""

        for char in text:
            test_line = current_line + char
            line_width = font.getsize(test_line)[0]
            if line_width > rect_width and current_line:
                lines.append(current_line)
                current_line = char
            else:
                current_line = test_line
        lines.append(current_line)

        total_height = len(lines) * mid_size * line_height_ratio
        if total_height <= rect_height:
            best_size = mid_size
            best_lines = lines
            min_size = mid_size
        else:
            max_size = mid_size
    return {"font_size": best_size, "lines": best_lines, "font": ImageFont.truetype(font_path, best_size)}

如果系统没有预装Verdana字体,把font_path参数替换为你本地Verdana字体文件的绝对路径即可。

内容的提问来源于stack exchange,提问作者Mattlau04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 05:00:02