콘텐츠로 이동
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의 사각형입니다. 별도 도형이므로 두 줄 제목에 맞춰 위치와 높이(176px)를 직접 정합니다.
  • 출처 줄은 텍스트 레이어 하나입니다. 두 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')}")