# HG changeset patch # User František Kučera # Date 1416240168 -3600 # Node ID 8e99832606245ee19dc9ab5a891f2021a10d7bc9 # Parent b329573c76d7cc60a1e175823c13418e3f1e59dd first working version diff -r b329573c76d7 -r 8e9983260624 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java Mon Nov 17 01:17:02 2014 +0100 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java Mon Nov 17 17:02:48 2014 +0100 @@ -18,12 +18,20 @@ package cz.frantovo.copyImageResizer; import cz.frantovo.copyImageResizer.SingleImageResizer.ImageFormat; +import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.util.logging.Level; import java.util.logging.Logger; +import javax.imageio.ImageIO; /** * @@ -39,24 +47,71 @@ resizeDirectory(options.getInput(), options); } - private void resizeFile(File file, RecursiveOptions options) throws ResizeException { - log.log(Level.FINE, "Resizing file: {0}", relativize(options.getInput(), file)); + private void resizeFile(File inputFile, RecursiveOptions options) throws ResizeException { + File inputFileRelative = relativize(options.getInput(), inputFile); + log.log(Level.FINE, "Resizing file: {0}", inputFileRelative); - ImageFormat format = ImageFormat.getMatching(file.getName()); + ImageFormat format = ImageFormat.getMatching(inputFile.getName()); if (format == null) { - log.log(Level.FINE, "Skipping file: {0} (no image format matched this extension)", relativize(options.getInput(), file)); + log.log(Level.FINE, "Skipping file: {0} (no image format matched this extension)", inputFileRelative); } else { try { - FileInputStream input = new FileInputStream(file); - File relative = relativize(options.getInput(), file); - File outputFile = new File(options.getOutput(), relative.getPath()); - FileOutputStream output = new FileOutputStream(outputFile); - resizer.resize(input, output, format); + for (SizeSpecification size : options.getSizes()) { + File sizeRoot = new File(options.getOutput(), size.getDirectory()); + File outputFile = new File(sizeRoot, inputFileRelative.getPath()); + try (FileInputStream input = new FileInputStream(inputFile)) { + BufferedImage image = readImage(input); + if (shouldResize(image, size)) { + try (FileOutputStream output = new FileOutputStream(outputFile)) { + resizer.resize(image, output, size, format); + } + } else { + log.log(Level.INFO, "File: {0} has already required size → just copy", inputFileRelative); + justCopy(inputFile, outputFile); + } + } + } } catch (FileNotFoundException e) { throw new ResizeException("Error while opening stream", e); + } catch (IOException e) { + throw new ResizeException("Error while closing stream", e); } } + } + + private static boolean shouldResize(BufferedImage input, SizeSpecification requested) { + if (requested.isResizeSmaller()) { + return input.getHeight() != requested.getHeight() || input.getWidth() != requested.getWidth(); + } else { + return input.getHeight() > requested.getHeight() || input.getWidth() > requested.getWidth(); + } + } + + private static BufferedImage readImage(InputStream input) throws ResizeException { + try { + return ImageIO.read(input); + } catch (IOException e) { + throw new ResizeException("Unable to read image from stream", e); + } + } + + private static void justCopy(File inputFile, File outputFile) throws ResizeException { + try { + + if (!outputFile.exists()) { + outputFile.createNewFile(); + } + + try (FileChannel input = new FileInputStream(inputFile).getChannel()) { + try (FileChannel output = new FileOutputStream(outputFile).getChannel()) { + output.transferFrom(input, 0, input.size()); + } + } + + } catch (IOException e) { + throw new ResizeException("Unable copy stream/channel", e); + } } @@ -64,9 +119,12 @@ log.log(Level.FINE, "Resizing directory: {0}", directory); - File relative = relativize(options.getInput(), directory); - File output = new File(options.getOutput(), relative.getPath()); - output.mkdirs(); + for (SizeSpecification size : options.getSizes()) { + File relative = relativize(options.getInput(), directory); + File sizeRoot = new File(options.getOutput(), size.getDirectory()); + File dir = new File(sizeRoot, relative.getPath()); + dir.mkdirs(); + } for (File entry : directory.listFiles()) { if (entry.isDirectory()) { diff -r b329573c76d7 -r 8e9983260624 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveOptions.java --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveOptions.java Mon Nov 17 01:17:02 2014 +0100 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveOptions.java Mon Nov 17 17:02:48 2014 +0100 @@ -63,34 +63,4 @@ public void addSize(SizeSpecification size) { sizes.add(size); } - - public static class SizeSpecification { - - private final int width; - private final int height; - private final String directory; - - public SizeSpecification(int width, int height, String directory) { - this.width = width; - this.height = height; - this.directory = directory; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public String getDirectory() { - return directory; - } - - @Override - public String toString() { - return width + "×" + height + " → " + directory; - } - } } diff -r b329573c76d7 -r 8e9983260624 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/SingleImageResizer.java --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/SingleImageResizer.java Mon Nov 17 01:17:02 2014 +0100 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/SingleImageResizer.java Mon Nov 17 17:02:48 2014 +0100 @@ -20,8 +20,9 @@ import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Pattern; import javax.imageio.ImageIO; @@ -31,10 +32,11 @@ */ public class SingleImageResizer { - public void resize(InputStream input, OutputStream output, ImageFormat outputFormat) throws ResizeException { + private static final Logger log = Logger.getLogger(SingleImageResizer.class.getName()); + + public void resize(BufferedImage input, OutputStream output, SizeSpecification size, ImageFormat outputFormat) throws ResizeException { try { - BufferedImage image = ImageIO.read(input); - BufferedImage resized = resize(image, 64, 64, image.getType()); + BufferedImage resized = resize(input, size.getWidth(), size.getHeight(), input.getType()); ImageIO.write(resized, outputFormat.getFormat(), output); } catch (IOException e) { @@ -56,6 +58,11 @@ height = maxHeight; } + if (type == BufferedImage.TYPE_CUSTOM) { + log.log(Level.FINE, "Setting default image type: from TYPE_CUSTOM to TYPE_INT_ARGB"); + type = BufferedImage.TYPE_INT_ARGB; + } + BufferedImage resized = new BufferedImage(width, height, type); Graphics2D g = resized.createGraphics(); g.drawImage(original, 0, 0, width, height, null); @@ -78,6 +85,9 @@ this.regex = regex; } + /** + * @return format name for {@linkplain ImageIO#write(java.awt.image.RenderedImage, java.lang.String, java.io.File) + */ public String getFormat() { return format; } diff -r b329573c76d7 -r 8e9983260624 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/SizeSpecification.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/SizeSpecification.java Mon Nov 17 17:02:48 2014 +0100 @@ -0,0 +1,58 @@ +/** + * copy-image-resizer + * Copyright © 2014 František Kučera (frantovo.cz) + * + * 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 3 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, see . + */ +package cz.frantovo.copyImageResizer; + +/** + * + * @author Ing. František Kučera (frantovo.cz) + */ +public class SizeSpecification { + + private final int width; + private final int height; + private final String directory; + private final boolean resizeSmaller; + + public SizeSpecification(int width, int height, String directory, boolean resizeSmaller) { + this.width = width; + this.height = height; + this.directory = directory; + this.resizeSmaller = resizeSmaller; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public String getDirectory() { + return directory; + } + + public boolean isResizeSmaller() { + return resizeSmaller; + } + + @Override + public String toString() { + return width + "×" + height + " → " + directory; + } +} diff -r b329573c76d7 -r 8e9983260624 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIParser.java --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIParser.java Mon Nov 17 01:17:02 2014 +0100 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIParser.java Mon Nov 17 17:02:48 2014 +0100 @@ -18,6 +18,7 @@ package cz.frantovo.copyImageResizer.cli; import cz.frantovo.copyImageResizer.RecursiveOptions; +import cz.frantovo.copyImageResizer.SizeSpecification; import java.io.File; import java.util.Arrays; import java.util.Collection; @@ -52,11 +53,21 @@ return options; } - private static String fetchNext(String[] args, int index) throws CLIParserException { + /** + * + * @param args + * @param index + * @param option name of the option for error messages | if null, the previous argument is used + * as option name + * @return + * @throws CLIParserException + */ + private static String fetchNext(String[] args, int index, String option) throws CLIParserException { if (index < args.length) { return args[index]; } else { - throw new CLIParserException("Expecting value for option: " + args[index - 1]); + option = option == null ? args[index - 1] : option; + throw new CLIParserException("Expecting value for option: " + option); } } @@ -66,7 +77,7 @@ @Override public int parse(String[] args, int index, RecursiveOptions options) throws CLIParserException { int originalIndex = index; - String name = fetchNext(args, ++index); + String name = fetchNext(args, ++index, args[originalIndex]); options.setInput(new File(name)); return index - originalIndex; } @@ -75,7 +86,7 @@ @Override public int parse(String[] args, int index, RecursiveOptions options) throws CLIParserException { int originalIndex = index; - String name = fetchNext(args, ++index); + String name = fetchNext(args, ++index, args[originalIndex]); options.setOutput(new File(name)); return index - originalIndex; } @@ -84,10 +95,11 @@ @Override public int parse(String[] args, int index, RecursiveOptions options) throws CLIParserException { int originalIndex = index; - int width = parseInt(fetchNext(args, ++index)); - int height = parseInt(fetchNext(args, ++index)); + int width = parseInt(fetchNext(args, ++index, args[originalIndex])); + int height = parseInt(fetchNext(args, ++index, args[originalIndex])); + boolean resizeSmaller = parseBoolean(fetchNext(args, ++index, args[originalIndex])); String directory = width + "x" + height; - options.addSize(new RecursiveOptions.SizeSpecification(width, height, directory)); + options.addSize(new SizeSpecification(width, height, directory, resizeSmaller)); return index - originalIndex; } }, @@ -95,10 +107,11 @@ @Override public int parse(String[] args, int index, RecursiveOptions options) throws CLIParserException { int originalIndex = index; - int width = parseInt(fetchNext(args, ++index)); - int height = parseInt(fetchNext(args, ++index)); - String directory = fetchNext(args, ++index); - options.addSize(new RecursiveOptions.SizeSpecification(width, height, directory)); + int width = parseInt(fetchNext(args, ++index, args[originalIndex])); + int height = parseInt(fetchNext(args, ++index, args[originalIndex])); + boolean resizeSmaller = parseBoolean(fetchNext(args, ++index, args[originalIndex])); + String directory = fetchNext(args, ++index, args[originalIndex]); + options.addSize(new SizeSpecification(width, height, directory, resizeSmaller)); return index - originalIndex; } }; @@ -125,6 +138,17 @@ } } + private static boolean parseBoolean(String value) throws CLIParserException { + switch (value) { + case "true": + return true; + case "false": + return false; + default: + throw new CLIParserException("Value „" + value + "“ is not a valid boolean. Expecting „true“ or „false“."); + } + } + /** * Parse String arguments and fill values into the options object. *