images: fixed sets/rarity icons download from gatherer, removed outdated code and improved default icons folder (close #13797);

This commit is contained in:
Oleg Agafonov 2025-06-28 17:12:39 +04:00
parent 76f0397ef0
commit 85c04bca59
6 changed files with 55 additions and 75 deletions

View file

@ -63,6 +63,9 @@ public final class Constants {
public static final String RESOURCE_SYMBOL_FOLDER_SVG = "svg";
public static final String RESOURCE_SYMBOL_FOLDER_PNG = "png";
// download rarity icons to large folder by default
public static final String RESOURCE_PATH_SYMBOLS_RARITY_DEFAULT_PATH = RESOURCE_PATH_SYMBOLS + File.separator + RESOURCE_SYMBOL_FOLDER_LARGE;
public enum ResourceSymbolSize {
SMALL, // TODO: delete SMALL, MEDIUM and LARGE as outdated (svg or generated png works fine)
MEDIUM,
@ -74,12 +77,12 @@ public final class Constants {
// resources - sets
public static final String RESOURCE_PATH_SETS = File.separator + "sets";
public static final String RESOURCE_SET_FOLDER_SMALL = "small";
public static final String RESOURCE_SET_FOLDER_MEDIUM = ""; // empty, medium images laydown in "sets" folder, TODO: delete that and auto gen, use png for html, not gif
public static final String RESOURCE_SET_FOLDER_LARGE = "large";
public static final String RESOURCE_SET_FOLDER_SVG = "svg";
public enum ResourceSetSize {
SMALL,
MEDIUM,
LARGE,
SVG
}

View file

@ -89,11 +89,6 @@ public final class ManaSymbols {
public static void loadImages() {
logger.info("Symbols: loading...");
// TODO: delete files rename jpg->gif (it was for backward compatibility for one of the old version?)
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.SMALL));
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.MEDIUM));
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.LARGE));
//renameSymbols(getSymbolsPath(ResourceSymbolSize.SVG)); // not need
// TODO: remove medium sets files to "medium" folder like symbols above?
// prepare svg's css settings
@ -145,9 +140,9 @@ public final class ManaSymbols {
Map<Rarity, Image> rarityImages = new EnumMap<>(Rarity.class);
setImages.put(set, rarityImages);
// load medium size
// load large size
for (Rarity rarityCode : codes) {
File file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + rarityCode.getCode() + ".jpg");
File file = new File(getResourceSetsPath(ResourceSetSize.LARGE) + set + '-' + rarityCode.getCode() + ".png");
try {
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
int width = image.getWidth(null);
@ -167,7 +162,7 @@ public final class ManaSymbols {
// generate small size
try {
File file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM));
File file = new File(getResourceSetsPath(ResourceSetSize.LARGE));
if (!file.exists()) {
file.mkdirs();
}
@ -175,11 +170,11 @@ public final class ManaSymbols {
for (Rarity code : codes) {
File newFile = new File(pathRoot + '-' + code + ".png");
if (!(MageFrame.isSkipSmallSymbolGenerationForExisting() && newFile.exists())) {// skip if option enabled and file already exists
file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + code + ".png");
file = new File(getResourceSetsPath(ResourceSetSize.LARGE) + set + '-' + code + ".png");
if (file.exists()) {
continue;
}
file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + code + ".jpg");
file = new File(getResourceSetsPath(ResourceSetSize.LARGE) + set + '-' + code + ".png");
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
try {
int width = image.getWidth(null);
@ -239,7 +234,7 @@ public final class ManaSymbols {
}
}
private static File getSymbolFileNameAsGIF(String symbol, int size) {
private static File getSymbolFileNameAsPNG(String symbol, int size) {
ResourceSymbolSize needSize = null;
if (size <= 15) {
@ -250,15 +245,15 @@ public final class ManaSymbols {
needSize = ResourceSymbolSize.LARGE;
}
return new File(getResourceSymbolsPath(needSize) + symbol + ".gif");
return new File(getResourceSymbolsPath(needSize) + symbol + ".png");
}
private static BufferedImage loadSymbolAsGIF(String symbol, int resizeToWidth, int resizeToHeight) {
File file = getSymbolFileNameAsGIF(symbol, resizeToWidth);
return loadSymbolAsGIF(file, resizeToWidth, resizeToHeight);
private static BufferedImage loadSymbolAsPNG(String symbol, int resizeToWidth, int resizeToHeight) {
File file = getSymbolFileNameAsPNG(symbol, resizeToWidth);
return loadSymbolAsPNG(file, resizeToWidth, resizeToHeight);
}
private static BufferedImage loadSymbolAsGIF(File sourceFile, int resizeToWidth, int resizeToHeight) {
private static BufferedImage loadSymbolAsPNG(File sourceFile, int resizeToWidth, int resizeToHeight) {
BufferedImage image = null;
@ -315,9 +310,9 @@ public final class ManaSymbols {
// gif (if svg fails)
if (image == null) {
file = getSymbolFileNameAsGIF(symbol, size);
file = getSymbolFileNameAsPNG(symbol, size);
if (file.exists()) {
image = loadSymbolAsGIF(file, size, size);
image = loadSymbolAsPNG(file, size, size);
}
}
if (image == null) {
@ -352,29 +347,6 @@ public final class ManaSymbols {
return errorInfo.isEmpty();
}
private static void renameSymbols(String path) {
File file = new File(path);
if (!file.exists()) {
return;
}
final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.jpg");
try {
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (matcher.matches(file)) {
Path gifPath = file.resolveSibling(file.getFileName().toString().replaceAll("\\.jpg$", ".gif"));
Files.move(file, gifPath, StandardCopyOption.REPLACE_EXISTING);
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
logger.error("Couldn't rename mana symbols on " + path, e);
}
}
private static String getResourceSymbolsPath(ResourceSymbolSize needSize) {
// return real path to symbols (default or user defined)
@ -420,8 +392,8 @@ public final class ManaSymbols {
case SMALL:
path = path + Constants.RESOURCE_SET_FOLDER_SMALL;
break;
case MEDIUM:
path = path + Constants.RESOURCE_SET_FOLDER_MEDIUM;
case LARGE:
path = path + Constants.RESOURCE_SET_FOLDER_LARGE;
break;
case SVG:
path = path + Constants.RESOURCE_SET_FOLDER_SVG;

View file

@ -663,7 +663,9 @@ public class CardPluginImpl implements CardPlugin {
// mana symbols (low quality)
jobs = new GathererSymbols();
for (DownloadJob job : jobs) {
downloader.add(job);
// TODO: gatherer removed mana symbols icons after 2025, see https://github.com/magefree/mage/issues/13797
// remove GathererSymbols code after few releases as unused (2025.06.28)
// downloader.add(job);
}
// set code symbols (low quality)

View file

@ -46,8 +46,10 @@ public class Downloader extends AbstractLaternaBean {
public Downloader() {
// prepare 10 threads and start to waiting new download jobs from queue
// TODO: gatherer website has download rate limits, so limit max threads as temporary solution
int maxThreads = 3;
PoolFiberFactory f = new PoolFiberFactory(pool);
for (int i = 0, numThreads = 10; i < numThreads; i++) {
for (int i = 0, numThreads = maxThreads; i < numThreads; i++) {
Fiber fiber = f.create();
fiber.start();
fibers.add(fiber);

View file

@ -16,7 +16,9 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
/**
* Download: set code symbols download from wizards web size
* <p>
* Warning, it's outdated source with low quality images. TODO: must migrate to scryfall like mana icons
* Warning, it's outdated source with low quality images.
* TODO: must migrate to scryfall like mana icons,
* see https://github.com/magefree/mage/issues/13261
*/
public class GathererSets implements Iterable<DownloadJob> {
@ -41,9 +43,10 @@ public class GathererSets implements Iterable<DownloadJob> {
private static File outDir;
private static final int DAYS_BEFORE_RELEASE_TO_DOWNLOAD = +14; // Try to load the symbolsBasic eralies 14 days before release date
private static final int DAYS_BEFORE_RELEASE_TO_DOWNLOAD = +14; // Try to load the symbolsBasic 14 days before release date
private static final Logger logger = Logger.getLogger(GathererSets.class);
// TODO: find all possible sets from ExpansionRepository instead custom
private static final String[] symbolsBasic = {"10E", "9ED", "8ED", "7ED", "6ED", "5ED", "4ED", "3ED", "2ED", "LEB", "LEA",
"HOP",
"ARN", "ATQ", "LEG", "DRK", "FEM", "HML",
@ -113,9 +116,7 @@ public class GathererSets implements Iterable<DownloadJob> {
"DRB", "V09", "V10", "V12", "V13", "V14", "V15", "V16", "V17", "EXP", "MED"
// "HTR16" does not exist
};
private static final String[] symbolsOnlySpecial = {
"MPS", "MP2"
};
private static final HashMap<String, String> codeReplacements = new HashMap<>();
@ -171,8 +172,7 @@ public class GathererSets implements Iterable<DownloadJob> {
}
public GathererSets() {
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS);
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS_RARITY_DEFAULT_PATH);
if (!outDir.exists()) {
outDir.mkdirs();
@ -287,9 +287,9 @@ public class GathererSets implements Iterable<DownloadJob> {
canDownload = false;
if (exp != null && exp.getReleaseDate().before(compareDate)) {
canDownload = true;
jobs.add(generateDownloadJob(symbol, "C", "C"));
jobs.add(generateDownloadJob(symbol, "U", "U"));
jobs.add(generateDownloadJob(symbol, "R", "R"));
jobs.add(generateDownloadJob(symbol, "C", "common"));
jobs.add(generateDownloadJob(symbol, "U", "uncommon"));
jobs.add(generateDownloadJob(symbol, "R", "rare"));
}
CheckSearchResult(symbol, exp, canDownload, true, true, true, false);
}
@ -299,10 +299,10 @@ public class GathererSets implements Iterable<DownloadJob> {
canDownload = false;
if (exp != null && exp.getReleaseDate().before(compareDate)) {
canDownload = true;
jobs.add(generateDownloadJob(symbol, "C", "C"));
jobs.add(generateDownloadJob(symbol, "U", "U"));
jobs.add(generateDownloadJob(symbol, "R", "R"));
jobs.add(generateDownloadJob(symbol, "M", "M"));
jobs.add(generateDownloadJob(symbol, "C", "common"));
jobs.add(generateDownloadJob(symbol, "U", "uncommon"));
jobs.add(generateDownloadJob(symbol, "R", "rare"));
jobs.add(generateDownloadJob(symbol, "M", "mythic"));
}
CheckSearchResult(symbol, exp, canDownload, true, true, true, true);
}
@ -312,17 +312,7 @@ public class GathererSets implements Iterable<DownloadJob> {
canDownload = false;
if (exp != null && exp.getReleaseDate().before(compareDate)) {
canDownload = true;
jobs.add(generateDownloadJob(symbol, "M", "M"));
}
CheckSearchResult(symbol, exp, canDownload, false, false, false, true);
}
for (String symbol : symbolsOnlySpecial) {
ExpansionSet exp = Sets.findSet(symbol);
canDownload = false;
if (exp != null && exp.getReleaseDate().before(compareDate)) {
canDownload = true;
jobs.add(generateDownloadJob(symbol, "M", "S"));
jobs.add(generateDownloadJob(symbol, "M", "mythic"));
}
CheckSearchResult(symbol, exp, canDownload, false, false, false, true);
}
@ -334,11 +324,22 @@ public class GathererSets implements Iterable<DownloadJob> {
}
private DownloadJob generateDownloadJob(String set, String rarity, String urlRarity) {
File dst = new File(outDir, set + '-' + rarity + ".jpg");
File dst = new File(outDir, set + '-' + rarity + ".png");
if (codeReplacements.containsKey(set)) {
set = codeReplacements.get(set);
}
String url = "https://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + urlRarity;
// example:
// - small: https://gatherer-static.wizards.com/set_symbols/FIN/small-common-FIN.png
// - big: https://gatherer-static.wizards.com/set_symbols/FIN/large-rare-FIN.png
String useSet = set.toUpperCase(Locale.ENGLISH);
String useSize = "large"; // allow: small, large
String url = String.format("https://gatherer-static.wizards.com/set_symbols/%s/%s-%s-%s.png",
useSet,
useSize,
urlRarity,
useSet
);
return new DownloadJob(set + '-' + rarity, url, toFile(dst), false);
}
}

View file

@ -75,7 +75,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
continue;
}
String symbol = sym.replaceAll("/", "");
File dst = new File(dir, symbol + ".gif");
File dst = new File(dir, symbol + ".png");
// workaround for miss icons on Gatherer (no cards with it, so no icons)
// TODO: comment and try download without workaround, keep fix for symbols with "Resource not found" error