Commit 60f822ed authored by Senator John's avatar Senator John 💬

Update

Implemented Crop Option.
parent f28cc611
...@@ -7,8 +7,9 @@ Options: ...@@ -7,8 +7,9 @@ Options:
1. Export from test-release.cdb to JSON 1. Export from test-release.cdb to JSON
2. Dump IDs from JSON to CSV (merging existing Official mappings) 2. Dump IDs from JSON to CSV (merging existing Official mappings)
3. Fetch artwork images for IDs (with multi-art prompting) 3. Fetch artwork images for IDs (with multi-art prompting)
4. Crop downloaded card images to artwork region only
Configuration paths at top — no prompts for file locations except for multi-art choices. Configuration paths and crop percentages are set at the top.
""" """
import os import os
import sys import sys
...@@ -17,6 +18,7 @@ import sqlite3 ...@@ -17,6 +18,7 @@ import sqlite3
import csv import csv
import requests import requests
from tqdm import tqdm from tqdm import tqdm
from PIL import Image
# ===== Configuration ===== # ===== Configuration =====
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
...@@ -25,8 +27,28 @@ TRANSFORMED_JSON = os.path.join(SCRIPT_DIR, 'cards_transformed.json') ...@@ -25,8 +27,28 @@ TRANSFORMED_JSON = os.path.join(SCRIPT_DIR, 'cards_transformed.json')
IDS_CSV = os.path.join(SCRIPT_DIR, 'IDs.csv') IDS_CSV = os.path.join(SCRIPT_DIR, 'IDs.csv')
MANIFEST_JSON = os.path.join(SCRIPT_DIR, 'manifest.json') MANIFEST_JSON = os.path.join(SCRIPT_DIR, 'manifest.json')
OUTPUT_DIR = os.path.join(SCRIPT_DIR, 'pics') OUTPUT_DIR = os.path.join(SCRIPT_DIR, 'pics')
CROP_DIR = os.path.join(SCRIPT_DIR, 'artworks_only')
DEBUG = False # set True for verbose logging DEBUG = False # set True for verbose logging
# Crop boundaries (percentages as strings or numbers; commas allowed)
# e.g. "70,5" means 70.5%
CROP_LEFT = "12,5"
CROP_TOP = "18,6"
CROP_RIGHT = "87"
CROP_BOTTOM = "70"
# helper to convert percent to fraction
def _pct(v):
return float(str(v).replace(',', '.')) / 100.0
# computed fractions
CROP_LEFT_PCT = _pct(CROP_LEFT)
CROP_TOP_PCT = _pct(CROP_TOP)
CROP_RIGHT_PCT = _pct(CROP_RIGHT)
CROP_BOTTOM_PCT = _pct(CROP_BOTTOM)
# ===== Core Functions =====
def export_db(): def export_db():
"""Export cards from .cdb into JSON with fields id, name, desc.""" """Export cards from .cdb into JSON with fields id, name, desc."""
...@@ -89,7 +111,6 @@ def load_manifest(): ...@@ -89,7 +111,6 @@ def load_manifest():
def get_artwork_url(entry): def get_artwork_url(entry):
# choose in order bestOCG, bestArt, bestTCG
for key in ('bestOCG','bestArt','bestTCG'): for key in ('bestOCG','bestArt','bestTCG'):
url = entry.get(key) url = entry.get(key)
if url: if url:
...@@ -143,13 +164,13 @@ def fetch_artworks(): ...@@ -143,13 +164,13 @@ def fetch_artworks():
f"ID {id_str} has {count} artworks. " f"ID {id_str} has {count} artworks. "
f"[L]ast {default_n}, [A]ll {count}, or [N]one? ") f"[L]ast {default_n}, [A]ll {count}, or [N]one? ")
resp = input(prompt).strip().lower() resp = input(prompt).strip().lower()
if resp == 'a' or resp == 'all': if resp in ('a','all'):
to_download = versions to_download = versions
elif resp in ('', 'l', 'last'): elif resp in ('','l','last'):
to_download = versions[-default_n:] to_download = versions[-default_n:]
else: else:
if DEBUG: if DEBUG:
print(f"User skipped ID {id_str}") print(f"Skipped ID {id_str}")
continue continue
for ver in to_download: for ver in to_download:
...@@ -160,28 +181,50 @@ def fetch_artworks(): ...@@ -160,28 +181,50 @@ def fetch_artworks():
print(f"No URL for {id_str} v{ver}") print(f"No URL for {id_str} v{ver}")
continue continue
url = normalize_url(raw) url = normalize_url(raw)
fname = f"{id_str}_{ver}.png" if count > 1 else f"{id_str}.png" fname = f"{id_str}_{ver}.png" if count>1 else f"{id_str}.png"
outp = os.path.join(OUTPUT_DIR, fname) outp = os.path.join(OUTPUT_DIR, fname)
if os.path.exists(outp): if os.path.exists(outp):
continue continue
try: try:
r = requests.get(url, stream=True, timeout=10) r = requests.get(url, stream=True, timeout=10)
r.raise_for_status() r.raise_for_status()
with open(outp, 'wb') as f: with open(outp,'wb') as f:
for chunk in r.iter_content(8192): for chunk in r.iter_content(8192):
f.write(chunk) f.write(chunk)
except Exception as e: except Exception as e:
if DEBUG: if DEBUG:
print(f"Error downloading {url}: {e}") print(f"Error downloading {url}: {e}")
print(f"Fetched artwork for {len(valid_ids)} cards to {OUTPUT_DIR}") print(f"Fetched artwork for {len(valid_ids)} cards to {OUTPUT_DIR}")
def crop_artworks():
"""
Crop card images to artwork region only, based on configured percentages.
"""
os.makedirs(CROP_DIR, exist_ok=True)
files = [f for f in os.listdir(OUTPUT_DIR) if f.lower().endswith(('.png','.jpg','.jpeg'))]
for fname in tqdm(files, desc='Cropping artworks'):
in_path = os.path.join(OUTPUT_DIR, fname)
out_path = os.path.join(CROP_DIR, fname)
if os.path.exists(out_path):
continue
img = Image.open(in_path)
w, h = img.size
left = int(w * CROP_LEFT_PCT)
top = int(h * CROP_TOP_PCT)
right = int(w * CROP_RIGHT_PCT)
bottom = int(h * CROP_BOTTOM_PCT)
cropped = img.crop((left, top, right, bottom))
cropped.save(out_path)
print(f'Cropped {len(files)} images to {CROP_DIR}')
def main(): def main():
print("Select an option:") print("Select an option:")
print("1: Export from test-release.cdb") print("1: Export from test-release.cdb")
print("2: Dump IDs from JSON") print("2: Dump IDs from JSON")
print("3: Fetch Artwork") print("3: Fetch Artwork")
print("4: Crop Artworks Only")
choice = input("Select Option: ").strip() choice = input("Select Option: ").strip()
if choice == '1': if choice == '1':
export_db() export_db()
...@@ -189,6 +232,8 @@ def main(): ...@@ -189,6 +232,8 @@ def main():
dump_ids() dump_ids()
elif choice == '3': elif choice == '3':
fetch_artworks() fetch_artworks()
elif choice == '4':
crop_artworks()
else: else:
print("Invalid choice.") print("Invalid choice.")
sys.exit(1) sys.exit(1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment