wangzhibo
2025-08-03 56d194a4300610a17cc3c6682aaf63f039e9c4ab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import requests
import urllib.parse
import datetime
import random
import os
from io import BytesIO
 
from  auto_media_publisher.config.conf_base import (
    TRANSLATE_API_TEMPLATE,
    POLLINATIONS_API_TEMPLATE,
    POLLINATIONS_DEFAULT_WIDTH ,
    POLLINATIONS_DEFAULT_HEIGHT ,
    POLLINATIONS_DEFAULT_MODEL,
)
from .utils_images import resize_and_crop_center_any
 
 
class Text2ImageGenerator:
    def __init__(self, width=POLLINATIONS_DEFAULT_WIDTH, height=POLLINATIONS_DEFAULT_HEIGHT, model=POLLINATIONS_DEFAULT_MODEL):
        self.width = width
        self.height = height
        self.model = model
 
    def translate_prompt(self, prompt: str) -> str:
        """
        使用 MyMemory API 将中文提示词翻译为英文,失败则返回原文。
        """
        
        encoded_prompt = urllib.parse.quote(prompt)
        api_url = TRANSLATE_API_TEMPLATE.format(prompt=encoded_prompt)
        try:
            res = requests.get(api_url, timeout=30)
            res.raise_for_status()
            data = res.json()
            if data.get("responseStatus") == 200 and "translatedText" in data.get("responseData", {}):
                translated = data["responseData"]["translatedText"]
                print(f"[✓] 翻译成功: {translated}")
                return translated
        except Exception as e:
            print(f"[!] 翻译失败,使用原文: {e}")
        return prompt
 
    def build_url(self, prompt: str) -> str:
        """
        构建 Pollinations 图片生成 URL。
        """
        seed = random.randint(1, 1_000_000)
        encoded_prompt = urllib.parse.quote(prompt)
        return POLLINATIONS_API_TEMPLATE.format(
            prompt=encoded_prompt,
            width=self.width,
            height=self.height,
            seed=seed,
            model=self.model
        )
    
    def _fetch_with_retry(self, url: str, max_retries: int = 3):
        """
        最多尝试 max_retries 次请求 URL,成功则返回 response.content,否则返回 None。
        """
        for attempt in range(1, max_retries + 1):
            try:
                response = requests.get(url, timeout=30)
                response.raise_for_status()
                return resize_and_crop_center_any(response.content,self.width,self.height)
            except Exception as e:
                print(f"[!] 请求第 {attempt} 次失败:{e}")
        return None
 
    def generate_image_with_trans(self, prompt: str, filename: str = None) -> str:
        if not prompt.strip():
            raise ValueError("提示词不能为空")
 
        translated_prompt = self.translate_prompt(prompt)
        url = self.build_url(translated_prompt)
 
        content = self._fetch_with_retry(url)
        if content is None:
            return None
 
        if not filename:
            now = datetime.datetime.now()
            filename = now.strftime("%Y%m%d%H%M%S") + ".png"
        if not filename.lower().endswith(".png"):
            filename += ".png"
 
        with open(filename, "wb") as f:
            f.write(content)
 
        abs_path = os.path.abspath(filename)
        print(f"[✓] 图片已保存:{abs_path}")
        return abs_path
    
    def generate_image_without_trans(self, prompt: str, filename: str = None) -> str:
        if not prompt.strip():
            raise ValueError("提示词不能为空")
 
        url = self.build_url(prompt)
        print(url)
 
        content = self._fetch_with_retry(url)
        if content is None:
            return None
 
        if not filename:
            now = datetime.datetime.now()
            filename = now.strftime("%Y%m%d%H%M%S") + ".png"
        if not filename.lower().endswith(".png"):
            filename += ".png"
 
        with open(filename, "wb") as f:
            f.write(content)
 
        abs_path = os.path.abspath(filename)
        print(f"[✓] 图片已保存:{abs_path}")
        return abs_path
    
    def generate_image_with_trans_to_stream(self, prompt: str) -> BytesIO:
        if not prompt.strip():
            raise ValueError("提示词不能为空")
 
        translated_prompt = self.translate_prompt(prompt)
        url = self.build_url(translated_prompt)
 
        content = self._fetch_with_retry(url)
        if content is None:
            return None
 
        image_stream = BytesIO(content)
        return image_stream