franta-hg@5: /** franta-hg@5: * copy-image-resizer franta-hg@5: * Copyright © 2014 František Kučera (frantovo.cz) franta-hg@5: * franta-hg@5: * This program is free software: you can redistribute it and/or modify franta-hg@5: * it under the terms of the GNU General Public License as published by franta-hg@5: * the Free Software Foundation, either version 3 of the License, or franta-hg@5: * (at your option) any later version. franta-hg@5: * franta-hg@5: * This program is distributed in the hope that it will be useful, franta-hg@5: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@5: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@5: * GNU General Public License for more details. franta-hg@5: * franta-hg@5: * You should have received a copy of the GNU General Public License franta-hg@5: * along with this program. If not, see . franta-hg@5: */ franta-hg@5: package cz.frantovo.copyImageResizer; franta-hg@5: franta-hg@17: import cz.frantovo.copyImageResizer.JavaSingleImageResizer.ImageFormat; franta-hg@6: import java.io.File; franta-hg@6: import java.io.FileInputStream; franta-hg@6: import java.io.FileNotFoundException; franta-hg@6: import java.io.FileOutputStream; franta-hg@7: import java.io.IOException; franta-hg@7: import java.nio.channels.FileChannel; franta-hg@6: import java.util.logging.Level; franta-hg@14: import java.util.logging.LogRecord; franta-hg@6: import java.util.logging.Logger; franta-hg@6: franta-hg@5: /** franta-hg@5: * franta-hg@5: * @author Ing. František Kučera (frantovo.cz) franta-hg@5: */ franta-hg@5: public class RecursiveImageResizer { franta-hg@5: franta-hg@6: private static final Logger log = Logger.getLogger(RecursiveImageResizer.class.getName()); franta-hg@13: franta-hg@12: private final Counters counters = new Counters(); franta-hg@6: franta-hg@17: /** franta-hg@17: * TODO: support plugins – several implementations of SingleImageResizer franta-hg@17: */ franta-hg@17: private final SingleImageResizer resizer = new JavaSingleImageResizer(); franta-hg@6: franta-hg@11: private final RecursiveOptions options; franta-hg@11: franta-hg@11: public RecursiveImageResizer(RecursiveOptions options) { franta-hg@11: this.options = options; franta-hg@6: } franta-hg@6: franta-hg@12: public Counters resize() throws RecursiveException, ResizeException { franta-hg@11: resizeDirectory(options.getInput()); franta-hg@12: return counters; franta-hg@11: } franta-hg@11: franta-hg@11: private void resizeFile(File inputFile) throws ResizeException { franta-hg@7: File inputFileRelative = relativize(options.getInput(), inputFile); franta-hg@10: log.log(Level.FINER, "Resizing file: {0}", inputFileRelative); franta-hg@13: counters.increment(Counters.COUNTER_TYPE.FILES); franta-hg@6: franta-hg@7: ImageFormat format = ImageFormat.getMatching(inputFile.getName()); franta-hg@6: franta-hg@6: if (format == null) { franta-hg@10: log.log(Level.FINER, "Skipping file: {0} (no image format matched this extension)", inputFileRelative); franta-hg@13: counters.increment(Counters.COUNTER_TYPE.SKIPPED_UNKNOWN_EXTENSION); franta-hg@6: } else { franta-hg@6: try { franta-hg@7: for (SizeSpecification size : options.getSizes()) { franta-hg@7: File sizeRoot = new File(options.getOutput(), size.getDirectory()); franta-hg@7: File outputFile = new File(sizeRoot, inputFileRelative.getPath()); franta-hg@7: try (FileInputStream input = new FileInputStream(inputFile)) { franta-hg@15: franta-hg@15: try (FileOutputStream output = new FileOutputStream(outputFile)) { franta-hg@15: boolean wasResized = resizer.resize(input, output, size, format); franta-hg@15: if (wasResized) { franta-hg@13: counters.increment(Counters.COUNTER_TYPE.RESIZED); franta-hg@15: } else { franta-hg@15: log.log(Level.FINER, "File: {0} has already required (or smaller) size → just copy", inputFileRelative); franta-hg@15: justCopy(inputFile, outputFile); franta-hg@15: counters.increment(Counters.COUNTER_TYPE.JUST_COPIED); franta-hg@7: } franta-hg@7: } franta-hg@7: } franta-hg@7: } franta-hg@6: } catch (FileNotFoundException e) { franta-hg@6: throw new ResizeException("Error while opening stream", e); franta-hg@7: } catch (IOException e) { franta-hg@7: throw new ResizeException("Error while closing stream", e); franta-hg@6: } franta-hg@6: } franta-hg@7: } franta-hg@7: franta-hg@7: private static void justCopy(File inputFile, File outputFile) throws ResizeException { franta-hg@7: try { franta-hg@7: franta-hg@7: if (!outputFile.exists()) { franta-hg@7: outputFile.createNewFile(); franta-hg@7: } franta-hg@7: franta-hg@7: try (FileChannel input = new FileInputStream(inputFile).getChannel()) { franta-hg@7: try (FileChannel output = new FileOutputStream(outputFile).getChannel()) { franta-hg@7: output.transferFrom(input, 0, input.size()); franta-hg@7: } franta-hg@7: } franta-hg@7: franta-hg@7: } catch (IOException e) { franta-hg@7: throw new ResizeException("Unable copy stream/channel", e); franta-hg@7: } franta-hg@6: franta-hg@6: } franta-hg@6: franta-hg@11: private void resizeDirectory(File directory) throws ResizeException { franta-hg@6: franta-hg@6: log.log(Level.FINE, "Resizing directory: {0}", directory); franta-hg@13: counters.increment(Counters.COUNTER_TYPE.DIRECTORIES); franta-hg@6: franta-hg@7: for (SizeSpecification size : options.getSizes()) { franta-hg@7: File relative = relativize(options.getInput(), directory); franta-hg@7: File sizeRoot = new File(options.getOutput(), size.getDirectory()); franta-hg@7: File dir = new File(sizeRoot, relative.getPath()); franta-hg@7: dir.mkdirs(); franta-hg@7: } franta-hg@6: franta-hg@6: for (File entry : directory.listFiles()) { franta-hg@6: if (entry.isDirectory()) { franta-hg@11: resizeDirectory(entry); franta-hg@6: } else { franta-hg@14: if (options.isSkipErrors()) { franta-hg@14: try { franta-hg@14: resizeFile(entry); franta-hg@14: } catch (Exception e) { franta-hg@14: counters.increment(Counters.COUNTER_TYPE.SKIPPED_ERROR); franta-hg@14: LogRecord record = new LogRecord(Level.WARNING, "Skipping error : {0}"); franta-hg@14: record.setParameters(new Object[]{entry}); franta-hg@14: record.setThrown(e); franta-hg@14: log.log(record); franta-hg@14: } franta-hg@14: } else { franta-hg@14: resizeFile(entry); franta-hg@14: } franta-hg@14: franta-hg@6: } franta-hg@6: } franta-hg@6: franta-hg@6: } franta-hg@6: franta-hg@6: private static File relativize(File root, File child) { franta-hg@6: return root.toPath().relativize(child.toPath()).toFile(); franta-hg@5: } franta-hg@5: franta-hg@5: }