1
0
Fork 0
mirror of https://github.com/ldericher/fftcgtool synced 2025-01-15 15:02:59 +00:00
This commit is contained in:
Jörn-Michael Miehe 2021-08-09 14:03:45 +02:00
parent ac5d05da49
commit a78a3ad04a
4 changed files with 76 additions and 50 deletions

View file

@ -3,70 +3,56 @@ import logging
from PIL import Image
from .cards import Cards
from .grid import Grid
from .imageloader import ImageLoader
def chunks(whole: list[any], chunk_size) -> list:
# while there are elements
while whole:
# get a chunk
yield whole[:chunk_size]
# remove that chunk
whole = whole[chunk_size:]
class Book:
# Card faces by Square API
__FACE_URL = "https://fftcg.cdn.sewest.net/images/cards/full/{}_{}.jpg"
# Card back image by Aurik
__BACK_URL = "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/"
def __init__(self, cards: Cards, grid: tuple[int, int], resolution: tuple[int, int], language: str,
num_threads: int):
logger = logging.getLogger(__name__)
# transform grid into Grid
grid = Grid(grid)
# sort cards by element, then alphabetically
cards.sort(key=lambda x: x.name)
cards.sort(key=lambda x: "Multi" if len(x.elements) > 1 else x.elements[0])
# all card face URLs
urls = [Book.__FACE_URL.format(card.code, language) for card in cards]
# card back URL
urls.append(Book.__BACK_URL)
urls = [f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language}.jpg" for card in cards]
# card back URL (image by Aurik)
urls.append(
"http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/"
)
# multithreaded download
# multi-threaded download
images = ImageLoader.load(urls, resolution, language, num_threads)
# card back Image
back_image = images.pop(-1)
# shorthands
# rows and columns per sheet
r, c = grid
# capacity of grid (reserve last space for card back)
grid_capacity = r * c - 1
# width, height per card
w, h = resolution
def paste_card(index: int, card: Image) -> None:
x, y = (index % c) * w, (index // c) * h
page.paste(card, (x, y))
self.__pages = []
for images in chunks(images, grid_capacity):
for page_images, page_cards in zip(grid.chunks(images), grid.chunks(cards)):
# create book page Image
page = Image.new("RGB", (c * w, r * h))
logger.info(f"New image: {page.size[0]}x{page.size[1]}")
page_image = Image.new("RGB", grid * resolution)
logger.info(f"New image: {page_image.size[0]}x{page_image.size[1]}")
# paste card faces onto page
for i, image in enumerate(images):
paste_card(i, image)
for i, image in enumerate(page_images):
grid.paste(page_image, i, image)
# paste card back in last position
paste_card(c * r - 1, back_image)
grid.paste(page_image, grid.capacity, back_image)
self.__pages.append(page)
# save page
self.__pages.append({
"image": page_image,
"cards": page_cards,
})
def __getitem__(self, index: int) -> Image.Image:
return self.__pages[index]["image"]
def save(self, filename: str) -> None:
for i, page in enumerate(self.__pages):
page.save(filename.format(i))
page["image"].save(f"{filename}_{i}.jpg")

33
fftcg/grid.py Normal file
View file

@ -0,0 +1,33 @@
from PIL import Image
class Grid(tuple[int, int]):
def __mul__(self, other):
other = Grid(other)
return Grid((self.x * other.x, self.y * other.y))
@property
def x(self):
return self[0]
@property
def y(self):
return self[1]
@property
def capacity(self):
# capacity of grid (reserve last space for card back)
return self.x * self.y - 1
def chunks(self, whole: list) -> list:
# while there are elements
while whole:
# get a chunk
yield whole[:self.capacity]
# remove that chunk
whole = whole[self.capacity:]
def paste(self, page: Image.Image, index: int, card: Image.Image) -> None:
w, h = card.size
position = (index % self.x) * w, (index // self.x) * h
page.paste(card, position)

View file

@ -10,25 +10,28 @@ class Opus(Cards):
logger = logging.getLogger(__name__)
if opus_id.isnumeric():
roman_opus_id = roman.toRoman(int(opus_id))
params = {"set": [f"Opus {roman_opus_id.upper()}"]}
self.__name = f"Opus {roman.toRoman(int(opus_id)).upper()}"
self.__number = opus_id
self.__name = f"opus_{opus_id}"
self.__filename = f"opus_{opus_id}"
params = {"set": [self.__name]}
elif opus_id == "chaos":
params = {"set": ["Boss Deck Chaos"]}
self.__name = "Boss Deck Chaos"
self.__number = "B"
self.__name = "boss_deck_chaos"
self.__filename = "boss_deck_chaos"
params = {"set": [self.__name]}
elif opus_id == "promo":
params = {"rarity": ["pr"]}
self.__name = "Promo"
self.__number = "PR"
self.__name = "promo"
self.__filename = "promo"
params = {"rarity": ["pr"]}
else:
params = {"set": ["?"]}
self.__number = "?"
self.__name = "?"
self.__number = "?"
self.__filename = "?"
params = {"set": "?"}
super().__init__(params)
@ -51,3 +54,7 @@ class Opus(Cards):
@property
def number(self) -> str:
return self.__number
@property
def filename(self) -> str:
return self.__filename

View file

@ -6,7 +6,7 @@ import os
import fftcg
# constants
GRID = 7, 10 # default in TTsim: 7 rows, 10 columns
GRID = 10, 7 # default in TTsim: 10 columns, 7 rows
RESOLUTION = 429, 600 # default in TTsim: 480x670 pixels per card
@ -45,7 +45,7 @@ def main() -> None:
# main program
opus = fftcg.Opus(args.opus_id)
book = fftcg.Book(opus, GRID, RESOLUTION, "eg", args.num_threads)
book.save(f"{opus.name}_{{}}.jpg")
book.save(opus.filename)
# bye
logging.info("Done. Put the generated JSON files in your 'Saved Objects' Folder.")