/*
* $Id$
*
* Copyright (c) 2010, 2011 by Joel Uckelman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.tools.image.tilecache;
import static VASSAL.tools.image.tilecache.ZipFileImageTilerState.STARTING_IMAGE;
import static VASSAL.tools.image.tilecache.ZipFileImageTilerState.TILE_WRITTEN;
import static VASSAL.tools.image.tilecache.ZipFileImageTilerState.TILING_FINISHED;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import VASSAL.tools.ArrayUtils;
import VASSAL.tools.concurrent.DaemonThreadFactory;
import VASSAL.tools.image.FallbackImageTypeConverter;
import VASSAL.tools.image.ImageIOImageLoader;
import VASSAL.tools.image.ImageLoader;
import VASSAL.tools.image.ImageTypeConverter;
import VASSAL.tools.io.FileArchive;
import VASSAL.tools.io.IOUtils;
import VASSAL.tools.io.TemporaryFileFactory;
import VASSAL.tools.io.ZipArchive;
import VASSAL.tools.lang.Callback;
/**
* Tiles images contained in a ZIP archive.
*
* @since 3.2.0
* @author Joel Uckelman
*/
public class ZipFileImageTiler {
private static final Logger logger =
LoggerFactory.getLogger(ZipFileImageTiler.class);
public static void main(String[] args) {
try {
logger.info("Starting");
// Oh we have no heads, we have no HEADS!
System.setProperty("java.awt.headless", "true");
// Ensure that exceptions are logged.
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable thrown) {
logger.error(thread.getName(), thrown);
}
});
// Parse the arguments
final String zpath = args[0];
final String tpath = args[1];
final int tw = Integer.parseInt(args[2]);
final int th = Integer.parseInt(args[3]);
// Get the image paths from stdin, one per line
final List<String> pl = new ArrayList<String>();
BufferedReader stdin = null;
try {
stdin = new BufferedReader(new InputStreamReader(System.in));
String s;
while ((s = stdin.readLine()) != null) {
pl.add(s);
}
}
catch (IOException e) {
logger.error("", e);
}
finally {
IOUtils.closeQuietly(stdin);
}
final String[] ipaths = pl.toArray(new String[pl.size()]);
// TODO: Determine what the optimal number of threads is.
final Runtime runtime = Runtime.getRuntime();
final ExecutorService exec = new ThreadPoolExecutor(
runtime.availableProcessors(),
runtime.availableProcessors()+1,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new DaemonThreadFactory(ZipFileImageTiler.class.getSimpleName())
);
final TemporaryFileFactory tfac = new TemporaryFileFactory() {
public File create() throws IOException {
return File.createTempFile("img", null, new File(tpath));
}
};
final ImageTypeConverter itc = new FallbackImageTypeConverter(tfac);
final ImageLoader loader = new ImageIOImageLoader(itc);
final TileSlicer slicer = new TileSlicerImpl();
final FileArchiveImageTiler tiler = new FileArchiveImageTiler();
final String portProp = System.getProperty("VASSAL.port");
Socket sock = null;
DataOutputStream dout = null;
try {
if (portProp != null) {
final int port = Integer.parseInt(portProp);
final InetAddress lo = InetAddress.getByName(null);
sock = new Socket(lo, port);
sock.shutdownInput();
dout = new DataOutputStream(sock.getOutputStream());
}
else {
dout = new DataOutputStream(System.err);
}
final DataOutputStream out = dout;
final Callback<String> imageL = new Callback<String>() {
public void receive(String ipath) throws IOException {
out.writeByte(STARTING_IMAGE);
out.writeUTF(ipath);
out.flush();
}
};
final Callback<Void> tileL = new Callback<Void>() {
public void receive(Void obj) throws IOException {
out.writeByte(TILE_WRITTEN);
out.flush();
}
};
final Callback<Void> doneL = new Callback<Void>() {
public void receive(Void obj) throws IOException {
out.writeByte(TILING_FINISHED);
out.flush();
}
};
FileArchive fa = null;
try {
fa = new ZipArchive(zpath);
// Tile the images
tiler.run(
fa, tpath, tw, th, ipaths, exec,
loader, slicer, imageL, tileL, doneL
);
fa.close();
}
catch (IOException e) {
logger.error("", e);
}
finally {
IOUtils.closeQuietly(fa);
}
dout.close();
if (sock != null) {
sock.close();
}
}
catch (IOException e) {
logger.error("", e);
}
finally {
IOUtils.closeQuietly(dout);
IOUtils.closeQuietly(sock);
}
}
finally {
logger.info("Exiting");
}
}
}