// ImageViewerTest.java // ----------------------- // part of YaCy // Copyright 2016 by luccioman; https://github.com/luccioman // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import javax.imageio.ImageIO; import javax.imageio.stream.ImageInputStream; import net.yacy.cora.document.id.DigestURL; import net.yacy.cora.util.ConcurrentLog; import net.yacy.peers.graphics.EncodedImage; import net.yacy.server.serverObjects; import net.yacy.visualization.ImageViewer; /** * Test rendering of one or more image files by ImageViewer * * @author luc * */ public class ImageViewerTest { /** Default image */ private static final String DEFAULT_IMG_RESOURCES = "/viewImageTest/test"; /** Default output encoding format */ private static final String DEFAULT_OUT_EXT = "png"; /** Viewer instance */ protected final ImageViewer VIEWER = new ImageViewer(); /** * @param args * main parameters. first item may contain input file or folder * URL * @return file or folder to be used : specified as first in args or default * one */ protected File getInputURL(String args[]) { String fileURL; if (args != null && args.length > 0) { fileURL = args[0]; } else { URL defaultURL = ImageViewerTest.class.getResource(DEFAULT_IMG_RESOURCES); if (defaultURL == null) { throw new IllegalArgumentException("File not found : " + DEFAULT_IMG_RESOURCES); } fileURL = defaultURL.getFile(); } return new File(fileURL); } /** * @param args * main parameters. args[2] main contains directory url for * rendered images files * @return output directory to use * @throws IllegalArgumentException * when args[2] is not set and default is not found */ protected File getOuputDir(String[] args) { File outDir; if (args.length > 2) { outDir = new File(args[2]); } else { String tmpDir = System.getProperty("java.io.tmpdir"); if (tmpDir == null) { throw new IllegalArgumentException("No destination dir specified, and default not found"); } outDir = new File(tmpDir + File.separator + this.getClass().getCanonicalName()); } return outDir; } /** * Build post parameters to use with ImageViewer * * @param args * main parameters : args[3] and args[4] may respectively contain * max width and max height. Set it to zero so there is no max * width and no max height when processing. args[5] may be set to * "quadratic" to render output images as squares. * @return a serverObjects instance */ protected serverObjects makePostParams(String args[]) { serverObjects post = new serverObjects(); if (args != null && args.length > 3) { int maxWidth = Integer.parseInt(args[3]); post.put("maxwidth", String.valueOf(maxWidth)); } if (args != null && args.length > 4) { int maxHeight = Integer.parseInt(args[4]); post.put("maxheight", String.valueOf(maxHeight)); } boolean quadratic = isQuadratic(args); if (quadratic) { post.put("quadratic", ""); } return post; } /** * * @param args * main parameters : second item may contain extension * @return extension to use for encoding */ protected String getEncodingExt(String args[]) { String ext = DEFAULT_OUT_EXT; if (args != null && args.length > 1) { ext = args[1]; } return ext; } /** * * @param args * main parameters. args[5] may be set to "quadratic" * @return true when image are supposed to be rendered as squares. */ protected boolean isQuadratic(String args[]) { boolean recursive = false; if (args != null && args.length > 5) { recursive = "quadratic".equals(args[5]); } return recursive; } /** * * @param args * main parameters. args[6] may be set to "recursive" * @return true when folders are supposed to processed recursively */ protected boolean isRecursive(String args[]) { boolean recursive = false; if (args != null && args.length > 6) { recursive = "recursive".equals(args[6]); } return recursive; } /** * Write same message to both system standard output and to outWriter. * * @param message * message to write * @param outWriter * PrintWriter writer. Must not be null. * @throws IOException * in case of write error */ protected void writeMessage(String message, PrintWriter outWriter) throws IOException { System.out.println(message); outWriter.println(message); } /** * Display detailed results and produce a results.txt file in outDir. All * parametrers required not to be null. * * @param processedFiles * all processed image files * @param failures * map input file url which failed with eventual cause error * @param time * total processing time in nanoseconds * @param outDir * directory to write results file * @throws IOException * when a write error occured writing the results file */ protected void displayResults(List<File> processedFiles, Map<String, Throwable> failures, long time, File outDir) throws IOException { PrintWriter resultsWriter = new PrintWriter(new FileWriter(new File(outDir, "results.txt"))); try { writeMessage(processedFiles.size() + " files processed in " + (time / 1000000) + " ms", resultsWriter); if (failures.size() > 0) { if (failures.size() == processedFiles.size()) { writeMessage("No input files could be processed :", resultsWriter); } else { writeMessage("Some input files could not be processed :", resultsWriter); } for (Entry<String, Throwable> entry : failures.entrySet()) { writeMessage(entry.getKey(), resultsWriter); if (entry.getValue() != null) { writeMessage("cause : " + entry.getValue(), resultsWriter); } } } else { if (processedFiles.size() > 0) { writeMessage("All input files were successfully processed.", resultsWriter); } else { writeMessage("No input file was provided.", resultsWriter); } } } finally { resultsWriter.close(); } } /** * Process inFiles and update processedFiles list and failures map. All * parameters must not be null. * * @param ext * output encoding image format * @param recursive * when true, also process inFiles directories * @param outDir * output directory * @param post * ImageViewer post parameters * @param inFiles * files or directories to process * @param processedFiles * list of processed files * @param failures * map failed file urls to eventual exception * @throws IOException * when an read/write error occured */ protected void processFiles(String ext, boolean recursive, File outDir, serverObjects post, File[] inFiles, List<File> processedFiles, Map<String, Throwable> failures) throws IOException { for (File inFile : inFiles) { if (inFile.isDirectory()) { if (recursive) { File subDir = new File(outDir, inFile.getName()); subDir.mkdirs(); processFiles(ext, recursive, subDir, post, inFile.listFiles(), processedFiles, failures); } } else { processedFiles.add(inFile); processFile(ext, outDir, post, failures, inFile); } } } /** * Process inFile image and update processedFiles list and failures map. All * parameters must not be null. * @param ext output encoding image format * @param outDir output directory * @param post ImageViewer post parameters * @param failures map failed file urls to eventual exception * @param inFile file image to process * @throws IOException when an read/write error occured */ protected void processFile(String ext, File outDir, serverObjects post, Map<String, Throwable> failures, File inFile) throws IOException { /* Delete eventual previous result file */ File outFile = new File(outDir, inFile.getName() + "." + ext); if (outFile.exists()) { outFile.delete(); } ImageInputStream inStream = ImageIO.createImageInputStream(inFile); String urlString = inFile.getAbsolutePath(); EncodedImage img = null; Throwable error = null; try { img = this.VIEWER.parseAndScale(post, true, new DigestURL(urlString), ext, inStream); } catch (Throwable e) { error = e; } if (img == null) { failures.put(urlString, error); } else { FileOutputStream outFileStream = null; try { outFileStream = new FileOutputStream(outFile); img.getImage().writeTo(outFileStream); } finally { if (outFileStream != null) { outFileStream.close(); } img.getImage().close(); } } } /** * Test image(s) (default : classpath resource folder /viewImageTest/test/) are parsed and * rendered to an output foler. Result can then be checked with program of * your choice. * * @param args * may be empty or contain parameters to override defaults : * <ul> * <li>args[0] : input image file URL or folder containing image * files URL. Default : classpath resource * /viewImageTest/test/</li> * <li>args[1] : output format name (for example : "jpg") for * rendered image. Defaut : "png".</li> * <li>args[2] : ouput folder URL. Default : * "[system tmp dir]/ImageViewerTest".</li> * <li>args[3] : max width (in pixels) for rendered image. May be * set to zero to specify no max width. Default : no value.</li> * <li>args[4] : max height (in pixels) for rendered image. May * be set to zero to specify no max height. Default : no value. * </li> * <li>args[5] : set to "quadratic" to render square output * image. May be set to any string to specify no quadratic shape. * Default : false.</li> * <li>args[6] : set to "recursive" to process recursively sub * folders. Default : false.</li> * </ul> * @throws IOException * when a read/write error occured */ public static void main(String args[]) throws IOException { ImageViewerTest test = new ImageViewerTest(); File inFile = test.getInputURL(args); String ext = test.getEncodingExt(args); File outDir = test.getOuputDir(args); boolean recursive = test.isRecursive(args); serverObjects post = test.makePostParams(args); outDir.mkdirs(); File[] inFiles; if (inFile.isFile()) { inFiles = new File[1]; inFiles[0] = inFile; System.out.println("Testing ImageViewer rendering with input file : " + inFile.getAbsolutePath() + " encoded To : " + ext); } else if (inFile.isDirectory()) { inFiles = inFile.listFiles(); System.out.println("Testing ImageViewer rendering with input files in folder : " + inFile.getAbsolutePath() + " encoded To : " + ext); } else { inFiles = new File[0]; } if (inFiles.length == 0) { throw new IllegalArgumentException(inFile.getAbsolutePath() + " is not a valid file or folder url."); } System.out.println("Rendered images will be written in dir : " + outDir.getAbsolutePath()); List<File> processedFiles = new ArrayList<File>(); Map<String, Throwable> failures = new TreeMap<>(); try { long time = System.nanoTime(); test.processFiles(ext, recursive, outDir, post, inFiles, processedFiles, failures); time = System.nanoTime() - time; test.displayResults(processedFiles, failures, time, outDir); } finally { ConcurrentLog.shutdown(); } } }