thumbnail-maker 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of thumbnail-maker might be problematic. Click here for more details.

@@ -0,0 +1,9 @@
1
+ """
2
+ 썸네일 생성기 패키지
3
+ """
4
+
5
+ from .renderer import ThumbnailRenderer
6
+
7
+ __version__ = "0.1.0"
8
+ __all__ = ["ThumbnailRenderer"]
9
+
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ thumbnail_maker: 단일 엔트리포인트 (subcommands: gui, generate-thumbnail, genthumb)
5
+ """
6
+
7
+ import sys
8
+ import argparse
9
+
10
+ from .gui import main as gui_main
11
+ from .cli import main as generate_main, main_cli as genthumb_main
12
+
13
+
14
+ def main() -> None:
15
+ parser = argparse.ArgumentParser(prog='thumbnail_maker', description='썸네일 메이커')
16
+ subparsers = parser.add_subparsers(dest='command', required=True)
17
+
18
+ # gui
19
+ subparsers.add_parser('gui', help='GUI 실행')
20
+
21
+ # generate-thumbnail (DSL만 사용)
22
+ gen = subparsers.add_parser('generate-thumbnail', help='DSL로 썸네일 생성')
23
+ gen.add_argument('dsl', nargs='?', default='thumbnail.json', help='DSL 파일 경로')
24
+ gen.add_argument('-o', '--output', default='thumbnail.png', help='출력 파일 경로')
25
+
26
+ # genthumb (간편 CLI: 제목/부제목 덮어쓰기 등)
27
+ gt = subparsers.add_parser('genthumb', help='간편 CLI로 썸네일 생성')
28
+ gt.add_argument('dsl', nargs='?', default='thumbnail.json', help='DSL 파일 경로')
29
+ gt.add_argument('-o', '--output', default='thumbnail.png', help='출력 파일 경로')
30
+ gt.add_argument('--title', help='제목 덮어쓰기 (\\n 또는 실제 줄바꿈 지원)')
31
+ gt.add_argument('--subtitle', help='부제목 덮어쓰기 (\\n 또는 실제 줄바꿈 지원)')
32
+ gt.add_argument('--bgImg', help='배경 이미지 경로')
33
+
34
+ args, unknown = parser.parse_known_args()
35
+
36
+ if args.command == 'gui':
37
+ gui_main()
38
+ return
39
+
40
+ if args.command == 'generate-thumbnail':
41
+ # generate_main은 자체 argparse를 사용하므로 여기서 직접 동작 위임이 어려움
42
+ # 동일 기능을 직접 수행하기보다는 해당 모듈의 메인 로직을 그대로 호출하도록 유지
43
+ # 간단하게는 모듈 내부가 파일 인자를 읽도록 짜여 있으므로, 여기서 args를 재적용
44
+ # 하지만 기존 main()은 sys.argv를 파싱하므로, 안전하게 별도 경로로 수행
45
+ # 대신 renderer를 직접 호출하지 않고, cli.main의 구현을 차용하기 위해 임시 argv 구성
46
+ sys.argv = ['generate-thumbnail', args.dsl, '-o', args.output]
47
+ generate_main()
48
+ return
49
+
50
+ if args.command == 'genthumb':
51
+ # 동일 이유로 간편 CLI도 기존 파서를 활용하기 위해 argv 재구성
52
+ new_argv = ['genthumb']
53
+ if args.dsl:
54
+ new_argv.append(args.dsl)
55
+ if args.output:
56
+ new_argv += ['-o', args.output]
57
+ if args.title:
58
+ new_argv += ['--title', args.title]
59
+ if args.subtitle:
60
+ new_argv += ['--subtitle', args.subtitle]
61
+ if args.bgImg:
62
+ new_argv += ['--bgImg', args.bgImg]
63
+ sys.argv = new_argv
64
+ genthumb_main()
65
+ return
66
+
67
+
68
+ if __name__ == '__main__':
69
+ main()
70
+
71
+
thumbnail_maker/cli.py ADDED
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ CLI 스크립트
5
+ """
6
+
7
+ import sys
8
+ import os
9
+ import json
10
+ import argparse
11
+ import base64
12
+ from .renderer import ThumbnailRenderer
13
+ import tempfile
14
+ import zipfile
15
+ import shutil
16
+
17
+
18
+ def main():
19
+ """메인 CLI 진입점"""
20
+ parser = argparse.ArgumentParser(description='썸네일 생성')
21
+ parser.add_argument('dsl', nargs='?', default='thumbnail.json', help='DSL 파일 경로')
22
+ parser.add_argument('-o', '--output', default='thumbnail.png', help='출력 파일 경로')
23
+
24
+ args = parser.parse_args()
25
+ staging = None
26
+ cwd_backup = os.getcwd()
27
+ # 출력 경로를 절대경로로 확보 (staging 디렉토리 변경 전)
28
+ output_path = args.output
29
+ if not os.path.isabs(output_path):
30
+ output_path = os.path.abspath(output_path)
31
+ try:
32
+ # .thl 패키지 지원: 임시 폴더에 풀어서 작업
33
+ if args.dsl.lower().endswith('.thl') and os.path.exists(args.dsl):
34
+ staging = tempfile.mkdtemp(prefix='thl_run_')
35
+ with zipfile.ZipFile(args.dsl, 'r') as zf:
36
+ zf.extractall(staging)
37
+ # 작업 디렉토리를 패키지 루트로 변경 (renderer의 'fonts/' 탐색을 위함)
38
+ os.chdir(staging)
39
+ dsl_path = os.path.join(staging, 'thumbnail.json')
40
+ else:
41
+ dsl_path = args.dsl
42
+
43
+ # DSL 파일 확인
44
+ if not os.path.exists(dsl_path):
45
+ print(f"오류: DSL 파일을 찾을 수 없습니다: {dsl_path}")
46
+ sys.exit(1)
47
+
48
+ # DSL 읽기
49
+ with open(dsl_path, 'r', encoding='utf-8') as f:
50
+ dsl = json.load(f)
51
+
52
+ # 썸네일 생성
53
+ ThumbnailRenderer.render_thumbnail(dsl, output_path)
54
+ finally:
55
+ try:
56
+ os.chdir(cwd_backup)
57
+ except Exception:
58
+ pass
59
+ if staging:
60
+ shutil.rmtree(staging, ignore_errors=True)
61
+
62
+
63
+ def main_cli():
64
+ """간편 CLI 진입점"""
65
+ parser = argparse.ArgumentParser(description='썸네일 생성 (간편 CLI)')
66
+ parser.add_argument('dsl', nargs='?', default='thumbnail.json', help='DSL 파일 경로')
67
+ parser.add_argument('-o', '--output', default='thumbnail.png', help='출력 파일 경로')
68
+ parser.add_argument('--title', help='제목 덮어쓰기 (\\n 또는 실제 줄바꿈 지원)')
69
+ parser.add_argument('--subtitle', help='부제목 덮어쓰기 (\\n 또는 실제 줄바꿈 지원)')
70
+ parser.add_argument('--bgImg', help='배경 이미지 경로')
71
+
72
+ args = parser.parse_args()
73
+
74
+ def normalize_text(s: str) -> str:
75
+ """CLI에서 전달된 텍스트의 줄바꿈 시퀀스를 실제 줄바꿈으로 변환"""
76
+ if s is None:
77
+ return s
78
+ # 리터럴 \n, \r\n, \r 처리
79
+ # 먼저 \r\n -> \n 으로 통일, 이후 리터럴 역슬래시-n 치환
80
+ s = s.replace('\r\n', '\n').replace('\r', '\n')
81
+ s = s.replace('\\n', '\n')
82
+ return s
83
+
84
+ staging = None
85
+ cwd_backup = os.getcwd()
86
+ # 출력 경로를 절대경로로 확보 (staging 디렉토리 변경 전)
87
+ output_path = args.output
88
+ if not os.path.isabs(output_path):
89
+ output_path = os.path.abspath(output_path)
90
+ try:
91
+ # .thl 패키지 지원
92
+ if args.dsl and args.dsl.lower().endswith('.thl') and os.path.exists(args.dsl):
93
+ staging = tempfile.mkdtemp(prefix='thl_run_')
94
+ with zipfile.ZipFile(args.dsl, 'r') as zf:
95
+ zf.extractall(staging)
96
+ os.chdir(staging)
97
+ dsl_path = os.path.join(staging, 'thumbnail.json')
98
+ else:
99
+ dsl_path = args.dsl
100
+
101
+ # DSL 파일 확인
102
+ if not os.path.exists(dsl_path):
103
+ print(f"오류: DSL 파일을 찾을 수 없습니다: {dsl_path}")
104
+ sys.exit(1)
105
+
106
+ # DSL 읽기
107
+ with open(dsl_path, 'r', encoding='utf-8') as f:
108
+ dsl = json.load(f)
109
+
110
+ # 배경 이미지 처리
111
+ if args.bgImg and os.path.exists(args.bgImg):
112
+ with open(args.bgImg, 'rb') as f:
113
+ image_data = f.read()
114
+ base64_str = base64.b64encode(image_data).decode('utf-8')
115
+ data_url = f"data:image/png;base64,{base64_str}"
116
+
117
+ dsl['Thumbnail']['Background']['type'] = 'image'
118
+ dsl['Thumbnail']['Background']['imagePath'] = data_url
119
+
120
+ # 제목/부제목 덮어쓰기
121
+ if 'Texts' in dsl.get('Thumbnail', {}):
122
+ for txt in dsl['Thumbnail']['Texts']:
123
+ if args.title and txt.get('type') == 'title':
124
+ txt['content'] = normalize_text(args.title)
125
+ if args.subtitle and txt.get('type') == 'subtitle':
126
+ txt['content'] = normalize_text(args.subtitle)
127
+
128
+ # 썸네일 생성
129
+ ThumbnailRenderer.render_thumbnail(dsl, output_path)
130
+ finally:
131
+ try:
132
+ os.chdir(cwd_backup)
133
+ except Exception:
134
+ pass
135
+ if staging:
136
+ shutil.rmtree(staging, ignore_errors=True)
137
+
138
+
139
+ if __name__ == '__main__':
140
+ main()
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ 메인 썸네일 생성 스크립트
5
+ """
6
+
7
+ import sys
8
+ import os
9
+ import json
10
+ import argparse
11
+ from .renderer import ThumbnailRenderer
12
+
13
+
14
+ def main():
15
+ parser = argparse.ArgumentParser(description='썸네일 생성')
16
+ parser.add_argument('dsl', nargs='?', default='thumbnail.json', help='DSL 파일 경로')
17
+ parser.add_argument('-o', '--output', default='thumbnail.png', help='출력 파일 경로')
18
+
19
+ args = parser.parse_args()
20
+
21
+ # DSL 파일 확인
22
+ if not os.path.exists(args.dsl):
23
+ print(f"오류: DSL 파일을 찾을 수 없습니다: {args.dsl}")
24
+ sys.exit(1)
25
+
26
+ # DSL 읽기
27
+ with open(args.dsl, 'r', encoding='utf-8') as f:
28
+ dsl = json.load(f)
29
+
30
+ # 썸네일 생성
31
+ ThumbnailRenderer.render_thumbnail(dsl, args.output)
32
+
33
+ print(f"✅ 썸네일 생성 완료: {args.output}")
34
+
35
+
36
+ if __name__ == '__main__':
37
+ main()
38
+