Circle_generator_Flask/generate_images.py
2025-06-23 21:39:38 +08:00

196 lines
6.9 KiB
Python

import sys
import csv
from PySide6.QtCore import Qt, QTimer, QObject, Signal, Slot
from PySide6.QtWidgets import QGraphicsScene, QGraphicsRectItem, QGraphicsPixmapItem,QApplication, QGraphicsTextItem
from PySide6.QtGui import QPainter, QImage, QColor, QPixmap, QFont, QFontDatabase
import CustomCircleItem
import re
BG_WIDTH = 3508
BG_HEIGHT = 2480
HEAD_ICON_PREFIX = "resource/head_%d.png"
X_OFFSET = 1700
Y_OFFSET = 650
CIRCLE_RADIUS = 617
CIRCLE_X_OFFSET = 750
def is_chinese(text):
# Returns True if any character is Chinese
return any('\u4e00' <= char <= '\u9fff' for char in text)
def is_english(text):
# Returns True if all characters are English letters (ignores spaces)
return bool(re.fullmatch(r'[A-Za-z\s]+', text))
class ImageGenerator(QObject):
finished = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QGraphicsScene()
self._timer = QTimer(self)
self._timer.timeout.connect(self.generate_images)
self.colors = self.read_csv("resource/colors.csv")
print(f"Loaded colors: {self.colors}")
# Add the font file (provide the correct path)
self.customFont = self.read_font("resource/TaiwanPearl-SemiBold.ttf")
def read_csv(self, path):
colors = []
try:
with open(path, newline='', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
colors.append(row)
if colors:
colors.pop(0) # Remove header row if exists
except Exception as e:
print(f"Error reading {path}: {e}")
return colors
def read_font(self,path):
try:
font_id = QFontDatabase.addApplicationFont(path)
if font_id != -1:
families = QFontDatabase.applicationFontFamilies(font_id)
print("Loaded font families:", families)
family = families[1] if len(families) > 1 else families[0]
customFont = QFont(family)
customFont.setPixelSize(80)
customFont.setLetterSpacing(QFont.AbsoluteSpacing,15) # Adjust word spacing if needed
return customFont
else:
print("Failed to load font.")
return QFont() # fallback to default font
except Exception as e:
print(f"Error loading font from {path}: {e}")
return QFont()
@Slot()
def start(self):
self._timer.start(1000) # Generate images every second
@Slot()
def stop(self):
self._timer.stop()
self.finished.emit()
def scene_to_image(self, scene, filename):
print(f"Saving scene to {filename}...")
image = QImage(scene.sceneRect().size().toSize(), QImage.Format_ARGB32)
image.fill(Qt.transparent)
# Set 300 DPI
dpi = 300
dots_per_meter = int(dpi / 0.0254)
image.setDotsPerMeterX(dots_per_meter)
image.setDotsPerMeterY(dots_per_meter)
painter = QPainter(image)
scene.render(painter)
painter.end()
image.save(f"generated_images/{filename}", "PNG")
self.stop()
@Slot()
def generate_images(self, name_csv, out_filename):
# Placeholder for image generation logic
print("Generating images...1")
# Group of rect
for i, name in enumerate(name_csv):
r =g =b = 0
for j, color in enumerate(self.colors):
if color[0] == name[0]:
print(f"Adding rect with color: {color}")
r, g, b = map(int, color[1:4])
break
_idx_x = i % 2
_idx_y = (i%6) // 2
if i % 6 == 0:
# Example of adding a simple item to the scene
bg_item = QGraphicsRectItem(0, 0, BG_WIDTH, BG_HEIGHT)
bg_item.setBrush(Qt.white)
self.scene.addItem(bg_item)
print("Generating images...2")
rect_item = QGraphicsRectItem(30+X_OFFSET*_idx_x, 30+(Y_OFFSET+20)*_idx_y, X_OFFSET, Y_OFFSET, parent= bg_item)
rect_item.setPen(Qt.NoPen)
#simple pixmap
# smaple_item = QGraphicsPixmapItem(QPixmap("resource/sample.jpg"), rect_item)
# smaple_item.setPos(rect_item.boundingRect().x()+100, rect_item.boundingRect().y()+25)
#draw circle
for j in range(2):
circle_item = CustomCircleItem.CustomCircleItem(100+(CIRCLE_X_OFFSET*j), 25, CIRCLE_RADIUS, 600, QColor(r, g, b), is_circle=True,parent=rect_item)
circle_item.setOpacity(1)
#draw head icon
head_icon_num = int(name[1]) if len(name) > 1 else 1
head_icon = QGraphicsPixmapItem(QPixmap(HEAD_ICON_PREFIX % head_icon_num), circle_item)
head_icon.setPos(circle_item.boundingRect().x(), circle_item.boundingRect().y())
#name item
name_item = QGraphicsTextItem()
name_str = name[2 + j] if len(name) > 2 + j else "Unknown"
if is_chinese(name_str):
if len(name_str) == 2:
self.customFont.setLetterSpacing(QFont.AbsoluteSpacing, 30) # Adjust word spacing if needed
elif len(name_str) == 3:
self.customFont.setLetterSpacing(QFont.AbsoluteSpacing, 15)
elif len(name_str) == 4:
self.customFont.setLetterSpacing(QFont.AbsoluteSpacing, 0)
else:
self.customFont.setLetterSpacing(QFont.AbsoluteSpacing, 0)
name_item.setFont(self.customFont)
name_item.setPlainText(name_str)
name_item.setDefaultTextColor(QColor(0, 0, 0))
name_item.setPos((circle_item.boundingRect().x()+ circle_item.boundingRect().width()/2 - name_item.boundingRect().width()/2)+10, circle_item.boundingRect().y()+430)
self.scene.addItem(name_item)
if i > 0 and i % 6 == 5:
# Save the current scene to an image file every 5 items
self.scene_to_image(self.scene, f"{out_filename}_{i//6}.png")
self.scene.clear()
print("Image generated and added to scene.")
if __name__ == "__main__":
app = QApplication(sys.argv)
generator = ImageGenerator()
generator.finished.connect(app.quit)
csv_file = "resource/sample.csv"
out_filename = "generated_image"
if len(sys.argv) > 2:
csv_file = sys.argv[1]
out_filename = sys.argv[2]
print(f"Loading CSV file: {csv_file}, Output filename: {out_filename}")
sample_data = generator.read_csv(csv_file)
print(f"Sample data loaded: {sample_data}")
generator.generate_images(sample_data, out_filename)
#generator.start()
# Run the application event loop
sys.exit(0)