Instagramカード

写真、赤いラベル、セリフ体の見出し、出典の行を組み合わせた正方形のニュースカードです。
実行するには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')}")