LoginSignup
0
0

HTMLタグ内のカラーコードをPillowで適用する【Python】

Posted at

初めに

これが

'<span style="color: #0000FF">これが青い</span>、またhogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehoge<span class="font-bold" style="color: #FEDCBA">別の色</span>、<span class="font-bold" style="color: #777777">これがグレー</span>、<span class="font-bold" style="color: #FFFF00">これが黄色い</span>、',

こうなります。
スクリーンショット 2023-09-22 112153.png

HTMLを処理して何かするときに使えます。

仕様

<span ~ から始まる部分を探して、その中身を指定された色で描画できます。divだったりclassで指定されてる場合は適宜置き換えてください。

例:

<div class="red_txt">hoge</div>

だった場合、cssなどから色を取得して置き換える

<span style="color: #FF0000">hoge</span>

コード

以下がコードになります。

main.py
def despan_draw(draw, font_file, text, font_size, starcord):
    x_pos = starcord[0]
    y_pos = starcord[1]
    pattern = re.compile(
        r'<span[^>]*style="color: #[a-zA-Z0-9].....">(.*?)<\/span>',
        re.DOTALL,
    )
    lines = text.split("\n")
    for line in lines:
        if "<span" in line:
            amount = line.count("<span")
            for i in range(amount):
                start_idx = line.find("<span")
                end_idx = line.find("</span>")
                if start_idx != -1 and end_idx != -1:
                    style = line[start_idx : end_idx + 7]  # '<span ... </span>' の部分
                    color_start_idx = style.find("color:")
                    if color_start_idx != -1:
                        color_hex = style[color_start_idx + 8 : color_start_idx + 14]
                        text_color = tuple(
                            int(color_hex[i : i + 2], 16) for i in (0, 2, 4)
                        )
                # マッチした部分を抽出
                match = pattern.search(line)
                if match:
                    x = x_pos
                    span_text = match.group(1)
                    line = pattern.sub(rf"{span_text}", line, count=1)
                    span_start = line.find(span_text)
                    ct = 0
                    for char in line:
                        if char == "<":
                            x_pos = x
                            break
                        line = line[1:]
                        if ct >= span_start and ct < span_start + len(span_text):
                            char_color = text_color
                        else:  # その他の部分
                            char_color = (255, 255, 255)
                        draw.text(
                            (x, y_pos),
                            char,
                            fill=char_color,
                            font=ImageFont.truetype(font_file, font_size),
                        )
                        char_bbox = draw.textbbox(
                            (x, y_pos),
                            char,
                            font=ImageFont.truetype(font_file, font_size),
                        )
                        char_width = char_bbox[2] - char_bbox[0]
                        x += char_width
                        ct += 1
                        # ここで改行もできる(適宜調整)
                        if x >= 2000:
                            x = starcord[0]
                            y_pos += font_size
        else:
            # 普通の文字列
            draw.text(
                (int(x_pos), int(y_pos)),
                line,
                fill=(255, 255, 255),
                font=ImageFont.truetype(font_file, font_size),
            )
        y_pos += font_size
        x_pos = starcord[0]

上記の関数を呼び出すことで描画されます。

main.py
def draw_image(font_file):
    canvas = Image.new("RGBA", (2048, 1024), (255, 255, 255, 0))
    draw = ImageDraw.Draw(canvas)

    despan_draw(
        draw,
        font_file,
        '<span class="font-bold" style="color: #0000FF">これが青い</span>、またhogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehoge<span class="font-bold" style="color: #FEDCBA">別の色</span>、<span class="font-bold" style="color: #777777">これがグレー</span>、<span class="font-bold" style="color: #FFFF00">これが黄色い</span>、',
        20,
        (50, 100),
    )
    canvas.save("test.png")
    print("保存:test.png")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0