/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.app; import boofcv.alg.filter.misc.AverageDownSampleOps; import boofcv.io.image.ConvertBufferedImage; import boofcv.io.image.UtilImageIO; import boofcv.misc.BoofMiscOps; import boofcv.struct.image.GrayU8; import boofcv.struct.image.ImageBase; import boofcv.struct.image.ImageGray; import boofcv.struct.image.Planar; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * Loads a set of images, resizes them to a smaller size using an intelligent algorithm then saves them. * * @author Peter Abeles */ public class BatchDownSizeImage { public static List<File> images; public static File outputDir; // if true it will rename the input to files with consecutive numbers public static boolean rename = false; public static int width=0,height=0,side=0; // should it set the size using "side" public static boolean useSide = false; public static void printHelpAndExit(String[] args) { System.out.println("=== Usage"); System.out.println("BatchDownSizeImage <flags> <input file path regex> <output> <width> <height>"); System.out.println("BatchDownSizeImage <flags> <input file path regex> <output> <max length>"); System.out.println(); System.out.println("Downsizes multiple files at once using average resampling. When resizing a image "+ "to less than 50% of its original size this will typically perform much better than "+ "standard interpolation techniques. Output images are in png format."); System.out.println(); System.out.println("=== Flags"); System.out.println("-rename Renames the output files to image%05d.png"); System.out.println(); System.out.println("=== Arguments"); System.out.println("First argument is a Java regex for input files."); System.out.println(" /path/to/input/directory/\\\\w*.jpg"); System.out.println("Second argument is a path to the output directory"); System.out.println("If there are 4 arguments then last two is the width and height"); System.out.println(" either width or height can be zero. If zero then it will maintain the aspect"); System.out.println(" ratio of the input file."); System.out.println("If there are 3 arguments then that value is the length of the largest side"); System.out.println(" The other side will be set according to the aspect ratio."); System.exit(0); } private static void parseArguments(String[] args) { int start = 0; for (; start < args.length; start++) { String s = args[start]; if( s.charAt(0) == '-') { if( s.substring(1,s.length()).compareToIgnoreCase("rename") == 0 ) { rename = true; } else { printHelpAndExit(args); } } else { break; } } if( args.length-start > 4 || args.length-start < 3 ) printHelpAndExit(args); String fileRegex = args[start]; String output = args[start+1]; if( args.length-start == 3 ) { useSide = true; side = Integer.parseInt(args[start+2]); if( side <= 0 ) printHelpAndExit(args); } else { width = Integer.parseInt(args[start+2]); height = Integer.parseInt(args[start+3]); if( width <= 0 && height <= 0 ) printHelpAndExit(args); } outputDir = new File(output); if( !outputDir.exists() ) if( !outputDir.mkdirs() ) throw new IllegalArgumentException("Can't create output directory: "+output); images = Arrays.asList(BoofMiscOps.findMatches(fileRegex)); Collections.sort(images); if( images.size() == 0 ) { System.out.println(fileRegex); System.err.println("No images found. Is the path/regex correct?"); System.exit(1); } } public static void main(String[] args) { parseArguments(args); ImageBase input = new GrayU8(1,1); ImageBase small = null; int index = 0; for ( File f : images) { BufferedImage orig = UtilImageIO.loadImage(f.getPath()); WritableRaster info = orig.getRaster(); boolean missMatch = false; if( input.getWidth() != info.getWidth() || input.getHeight() != info.getHeight()) { missMatch = true; } if( info.getNumBands() == 1 ) { if( !(input instanceof ImageGray) ) missMatch = true; } else { if( !(input instanceof Planar)) { missMatch = true; } else if( info.getNumBands() != ((Planar)input).getNumBands() ) { missMatch = true; } } if( missMatch ) { // declare the BoofCV image to conver the input into if( info.getNumBands() == 1 ) { input = new GrayU8(info.getWidth(),info.getHeight()); } else { input = new Planar<>(GrayU8.class,info.getWidth(),info.getHeight(),info.getNumBands()); } // Now declare storage for the small image int smallHeight,smallWidth; if( useSide ) { if( input.getWidth() > input.getHeight() ) { width = side; height = 0; } else { height = side; width = 0; } } if( height == 0 ) { smallWidth = width; smallHeight = input.getHeight()*width/input.getWidth(); } else if( width == 0 ) { smallWidth = input.getWidth()*height/input.getHeight(); smallHeight = height; } else { smallWidth = width; smallHeight = height; } small = input.createNew(smallWidth,smallHeight); } System.out.printf(" %4d out of %4d %s\n",index+1,images.size(),f.getName()); ConvertBufferedImage.convertFrom(orig, input, true); AverageDownSampleOps.down(input,small); String nout; if( rename ) { nout = String.format("image%05d.png",index); } else { nout = f.getName(); nout = nout.substring(0, nout.length() - 3) + "png"; } File fout = new File(outputDir,nout); UtilImageIO.saveImage(small, fout.getPath()); index++; } System.out.println("Done"); } }