Coverage for paintmaskanimator/movie_slate.py: 98%
36 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 04:50 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 04:50 +0000
1"""ムービー書き出しの頭に出すカット名(Issue #26)。
3動画を書き出して流して見るとき、どのカットのものか分からなくなる。頭の数コマ
4だけカット名を太字で重ねておくと、ファイル名を見に行かずに済む。
6コマを足すのではなく最初の数コマへ重ねるので、タイミングは変わらない。
7"""
8from PySide6.QtCore import QRect, Qt
9from PySide6.QtGui import QColor, QFont, QImage, QPainter
11#: カット名を重ねるコマ数。
12LEADING_FRAMES = 8
13#: 画像の高さに対する文字の大きさ。
14_FONT_SCALE = 0.07
15#: 画面端からの余白(画像の高さに対する割合)。
16_MARGIN_SCALE = 0.04
19def cut_name_for(project_path, fallback=""):
20 """書き出すカット名。プロジェクトのファイル名を使う。"""
21 if project_path:
22 from pathlib import Path
24 stem = Path(str(project_path)).stem.strip()
25 if stem: 25 ↛ 27line 25 didn't jump to line 27 because the condition on line 25 was always true
26 return stem
27 return str(fallback or "").strip()
30def draw_cut_name(image: QImage, name: str) -> QImage:
31 """``image`` の左下へ ``name`` を太字で重ねた新しい画像を返す。
33 暗い絵でも明るい絵でも読めるよう、黒い縁取りの上に白で描く。
34 """
35 name = str(name or "").strip()
36 if not name or image is None or image.isNull():
37 return image
39 result = QImage(image)
40 height = result.height()
41 font = QFont()
42 font.setBold(True)
43 font.setPixelSize(max(12, int(height * _FONT_SCALE)))
45 painter = QPainter(result)
46 painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, True)
47 painter.setFont(font)
48 margin = max(6, int(height * _MARGIN_SCALE))
49 rect = QRect(
50 margin,
51 margin,
52 max(1, result.width() - margin * 2),
53 max(1, result.height() - margin * 2),
54 )
55 alignment = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBottom
56 # 縁取り:8方向へずらして黒で描いてから、白を重ねる。
57 painter.setPen(QColor("black"))
58 for dx in (-2, 0, 2):
59 for dy in (-2, 0, 2):
60 if dx or dy:
61 painter.drawText(rect.translated(dx, dy), alignment, name)
62 painter.setPen(QColor("white"))
63 painter.drawText(rect, alignment, name)
64 painter.end()
65 return result