コンテンツにスキップ
quickthumb
すべてのドキュメント

Instagramカード

炎の写真に「Wildfires Spread Across 18,000 Acres」と記した正方形の速報カード

写真、赤いラベル、セリフ体の見出し、出典の行を組み合わせた正方形のニュースカードです。

実行するにはuvをインストールし、リポジトリをクローンしてください。

git clone https://github.com/sjquant/quickthumb
cd quickthumb
uv run python examples/instagram_news_card.py

examples/instagram_news_card.pngを保存します。同名のファイルがあれば上書きします。

作り方

  • ラベルはBackground付きのテキストです。 Background(color="#CC0000", padding=(11, 22))が「BREAKING NEWS」の周りに赤い枠を描きます。別の図形を手で調整する必要はなく、文字に合わせて大きくなります。
  • 見出しだけ別のフォントを使います。 font="NotoSerif"で同梱フォルダーからセリフ体を読み込み、それ以外は既定のRobotoを使います。
  • 赤い縦線は幅9pxの長方形です。 独立した図形なので、2行の見出しに合わせて位置と高さ(176px)を指定します。
  • 出典は1枚のテキストレイヤーです。 2つのTextPartで「WORLD NEWS」と日付の色や太さを変えます。
  • 位置は主に百分率で指定します。 ("8%", "92%")のようにするとキャンバスとともに拡大縮小します。赤い縦線だけは、見出しに正確に揃えるためピクセル指定です。

コード

"""
Instagram News Card Example

Creates a breaking news-style Instagram card (1080x1080) with:
- Fire background image (cover fit, darkened)
- Dark gradient overlay for text legibility
- "BREAKING NEWS" badge
- Bold headline with stroke
- Source and timestamp at the bottom
"""

import os

from quickthumb import Canvas, Filter, FitMode, LinearGradient, TextPart
from quickthumb.models import Background, Shadow, Stroke

FILE_DIR = os.path.dirname(__file__)
ASSETS_DIR = os.path.join(FILE_DIR, "..", "assets")

os.environ["QUICKTHUMB_FONT_DIR"] = os.path.join(ASSETS_DIR, "fonts")
os.environ["QUICKTHUMB_DEFAULT_FONT"] = "Roboto"

SIZE = 1080

(
    Canvas(SIZE, SIZE)
    # 1. Background: fire image, cropped to fill the square
    .background(
        image=os.path.join(ASSETS_DIR, "images", "tobias-rademacher-wnF27F85ZKw-unsplash.jpg"),
        fit=FitMode.COVER,
        effects=[Filter(brightness=0.9, contrast=1.1, saturation=0.9)],
    )
    # 2. Dark gradient overlay — bottom two-thirds darkened for text legibility
    .background(
        gradient=LinearGradient(
            angle=90,
            stops=[("#00000000", 0.0), ("#000000B8", 0.42), ("#000000F2", 1.0)],
        ),
    )
    .text(
        content="LIVE  /  20:42 UTC",
        size=19,
        color="#FFFFFFAA",
        weight=700,
        letter_spacing=3,
        position=("8%", "6%"),
        align=("left", "top"),
    )
    .shape(
        shape="rectangle",
        position=("8%", "11%"),
        width=908,
        height=2,
        color="#FFFFFF44",
    )
    # 3. "BREAKING NEWS" badge near the top
    .text(
        content="BREAKING NEWS",
        size=28,
        color="#FFFFFF",
        weight=900,
        letter_spacing=4,
        position=("8%", "15%"),
        align=("left", "top"),
        effects=[
            Background(color="#CC0000", padding=(11, 22), border_radius=2),
        ],
    )
    .shape(
        shape="rectangle",
        position=("8%", 464),
        width=9,
        height=176,
        color="#E11D2E",
        border_radius=4,
    )
    # 4. Main headline — large, bold, white with shadow
    .text(
        content="Wildfires Spread\nAcross 18,000 Acres",
        font="NotoSerif",
        size=84,
        color="#FFFFFF",
        weight=900,
        position=("11%", "52%"),
        align=("left", "middle"),
        line_height=1.12,
        effects=[
            Stroke(width=1, color="#000000"),
            Shadow(offset_x=0, offset_y=6, color="#000000AA", blur_radius=10),
        ],
    )
    # 5. Source and timestamp row
    .text(
        content=[
            TextPart(text="WORLD NEWS  ", color="#FF4444", weight=700),
            TextPart(text="·  Feb 20, 2026", color="#AAAAAA", weight=400),
        ],
        size=30,
        position=("8%", "92%"),
        align=("left", "top"),
    )
    # Render
    .render(os.path.join(FILE_DIR, "instagram_news_card.png"))
)

print(f"✓ Instagram news card created: {os.path.join(FILE_DIR, 'instagram_news_card.png')}")