1
0
Fork 0
mirror of https://github.com/ldericher/fftcgtool synced 2025-01-15 15:02:59 +00:00

composition works

This commit is contained in:
Jörn-Michael Miehe 2021-08-04 18:36:23 +02:00
parent cb4031b422
commit f375d5792d
5 changed files with 129 additions and 45 deletions

View file

@ -1,25 +1,43 @@
import queue import logging
from PIL import Image
from .imageloader import ImageLoader
def chunks(whole: list, chunk_size):
# while there are elements
while whole:
# get a chunk
yield whole[:chunk_size]
# remove that chunk
whole = whole[chunk_size:]
class Book: class Book:
def __init__(self, cards): def __init__(self, cards, grid, resolution, language, num_threads):
self.__cards = cards logger = logging.getLogger(__name__)
def __get_pages(self, grid): images = ImageLoader.load(cards, resolution, language, num_threads)
# cards per sheet images = [images[card] for card in cards]
# shorthands
# rows and columns per sheet
r, c = grid r, c = grid
capacity = r * c - 1 # width, height per card
# flat copy w, h = resolution
cards = self.__cards
# while there are cards self.__pages = []
while cards: for images in chunks(images, r * c - 1):
# get a chunk page = Image.new("RGB", (c * w, r * h))
yield cards[:capacity] logger.info(f"New image: {page.size[0]}x{page.size[1]}")
# remove that chunk
cards = cards[capacity:]
def populate(self, grid, resolution, threadnum=16): for i, image in enumerate(images):
card_queue = queue.Queue() x, y = (i % c) * w, (i // c) * h
for i, card in enumerate(self.__cards): page.paste(image, (x, y, x + w, y + h))
card_queue.put((i, card))
self.__pages.append(page)
def save(self, filename):
for i, page in enumerate(self.__pages):
page.save(filename.format(i))

View file

@ -49,17 +49,21 @@ class Card:
self.__text = data[f"Text_{language}"] self.__text = data[f"Text_{language}"]
def __str__(self): def __str__(self):
return f"'{self.__name}' ({'/'.join(self.__elements)}, {self.get_code()})" return f"'{self.__name}' ({'/'.join(self.__elements)}, {self.code})"
# 6-048C # 6-048C
def get_code(self): @property
def code(self):
return f"{self.__opus}-{self.__serial}{self.__rarity}" return f"{self.__opus}-{self.__serial}{self.__rarity}"
def get_name(self): @property
def name(self):
return self.__name return self.__name
def get_text(self): @property
def text(self):
return self.__text return self.__text
def get_elements(self): @property
def elements(self):
return self.__elements return self.__elements

View file

@ -24,15 +24,16 @@ class ImageLoader(threading.Thread):
def run(self) -> None: def run(self) -> None:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
while not self.__queue.empty(): while not self.__queue.empty():
# take next card # take next card
i, card = self.__queue.get() card = self.__queue.get()
# fetch card image (retry on fail) # fetch card image (retry on fail)
while True: while True:
logger.info("get image for card {}".format(card)) logger.info(f"get image for card {card}")
try: try:
res = requests.get(ImageLoader.__FACE_URL.format(card.get_code(), self.__language)) res = requests.get(ImageLoader.__FACE_URL.format(card.code, self.__language))
image = Image.open(io.BytesIO(res.content)) image = Image.open(io.BytesIO(res.content))
image.convert("RGB") image.convert("RGB")
image = image.resize(self.__resolution, Image.BICUBIC) image = image.resize(self.__resolution, Image.BICUBIC)
@ -41,21 +42,31 @@ class ImageLoader(threading.Thread):
pass pass
# put image in correct position # put image in correct position
self.__images[i] = image self.__images[card] = image
# image is processed # image is processed
self.__queue.task_done() self.__queue.task_done()
@classmethod @classmethod
def spawn(cls, cards, resolution, language="eg", num_threads=16): def load(cls, cards, resolution, language, num_threads):
card_queue = queue.Queue() card_queue = queue.Queue()
for i, card in enumerate(cards): for card in cards:
card_queue.put((i, card)) card_queue.put(card)
loaders = []
for _ in range(num_threads): for _ in range(num_threads):
cls(card_queue, resolution, language).start() loader = cls(card_queue, resolution, language)
loaders.append(loader)
loader.start()
return card_queue card_queue.join()
def get_images(self): images = {}
for loader in loaders:
images = {**images, **loader.images}
return images
@property
def images(self):
return self.__images return self.__images

View file

@ -1,3 +1,5 @@
import logging
import roman import roman
from .cards import Cards from .cards import Cards
@ -5,18 +7,37 @@ from .cards import Cards
class Opus(Cards): class Opus(Cards):
def __init__(self, number): def __init__(self, number):
if isinstance(number, int): logger = logging.getLogger(__name__)
number = f"Opus {roman.toRoman(number)}"
if isinstance(number, str) and number.isnumeric():
set_name = f"Opus {roman.toRoman(int(number))}"
number = str(number)
elif number == "Boss Deck Chaos":
set_name = number
number = "B"
else:
set_name = "?"
number = "?"
params = { params = {
"text": "", "text": "",
"element": ["fire"], # "element": ["fire"],
"set": [number], "set": [set_name],
} }
Cards.__init__(self, params) Cards.__init__(self, params)
# filter out reprints
reprints = [card for card in self if not card.code.startswith(number)]
for reprint in reprints:
self.remove(reprint)
# sort every element alphabetically # sort every element alphabetically
self.sort(key=lambda x: x.get_code()) self.sort(key=lambda x: x.code)
self.sort(key=lambda x: x.get_name()) self.sort(key=lambda x: x.name)
self.sort(key=lambda x: "Multi" if len(x.get_elements()) > 1 else x.get_elements()[0]) self.sort(key=lambda x: "Multi" if len(x.elements) > 1 else x.elements[0])
for card in self:
logger.info(f"imported card {card}")

40
main.py
View file

@ -1,15 +1,45 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import logging
import os
from fftcg.imageloader import ImageLoader
from fftcg.opus import Opus from fftcg.opus import Opus
from fftcg.book import Book
def main(): def main():
opus = Opus(14) # Setup CLI
print(opus) parser = argparse.ArgumentParser(
description='Imports FFTCG cards for TT-Sim.')
queue = ImageLoader.spawn(opus, (429, 600)) parser.add_argument(
queue.join() 'opusid',
default="2",
metavar="OpusID",
nargs="?",
help='the Opus to import')
parser.add_argument(
'-n', '--num_threads',
type=int,
default=20,
metavar="COUNT",
help='maximum number of concurrent requests')
args = parser.parse_args()
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(threadName)s %(message)s')
opus = Opus(args.opusid)
# output directory
if not os.path.exists("out"):
os.mkdir("out")
os.chdir("out")
book = Book(opus, (7, 10), (429, 600), "eg", 16)
book.save(f"opus_{args.opusid}_{{}}.jpg")
if __name__ == '__main__': if __name__ == '__main__':