render-publication-graphic
について
このスキルは、印刷物とデジタルメディアの両方に対応した、出版品質の2Dグラフィックスを適切なDPI、カラープロファイル、タイポグラフィで生成します。学術雑誌、印刷出版物、またはウェブ最適化されたビジュアライゼーションの図版を、特定の出版社仕様に準拠させながら準備するためにご利用ください。単一ソースからのマルチフォーマット出力を処理し、技術的な準拠を保証します。
クイックインストール
Claude Code
推奨npx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/render-publication-graphicこのコマンドをClaude Codeにコピー&ペーストしてスキルをインストールします
ドキュメント
渲染出版圖形
製作合學術期刊、書籍、簡報與網路出版技術需求之發布級圖形。涵蓋 DPI 需求、色空間管理、排版最佳實踐、文件格式選擇與元資料嵌入。
適用時機
- 為學術期刊投稿備圖
- 為印刷出版(書、雜誌)建圖
- 為簡報生高品質資產
- 為網路出版以適當優化匯出視覺化
- 確圖形合出版者技術規範
- 帶適當元資料歸檔圖形
- 自單一源建多格式匯出
輸入
| 輸入 | 類型 | 描述 | 例 |
|---|---|---|---|
| Source graphic | File/Data | 原視覺化或藝術品 | SVG, R ggplot, Python matplotlib, Blender render |
| Publication target | Specification | 期刊、網路、印刷、簡報 | Nature journal, IEEE paper, website |
| Technical requirements | Parameters | DPI、尺寸、色空間、格式 | 300 DPI, 180mm width, CMYK, TIFF |
| Style guide | Document | 出版者排版與格式規 | Font families, line widths, color palette |
| Metadata | Information | 標題、作者、日期、版權、描述 | Figure caption, license info |
步驟
1. 定輸出需求
辨識目標出版之技術規範:
# Common publication requirements
academic_journal:
dpi: 300-600
format: TIFF, EPS, PDF
color_space: RGB or CMYK (check guidelines)
max_width: 180mm (single column) or 390mm (double column)
fonts: Embed or outline
resolution_minimums:
line_art: 1000 DPI
halftone: 300 DPI
combination: 600 DPI
web_publication:
dpi: 72-96 (retina: 144-192)
format: PNG, WebP, SVG
color_space: sRGB
max_file_size: 200KB-500KB
optimization: Compress, progressive loading
presentation:
dpi: 96-150
format: PNG, PDF, SVG
color_space: RGB
dimensions: 16:9 or 4:3 aspect ratio
contrast: High contrast for projectors
print_book:
dpi: 300-600
format: TIFF, PDF/X
color_space: CMYK
bleed: 3-5mm beyond trim
fonts: Embedded
預期: 對目標需求有明確理解 失敗時: 聯繫出版者問特定指南,用保守預設
2. 為點陣圖形設正確 DPI
依輸出媒體配置解析度:
from PIL import Image
def set_dpi_pillow(image_path, output_path, target_dpi=300):
"""Set DPI metadata for PNG/TIFF."""
img = Image.open(image_path)
# Save with DPI metadata
img.save(output_path, dpi=(target_dpi, target_dpi))
print(f"Saved with {target_dpi} DPI: {output_path}")
def calculate_dimensions(width_mm, height_mm, dpi=300):
"""Calculate pixel dimensions from physical size."""
# Convert mm to inches
width_inches = width_mm / 25.4
height_inches = height_mm / 25.4
# Calculate pixels
width_px = int(width_inches * dpi)
height_px = int(height_inches * dpi)
return width_px, height_px
# Example: 180mm wide figure at 300 DPI
width, height = calculate_dimensions(180, 120, dpi=300)
print(f"Required resolution: {width}x{height} pixels")
# Output: Required resolution: 2126x1417 pixels
# R ggplot2 export with proper DPI
library(ggplot2)
# Create plot
p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
theme_minimal(base_size = 12)
# Save for publication (300 DPI)
ggsave(
filename = "figure1.png",
plot = p,
width = 180,
height = 120,
units = "mm",
dpi = 300
)
# Save as vector for flexibility
ggsave(
filename = "figure1.pdf",
plot = p,
width = 180,
height = 120,
units = "mm",
device = cairo_pdf # Better text rendering
)
預期: 圖形以印刷品質之正確解析度渲染 失敗時: 驗 DPI 元資料正確存入,檢文件大小適當
3. 配置色空間
設適當之色彩設定檔:
from PIL import Image, ImageCms
def convert_to_cmyk(rgb_image_path, cmyk_output_path):
"""Convert RGB to CMYK for print."""
img = Image.open(rgb_image_path)
if img.mode != 'RGB':
img = img.convert('RGB')
# Convert to CMYK
cmyk_img = img.convert('CMYK')
cmyk_img.save(cmyk_output_path, format='TIFF', compression='tiff_lzw')
print(f"Converted to CMYK: {cmyk_output_path}")
def apply_srgb_profile(image_path, output_path):
"""Apply sRGB profile for web."""
img = Image.open(image_path)
# sRGB profile (embedded in Pillow)
srgb_profile = ImageCms.createProfile('sRGB')
# Convert to sRGB
img_srgb = ImageCms.profileToProfile(
img,
srgb_profile,
srgb_profile,
renderingIntent=ImageCms.Intent.PERCEPTUAL
)
img_srgb.save(output_path)
# ImageMagick for color space conversion
convert input.png -colorspace sRGB output_srgb.png
convert input.png -colorspace CMYK output_cmyk.tiff
# Check color profile
identify -verbose image.png | grep -i colorspace
預期: 色空間合出版需求 失敗時: 驗色彩設定檔已嵌,試印預覽
4. 配置排版
確保文字可讀且格式得當:
from PIL import ImageFont
def get_publication_fonts():
"""Load fonts appropriate for publication."""
# Common publication-safe fonts
fonts = {
'serif': 'Times New Roman',
'sans': 'Arial',
'mono': 'Courier New'
}
try:
# Load with proper size for DPI
# At 300 DPI, 12pt = 12 * 300/72 = 50 pixels
base_size_300dpi = 50
font_regular = ImageFont.truetype(f"{fonts['sans']}.ttf", base_size_300dpi)
font_bold = ImageFont.truetype(f"{fonts['sans']} Bold.ttf", base_size_300dpi)
return {'regular': font_regular, 'bold': font_bold}
except:
return {'regular': ImageFont.load_default(), 'bold': ImageFont.load_default()}
# Typography guidelines
typography_specs = {
'minimum_font_size': '8pt', # Readable when printed
'line_width_min': 0.5, # Points, for print clarity
'panel_labels': {
'font': 'Arial Bold',
'size': '12pt',
'position': 'top-left',
'style': 'A, B, C' # Or (a), (b), (c)
},
'axis_labels': {
'font': 'Arial',
'size': '10pt'
},
'legend': {
'font': 'Arial',
'size': '9pt',
'position': 'outside plot area'
}
}
# R publication-quality typography
library(ggplot2)
p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point(size = 2) +
labs(
title = "Fuel Efficiency vs Weight",
x = "Weight (1000 lbs)",
y = "Miles per Gallon"
) +
theme_bw(base_size = 12, base_family = "Arial") +
theme(
plot.title = element_text(size = 14, face = "bold"),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
legend.text = element_text(size = 10),
panel.grid.minor = element_blank(),
# Ensure text is black for print
text = element_text(color = "black")
)
預期: 文字於出版尺寸下可讀,字體正確嵌入 失敗時: 增大字號,檢字體授權,將文字轉為輪廓
5. 選適當之文件格式
依用例擇格式:
def export_multi_format(source_path, output_base, formats=['png', 'pdf', 'tiff']):
"""Export graphic in multiple formats."""
from PIL import Image
import cairosvg
import os
base, ext = os.path.splitext(output_base)
if ext.lower() in ['.svg']:
# SVG source - convert to rasters
for fmt in formats:
output = f"{base}.{fmt}"
if fmt == 'png':
cairosvg.svg2png(
url=source_path,
write_to=output,
output_width=2126, # 180mm @ 300 DPI
output_height=1417 # 120mm @ 300 DPI
)
elif fmt == 'pdf':
cairosvg.svg2pdf(url=source_path, write_to=output)
elif fmt == 'tiff':
# Convert via PNG intermediate
temp_png = f"{base}_temp.png"
cairosvg.svg2png(url=source_path, write_to=temp_png)
img = Image.open(temp_png)
img.save(output, format='TIFF', compression='tiff_lzw')
os.remove(temp_png)
else:
# Raster source
img = Image.open(source_path)
for fmt in formats:
output = f"{base}.{fmt}"
if fmt == 'png':
img.save(output, format='PNG', dpi=(300, 300), optimize=True)
elif fmt == 'tiff':
img.save(output, format='TIFF', compression='tiff_lzw', dpi=(300, 300))
elif fmt == 'pdf':
# Use img2pdf or similar for raster-to-PDF
img.save(output, format='PDF', resolution=300.0)
print(f"Exported in formats: {', '.join(formats)}")
# Format selection guide
format_guide = {
'TIFF': {
'use_for': 'Journal submission, archival',
'benefits': 'Lossless, supports CMYK, high quality',
'compression': 'LZW or ZIP (lossless)'
},
'PDF': {
'use_for': 'Submission, print, archival',
'benefits': 'Vector or raster, text searchable, widely accepted',
'variants': 'PDF/A (archival), PDF/X (print)'
},
'PNG': {
'use_for': 'Web, presentations, digital',
'benefits': 'Lossless, transparency, good compression',
'limitation': 'RGB only, larger than JPEG'
},
'SVG': {
'use_for': 'Web, further editing, scalable graphics',
'benefits': 'Vector, infinitely scalable, small file size',
'limitation': 'Not always accepted by journals'
},
'EPS': {
'use_for': 'Legacy journal requirements',
'benefits': 'Vector format accepted by older systems',
'limitation': 'Being phased out, use PDF instead'
}
}
預期: 適合出版渠道之格式 失敗時: 檢出版者要求,提供多種格式
6. 為網路優化
建網路優化版本:
def optimize_for_web(input_path, output_path, max_width=1200, quality=85):
"""Optimize image for web publication."""
from PIL import Image
img = Image.open(input_path)
# Resize if too large
if img.width > max_width:
ratio = max_width / img.width
new_height = int(img.height * ratio)
img = img.resize((max_width, new_height), Image.LANCZOS)
# Convert to RGB if needed
if img.mode in ('RGBA', 'LA', 'P'):
background = Image.new('RGB', img.size, (255, 255, 255))
if img.mode == 'P':
img = img.convert('RGBA')
background.paste(img, mask=img.split()[-1] if 'A' in img.mode else None)
img = background
# Save optimized
img.save(output_path, format='JPEG', quality=quality, optimize=True, progressive=True)
# Check file size
import os
file_size_kb = os.path.getsize(output_path) / 1024
print(f"Optimized: {file_size_kb:.1f} KB")
def create_responsive_set(input_path, output_base):
"""Create multiple resolutions for responsive web."""
from PIL import Image
img = Image.open(input_path)
sizes = [
(640, '640w'),
(1024, '1024w'),
(1920, '1920w')
]
for width, suffix in sizes:
if img.width >= width:
ratio = width / img.width
height = int(img.height * ratio)
resized = img.resize((width, height), Image.LANCZOS)
output = f"{output_base}_{suffix}.jpg"
resized.save(output, format='JPEG', quality=85, optimize=True)
預期: 網路優化圖像於 500KB 下,已生響應式尺寸 失敗時: 降品質、再縮小、考慮 WebP 格式
7. 嵌入元資料
加描述性元資料以資歸檔:
from PIL import Image
from PIL.PngImagePlugin import PngInfo
def embed_metadata(image_path, output_path, metadata):
"""Embed metadata in PNG."""
img = Image.open(image_path)
# Create metadata
png_info = PngInfo()
for key, value in metadata.items():
png_info.add_text(key, str(value))
# Save with metadata
img.save(output_path, format='PNG', pnginfo=png_info)
# Example metadata
metadata = {
'Title': 'Figure 1: Relationship between weight and fuel efficiency',
'Author': 'Jane Doe',
'Description': 'Scatter plot showing negative correlation',
'Copyright': 'CC-BY 4.0',
'Software': 'R 4.3.0, ggplot2 3.4.0',
'Creation Date': '2026-02-16',
'Source': 'mtcars dataset'
}
embed_metadata('figure1.png', 'figure1_with_metadata.png', metadata)
預期: 元資料已嵌且可取 失敗時: 檢格式支援元資料(PNG、TIFF、PDF 是;JPEG 受限)
驗證
- DPI 合出版需求(典型 300+)
- 物理尺寸合出版正確
- 色空間適當(網用 RGB,印用 CMYK)
- 文件格式為出版者所受
- 文字於出版尺寸下可讀
- 字體已嵌或輪廓化
- 線寬印時可見
- 灰階印之色對比足
- 文件大小於限內
- 元資料已嵌
- 已測印預覽或渲染
常見陷阱
- 解析度不足:72 DPI 網路圖形無法以品質印刷
- 錯之色空間:RGB 圖形印之或異於顯示
- 字體替換:未嵌之字體被預設替換
- 文字過小:8pt 下之字體印之或不可讀
- 線過細:0.5pt 下之線印之或不清
- 文件大小:高 DPI 圖形可能極大,宜適當壓縮
- 壓縮偽影:JPEG 壓縮不宜用於線稿或文字
- 缺出血:印刷圖形需 3-5mm 出血外於裁切
- 透明問題:某些格式不能正確保留透明
- 寬高比:尺寸計算錯致變形
相關技能
- create-2d-composition:建源圖形
- render-blender-output:出版用之 3D 渲染設定
- generate-quarto-report:將圖形整合入文件
GitHub リポジトリ
関連スキル
content-collections
メタこのスキルは、Content Collections(Markdown/MDXファイルを型安全なデータコレクションに変換するTypeScriptファーストのツール)の本番環境でテストされた設定を提供します。Zodバリデーションによる型安全性を実現し、ブログ、ドキュメントサイト、コンテンツ重視のVite + Reactアプリケーション構築時にご利用ください。Viteプラグインの設定、MDXコンパイルから、デプロイ最適化、スキーマバリデーションまで、すべてを網羅しています。
polymarket
メタこのスキルは、開発者がPolymarket予測市場プラットフォームを活用したアプリケーション構築を可能にします。API統合による取引や市場データの取得に加え、WebSocketを介したリアルタイムデータストリーミングにより、ライブ取引や市場活動を監視できます。取引戦略の実装や、ライブ市場更新を処理するツールの作成にご利用ください。
creating-opencode-plugins
メタこのスキルは、開発者がコマンド、ファイル、LSP操作など25種類以上のイベントタイプにフックするOpenCodeプラグインを作成することを支援します。JavaScript/TypeScriptモジュール向けに、プラグイン構造、イベントAPI仕様、および実装パターンを提供します。カスタムイベント駆動ロジックでOpenCode AIアシスタントのライフサイクルをインターセプト、監視、または拡張する必要がある場合にご利用ください。
sglang
メタSGLangは、高性能なLLMサービングフレームワークであり、RadixAttentionプレフィックスキャッシュを活用したJSON、正規表現、エージェントワークフロー向けの高速で構造化された生成を特長とします。特にプレフィックスが繰り返されるタスクにおいて、大幅に高速な推論を実現し、複雑な構造化出力やマルチターン対話に最適です。制約付きデコードが必要な場合や、広範なプレフィックス共有を伴うアプリケーションを構築する場合は、vLLMなどの代替案ではなくSGLangを選択してください。
