194 lines
6.9 KiB
Python
194 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):
|
|
# 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"generated_image_{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)
|
|
|
|
if len(sys.argv) > 1:
|
|
csv_file = sys.argv[1]
|
|
print(f"Loading CSV file: {csv_file}")
|
|
else:
|
|
csv_file = "resource/sample.csv"
|
|
print(f"No CSV file provided, using default: {csv_file}")
|
|
|
|
sample_data = generator.read_csv(csv_file)
|
|
print(f"Sample data loaded: {sample_data}")
|
|
|
|
generator.generate_images(sample_data)
|
|
#generator.start()
|
|
|
|
# Run the application event loop
|
|
sys.exit(0) |