java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java
author František Kučera <franta-hg@frantovo.cz>
Mon, 17 Nov 2014 21:59:20 +0100
changeset 17 505031965440
parent 15 93fa6ce675e5
child 18 a5a36526ff71
permissions -rw-r--r--
preparation for later support of NativeSingleImageResizer
     1 /**
     2  * copy-image-resizer
     3  * Copyright © 2014 František Kučera (frantovo.cz)
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, either version 3 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 package cz.frantovo.copyImageResizer;
    19 
    20 import cz.frantovo.copyImageResizer.JavaSingleImageResizer.ImageFormat;
    21 import java.io.File;
    22 import java.io.FileInputStream;
    23 import java.io.FileNotFoundException;
    24 import java.io.FileOutputStream;
    25 import java.io.IOException;
    26 import java.nio.channels.FileChannel;
    27 import java.util.logging.Level;
    28 import java.util.logging.LogRecord;
    29 import java.util.logging.Logger;
    30 
    31 /**
    32  *
    33  * @author Ing. František Kučera (frantovo.cz)
    34  */
    35 public class RecursiveImageResizer {
    36 
    37 	private static final Logger log = Logger.getLogger(RecursiveImageResizer.class.getName());
    38 
    39 	private final Counters counters = new Counters();
    40 
    41 	/**
    42 	 * TODO: support plugins – several implementations of SingleImageResizer
    43 	 */
    44 	private final SingleImageResizer resizer = new JavaSingleImageResizer();
    45 
    46 	private final RecursiveOptions options;
    47 
    48 	public RecursiveImageResizer(RecursiveOptions options) {
    49 		this.options = options;
    50 	}
    51 
    52 	public Counters resize() throws RecursiveException, ResizeException {
    53 		resizeDirectory(options.getInput());
    54 		return counters;
    55 	}
    56 
    57 	private void resizeFile(File inputFile) throws ResizeException {
    58 		File inputFileRelative = relativize(options.getInput(), inputFile);
    59 		log.log(Level.FINER, "Resizing file: {0}", inputFileRelative);
    60 		counters.increment(Counters.COUNTER_TYPE.FILES);
    61 
    62 		ImageFormat format = ImageFormat.getMatching(inputFile.getName());
    63 
    64 		if (format == null) {
    65 			log.log(Level.FINER, "Skipping file: {0} (no image format matched this extension)", inputFileRelative);
    66 			counters.increment(Counters.COUNTER_TYPE.SKIPPED_UNKNOWN_EXTENSION);
    67 		} else {
    68 			try {
    69 				for (SizeSpecification size : options.getSizes()) {
    70 					File sizeRoot = new File(options.getOutput(), size.getDirectory());
    71 					File outputFile = new File(sizeRoot, inputFileRelative.getPath());
    72 					try (FileInputStream input = new FileInputStream(inputFile)) {
    73 
    74 						try (FileOutputStream output = new FileOutputStream(outputFile)) {
    75 							boolean wasResized = resizer.resize(input, output, size, format);
    76 							if (wasResized) {
    77 								counters.increment(Counters.COUNTER_TYPE.RESIZED);
    78 							} else {
    79 								log.log(Level.FINER, "File: {0} has already required (or smaller) size → just copy", inputFileRelative);
    80 								justCopy(inputFile, outputFile);
    81 								counters.increment(Counters.COUNTER_TYPE.JUST_COPIED);
    82 							}
    83 						}
    84 					}
    85 				}
    86 			} catch (FileNotFoundException e) {
    87 				throw new ResizeException("Error while opening stream", e);
    88 			} catch (IOException e) {
    89 				throw new ResizeException("Error while closing stream", e);
    90 			}
    91 		}
    92 	}
    93 
    94 	private static void justCopy(File inputFile, File outputFile) throws ResizeException {
    95 		try {
    96 
    97 			if (!outputFile.exists()) {
    98 				outputFile.createNewFile();
    99 			}
   100 
   101 			try (FileChannel input = new FileInputStream(inputFile).getChannel()) {
   102 				try (FileChannel output = new FileOutputStream(outputFile).getChannel()) {
   103 					output.transferFrom(input, 0, input.size());
   104 				}
   105 			}
   106 
   107 		} catch (IOException e) {
   108 			throw new ResizeException("Unable copy stream/channel", e);
   109 		}
   110 
   111 	}
   112 
   113 	private void resizeDirectory(File directory) throws ResizeException {
   114 
   115 		log.log(Level.FINE, "Resizing directory: {0}", directory);
   116 		counters.increment(Counters.COUNTER_TYPE.DIRECTORIES);
   117 
   118 		for (SizeSpecification size : options.getSizes()) {
   119 			File relative = relativize(options.getInput(), directory);
   120 			File sizeRoot = new File(options.getOutput(), size.getDirectory());
   121 			File dir = new File(sizeRoot, relative.getPath());
   122 			dir.mkdirs();
   123 		}
   124 
   125 		for (File entry : directory.listFiles()) {
   126 			if (entry.isDirectory()) {
   127 				resizeDirectory(entry);
   128 			} else {
   129 				if (options.isSkipErrors()) {
   130 					try {
   131 						resizeFile(entry);
   132 					} catch (Exception e) {
   133 						counters.increment(Counters.COUNTER_TYPE.SKIPPED_ERROR);
   134 						LogRecord record = new LogRecord(Level.WARNING, "Skipping error : {0}");
   135 						record.setParameters(new Object[]{entry});
   136 						record.setThrown(e);
   137 						log.log(record);
   138 					}
   139 				} else {
   140 					resizeFile(entry);
   141 				}
   142 
   143 			}
   144 		}
   145 
   146 	}
   147 
   148 	private static File relativize(File root, File child) {
   149 		return root.toPath().relativize(child.toPath()).toFile();
   150 	}
   151 
   152 }