[feature] Card images are now saved and read from zip files

This commit is contained in:
North 2012-09-07 20:09:29 +03:00
parent e0d4285a69
commit fa82f1b159
5 changed files with 111 additions and 106 deletions

View file

@ -1,23 +0,0 @@
package mage.client.util;
import java.io.File;
public class FileUtils {
public static File getTempDir(String key) {
String tmpDir = System.getProperty("java.io.tmpdir");
String sep = System.getProperty("file.separator");
if (!tmpDir.endsWith(sep))
tmpDir += sep;
tmpDir += key + "-" + java.util.UUID.randomUUID().toString();
File dir = new File(tmpDir);
if (!dir.mkdirs()) {
throw new RuntimeException("couldn't create temp directory " + tmpDir);
}
return dir;
}
}

View file

@ -1,5 +1,10 @@
package org.mage.plugins.card.images;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TConfig;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileOutputStream;
import de.schlichtherle.truezip.fs.FsOutputOption;
import mage.cards.Card;
import mage.client.dialog.PreferencesDialog;
import mage.remote.Connection;
@ -61,6 +66,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
public static void main(String[] args) {
startDownload(null, null, null);
TConfig config = TConfig.get();
config.setArchiveDetector(new TArchiveDetector("zip"));
config.getOutputPreferences().set(FsOutputOption.STORE);
}
public static void startDownload(JFrame frame, Set<Card> allCards, String imagesPath) {
@ -204,7 +212,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
}
public static boolean checkForNewCards(Set<Card> allCards, String imagesPath) {
File file;
TFile file;
for (Card card : allCards) {
if (card.getCardNumber() > 0 && !card.getExpansionSetCode().isEmpty()) {
CardInfo url = new CardInfo(card.getName(), card.getExpansionSetCode(), card.getCardNumber(), 0, false, card.canTransform(), card.isNightCard());
@ -212,9 +220,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
if (basicLandPattern.matcher(card.getName()).matches()) {
withCollectorId = true;
}
file = new File(CardImageUtils.getImagePath(url, withCollectorId, imagesPath));
if (!file.exists())
file = new TFile(CardImageUtils.getImagePath(url, withCollectorId, imagesPath));
if (!file.exists()) {
return true;
}
}
}
return false;
@ -267,7 +276,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
log.error(e);
}
File file;
TFile file;
/**
* check to see which cards we already have
@ -277,7 +286,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
if (basicLandPattern.matcher(card.getName()).matches()) {
withCollectorId = true;
}
file = new File(CardImageUtils.getImagePath(card, withCollectorId, imagesPath));
file = new TFile(CardImageUtils.getImagePath(card, withCollectorId, imagesPath));
if (!file.exists()) {
cardsToDownload.add(card);
}
@ -300,16 +309,11 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
private static ArrayList<CardInfo> getTokenCardUrls() throws RuntimeException {
ArrayList<CardInfo> list = new ArrayList<CardInfo>();
HashSet<String> filter = new HashSet<String>();
InputStream in = DownloadPictures.class.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
readImageURLsFromFile(in, list, filter);
return list;
}
private static void readImageURLsFromFile(InputStream in, ArrayList<CardInfo> list, Set<String> filter) throws RuntimeException {
if (in == null) {
log.error("resources input stream is null");
return;
return list;
}
BufferedReader reader = null;
@ -361,6 +365,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
}
}
return list;
}
@Override
@ -414,7 +419,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
}
if (url != null) {
Runnable task = new DownloadTask(card, new URL(url), imagesPath);
Runnable task = new DownloadTask(card, new URL(url));
executor.execute(task);
} else {
synchronized (sync) {
@ -439,38 +444,34 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
private CardInfo card;
private URL url;
private String imagesPath;
public DownloadTask(CardInfo card, URL url, String imagesPath) {
public DownloadTask(CardInfo card, URL url) {
this.card = card;
this.url = url;
this.imagesPath = imagesPath;
}
@Override
public void run() {
try {
createDirForCard(card, imagesPath);
boolean withCollectorId = false;
if (basicLandPattern.matcher(card.getName()).matches()) {
withCollectorId = true;
}
File fileOut = new File(CardImageUtils.getImagePath(card, withCollectorId));
File temporaryFile = new File(Constants.IO.imageBaseDir + File.separator + card.hashCode() + "." + card.getName() + ".jpg");
BufferedInputStream in = new BufferedInputStream(url.openConnection(p).getInputStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileOut));
BufferedOutputStream out = new BufferedOutputStream(new TFileOutputStream(temporaryFile));
byte[] buf = new byte[1024];
int len = 0;
int len;
while ((len = in.read(buf)) != -1) {
// user cancelled
if (cancel) {
in.close();
out.flush();
out.close();
// delete what was written so far
fileOut.delete();
temporaryFile.delete();
return;
}
out.write(buf, 0, len);
}
@ -479,8 +480,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
out.flush();
out.close();
TFile outputFile = new TFile(CardImageUtils.getImagePath(card, withCollectorId));
if (card.isTwoFacedCard()) {
BufferedImage image = ImageIO.read(fileOut);
BufferedImage image = ImageIO.read(temporaryFile);
temporaryFile.delete();
if (image.getHeight() == 470) {
BufferedImage renderedImage = new BufferedImage(265, 370, BufferedImage.TYPE_INT_RGB);
renderedImage.getGraphics();
@ -491,20 +494,23 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
graphics2D.drawImage(image, 0, 0, 265, 370, 41, 62, 306, 432, null);
}
graphics2D.dispose();
writeImageToFile(renderedImage, fileOut);
writeImageToFile(renderedImage, outputFile);
}
} else {
new TFile(temporaryFile).cp_rp(outputFile);
temporaryFile.delete();
}
synchronized (sync) {
update(cardIndex + 1);
}
} catch (Exception e) {
log.error(e, e);
}
synchronized (sync) {
update(cardIndex + 1);
}
}
private void writeImageToFile(BufferedImage image, File file) throws IOException {
private void writeImageToFile(BufferedImage image, TFile file) throws IOException {
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = (ImageWriter) iter.next();
@ -512,21 +518,17 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(0.96f);
FileImageOutputStream output = new FileImageOutputStream(file);
File tempFile = new File(Constants.IO.imageBaseDir + File.separator + image.hashCode() + file.getName());
FileImageOutputStream output = new FileImageOutputStream(tempFile);
writer.setOutput(output);
IIOImage image2 = new IIOImage(image, null, null);
writer.write(null, image2, iwp);
writer.dispose();
output.close();
}
}
private static File createDirForCard(CardInfo card, String imagesPath) throws Exception {
File setDir = new File(CardImageUtils.getImageDir(card, imagesPath));
if (!setDir.exists()) {
setDir.mkdirs();
new TFile(tempFile).cp_rp(file);
tempFile.delete();
}
return setDir;
}
private void update(int card) {
@ -545,7 +547,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
if (basicLandPattern.matcher(cardInfo.getName()).matches()) {
withCollectorId = true;
}
File file = new File(CardImageUtils.getImagePath(cardInfo, withCollectorId));
TFile file = new TFile(CardImageUtils.getImagePath(cardInfo, withCollectorId));
if (file.exists()) {
cardsIterator.remove();
}

View file

@ -4,19 +4,20 @@ import com.google.common.base.Function;
import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker;
import com.mortennobel.imagescaling.ResampleOp;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import de.schlichtherle.truezip.file.TFileOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import mage.view.CardView;
import org.apache.log4j.Logger;
import org.mage.plugins.card.constants.Constants;
import org.mage.plugins.card.utils.CardImageUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class stores ALL card images in a cache with soft values. this means
* that the images may be garbage collected when they are not needed any more, but will
@ -65,21 +66,27 @@ public class ImageCache {
CardInfo info = new CardInfo(name, set, collectorId, type);
if (collectorId == 0) info.setToken(true);
if (collectorId == 0) {
info.setToken(true);
}
String path = CardImageUtils.getImagePath(info);
if (path == null) return null;
File file = new File(path);
if (path == null) {
return null;
}
TFile file = new TFile(path);
if (thumbnail && path.endsWith(".jpg")) {
String thumbnailPath = path.replace(".jpg", ".thumb.jpg");
File thumbnailFile = new File(thumbnailPath);
String thumbnailPath = path.replace(".zip", ".thumb.zip");
TFile thumbnailFile = new TFile(thumbnailPath);
if (thumbnailFile.exists()) {
//log.debug("loading thumbnail for " + key + ", path="+thumbnailPath);
return loadImage(thumbnailFile);
} else {
BufferedImage image = loadImage(file);
image = getWizardsCard(image);
if (image == null) return null;
if (image == null) {
return null;
}
//log.debug("creating thumbnail for " + key);
return makeThumbnail(image, thumbnailPath);
}
@ -91,10 +98,11 @@ public class ImageCache {
"Requested image doesn't fit the requirement for key (<cardname>#<setname>#<collectorID>): " + key);
}
} catch (Exception ex) {
if (ex instanceof ComputationException)
if (ex instanceof ComputationException) {
throw (ComputationException) ex;
else
} else {
throw new ComputationException(ex);
}
}
}
});
@ -138,8 +146,9 @@ public class ImageCache {
// legitimate, happens when a card has no image
return null;
} catch (ComputationException ex) {
if (ex.getCause() instanceof NullPointerException)
if (ex.getCause() instanceof NullPointerException) {
return null;
}
log.error(ex,ex);
return null;
}
@ -163,13 +172,15 @@ public class ImageCache {
* file to load image from
* @return {@link BufferedImage}
*/
public static BufferedImage loadImage(File file) {
public static BufferedImage loadImage(TFile file) {
BufferedImage image = null;
if (!file.exists()) {
return null;
}
try {
image = ImageIO.read(file);
TFileInputStream inputStream = new TFileInputStream(file);
image = ImageIO.read(inputStream);
inputStream.close();
} catch (Exception e) {
log.error(e, e);
}
@ -179,10 +190,12 @@ public class ImageCache {
public static BufferedImage makeThumbnail(BufferedImage original, String path) {
BufferedImage image = getResizedImage(original, Constants.THUMBNAIL_SIZE_FULL);
File imagePath = new File(path);
TFile imageFile = new TFile(path);
try {
//log.debug("thumbnail path:"+path);
ImageIO.write(image, "jpg", imagePath);
TFileOutputStream outputStream = new TFileOutputStream(imageFile);
ImageIO.write(image, "jpg", outputStream);
outputStream.close();
} catch (Exception e) {
log.error(e,e);
}
@ -203,8 +216,9 @@ public class ImageCache {
int tgtWidth = Constants.CARD_SIZE_FULL.width;
int tgtHeight = Constants.CARD_SIZE_FULL.height;
if (srcWidth == tgtWidth && srcHeight == tgtHeight)
if (srcWidth == tgtWidth && srcHeight == tgtHeight) {
return original;
}
ResampleOp resampleOp = new ResampleOp(tgtWidth, tgtHeight);
BufferedImage image = resampleOp.filter(original, null);
@ -216,8 +230,9 @@ public class ImageCache {
* panel For future use.
*/
private static BufferedImage getFullSizeImage(BufferedImage original, double scale) {
if (scale == 1)
if (scale == 1) {
return original;
}
ResampleOp resampleOp = new ResampleOp((int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
BufferedImage image = resampleOp.filter(original, null);
return image;
@ -239,12 +254,14 @@ public class ImageCache {
public static BufferedImage getImage(CardView card, int width, int height) {
String key = getKey(card);
BufferedImage original = getImage(key);
if (original == null)
if (original == null) {
return null;
}
double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight());
if (scale > 1)
if (scale > 1) {
scale = 1;
}
return getFullSizeImage(original, scale);
}

View file

@ -1,12 +1,11 @@
package org.mage.plugins.card.utils;
import de.schlichtherle.truezip.file.TFile;
import java.util.HashMap;
import org.mage.plugins.card.constants.Constants;
import org.mage.plugins.card.images.CardInfo;
import org.mage.plugins.card.properties.SettingsManager;
import java.io.File;
import java.util.HashMap;
public class CardImageUtils {
private static HashMap<CardInfo, String> pathCache = new HashMap<CardInfo, String>();
@ -22,17 +21,17 @@ public class CardImageUtils {
String filePath;
String suffix = ".jpg";
File file = null;
TFile file;
if (card.isToken()) {
if (pathCache.containsKey(card)) {
return pathCache.get(card);
}
filePath = getTokenImagePath(card);
file = new File(filePath);
file = new TFile(filePath);
if (!file.exists()) {
filePath = searchForCardImage(card);
file = new File(filePath);
file = new TFile(filePath);
}
if (file.exists()) {
@ -40,11 +39,11 @@ public class CardImageUtils {
}
} else {
filePath = getImagePath(card, false);
file = new File(filePath);
file = new TFile(filePath);
if (!file.exists()) {
filePath = getImagePath(card, true);
file = new File(filePath);
file = new TFile(filePath);
}
}
@ -53,7 +52,7 @@ public class CardImageUtils {
*/
if (file == null || !file.exists()) {
filePath = cleanString(card.getName()) + suffix;
file = new File(filePath);
file = new TFile(filePath);
}
if (file.exists()) {
@ -66,17 +65,16 @@ public class CardImageUtils {
private static String getTokenImagePath(CardInfo card) {
String filename = getImagePath(card, false);
File file = new File(filename);
TFile file = new TFile(filename);
if (!file.exists()) {
CardInfo updated = new CardInfo(card);
updated.setName(card.getName() + " 1");
filename = getImagePath(updated, false);
file = new File(filename);
file = new TFile(filename);
if (!file.exists()) {
updated = new CardInfo(card);
updated.setName(card.getName() + " 2");
filename = getImagePath(updated, false);
file = new File(filename);
}
}
@ -84,14 +82,14 @@ public class CardImageUtils {
}
private static String searchForCardImage(CardInfo card) {
File file = null;
String path = "";
TFile file;
String path;
CardInfo c = new CardInfo(card);
for (String set : SettingsManager.getIntance().getTokenLookupOrder()) {
c.setSet(set);
path = getTokenImagePath(c);
file = new File(path);
file = new TFile(path);
if (file.exists()) {
pathCache.put(card, path);
return path;
@ -106,9 +104,9 @@ public class CardImageUtils {
char c;
for (int i = 0; i < in.length(); i++) {
c = in.charAt(i);
if (c == ' ' || c == '-')
if (c == ' ' || c == '-') {
out.append('_');
else if (Character.isLetterOrDigit(c)) {
} else if (Character.isLetterOrDigit(c)) {
out.append(c);
}
}
@ -134,9 +132,9 @@ public class CardImageUtils {
String set = updateSet(card.getSet(), false).toUpperCase();
String imagesDir = (imagesPath != null ? imagesPath : Constants.IO.imageBaseDir);
if (card.isToken()) {
return imagesDir + File.separator + "TOK" + File.separator + set;
return imagesDir + TFile.separator + "TOK" + ".zip" + TFile.separator + set;
} else {
return imagesDir + File.separator + set;
return imagesDir + TFile.separator + set + ".zip" + TFile.separator + set;
}
}
@ -148,9 +146,9 @@ public class CardImageUtils {
String type = card.getType() != 0 ? " " + Integer.toString(card.getType()) : "";
String name = card.getName();
if (withCollector) {
return getImageDir(card, imagesPath) + File.separator + name + "." + card.getCollectorId() + ".full.jpg";
return getImageDir(card, imagesPath) + TFile.separator + name + "." + card.getCollectorId() + ".full.jpg";
} else {
return getImageDir(card, imagesPath) + File.separator + name + type + ".full.jpg";
return getImageDir(card, imagesPath) + TFile.separator + name + type + ".full.jpg";
}
}
}