java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java
author František Kučera <franta-hg@frantovo.cz>
Mon, 17 Nov 2014 17:02:48 +0100
changeset 7 8e9983260624
parent 6 b329573c76d7
child 10 a5a723467a39
permissions -rw-r--r--
first working version
     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.SingleImageResizer.ImageFormat;
    21 import java.awt.image.BufferedImage;
    22 import java.io.File;
    23 import java.io.FileInputStream;
    24 import java.io.FileNotFoundException;
    25 import java.io.FileOutputStream;
    26 import java.io.IOException;
    27 import java.io.InputStream;
    28 import java.nio.channels.Channels;
    29 import java.nio.channels.FileChannel;
    30 import java.nio.channels.ReadableByteChannel;
    31 import java.nio.channels.WritableByteChannel;
    32 import java.util.logging.Level;
    33 import java.util.logging.Logger;
    34 import javax.imageio.ImageIO;
    35 
    36 /**
    37  *
    38  * @author Ing. František Kučera (frantovo.cz)
    39  */
    40 public class RecursiveImageResizer {
    41 
    42 	private static final Logger log = Logger.getLogger(RecursiveImageResizer.class.getName());
    43 
    44 	private final SingleImageResizer resizer = new SingleImageResizer();
    45 
    46 	public void resize(RecursiveOptions options) throws RecursiveException, ResizeException {
    47 		resizeDirectory(options.getInput(), options);
    48 	}
    49 
    50 	private void resizeFile(File inputFile, RecursiveOptions options) throws ResizeException {
    51 		File inputFileRelative = relativize(options.getInput(), inputFile);
    52 		log.log(Level.FINE, "Resizing file: {0}", inputFileRelative);
    53 
    54 		ImageFormat format = ImageFormat.getMatching(inputFile.getName());
    55 
    56 		if (format == null) {
    57 			log.log(Level.FINE, "Skipping file: {0} (no image format matched this extension)", inputFileRelative);
    58 		} else {
    59 			try {
    60 				for (SizeSpecification size : options.getSizes()) {
    61 					File sizeRoot = new File(options.getOutput(), size.getDirectory());
    62 					File outputFile = new File(sizeRoot, inputFileRelative.getPath());
    63 					try (FileInputStream input = new FileInputStream(inputFile)) {
    64 						BufferedImage image = readImage(input);
    65 						if (shouldResize(image, size)) {
    66 							try (FileOutputStream output = new FileOutputStream(outputFile)) {
    67 								resizer.resize(image, output, size, format);
    68 							}
    69 						} else {
    70 							log.log(Level.INFO, "File: {0} has already required size → just copy", inputFileRelative);
    71 							justCopy(inputFile, outputFile);
    72 						}
    73 					}
    74 				}
    75 			} catch (FileNotFoundException e) {
    76 				throw new ResizeException("Error while opening stream", e);
    77 			} catch (IOException e) {
    78 				throw new ResizeException("Error while closing stream", e);
    79 			}
    80 		}
    81 	}
    82 
    83 	private static boolean shouldResize(BufferedImage input, SizeSpecification requested) {
    84 		if (requested.isResizeSmaller()) {
    85 			return input.getHeight() != requested.getHeight() || input.getWidth() != requested.getWidth();
    86 		} else {
    87 			return input.getHeight() > requested.getHeight() || input.getWidth() > requested.getWidth();
    88 		}
    89 	}
    90 
    91 	private static BufferedImage readImage(InputStream input) throws ResizeException {
    92 		try {
    93 			return ImageIO.read(input);
    94 		} catch (IOException e) {
    95 			throw new ResizeException("Unable to read image from stream", e);
    96 		}
    97 	}
    98 
    99 	private static void justCopy(File inputFile, File outputFile) throws ResizeException {
   100 		try {
   101 
   102 			if (!outputFile.exists()) {
   103 				outputFile.createNewFile();
   104 			}
   105 
   106 			try (FileChannel input = new FileInputStream(inputFile).getChannel()) {
   107 				try (FileChannel output = new FileOutputStream(outputFile).getChannel()) {
   108 					output.transferFrom(input, 0, input.size());
   109 				}
   110 			}
   111 
   112 		} catch (IOException e) {
   113 			throw new ResizeException("Unable copy stream/channel", e);
   114 		}
   115 
   116 	}
   117 
   118 	private void resizeDirectory(File directory, RecursiveOptions options) throws ResizeException {
   119 
   120 		log.log(Level.FINE, "Resizing directory: {0}", directory);
   121 
   122 		for (SizeSpecification size : options.getSizes()) {
   123 			File relative = relativize(options.getInput(), directory);
   124 			File sizeRoot = new File(options.getOutput(), size.getDirectory());
   125 			File dir = new File(sizeRoot, relative.getPath());
   126 			dir.mkdirs();
   127 		}
   128 
   129 		for (File entry : directory.listFiles()) {
   130 			if (entry.isDirectory()) {
   131 				resizeDirectory(entry, options);
   132 			} else {
   133 				resizeFile(entry, options);
   134 			}
   135 		}
   136 
   137 	}
   138 
   139 	private static File relativize(File root, File child) {
   140 		return root.toPath().relativize(child.toPath()).toFile();
   141 	}
   142 
   143 }