package net.coobird.thumbnailator; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import net.coobird.thumbnailator.builders.BufferedImageBuilder; import net.coobird.thumbnailator.builders.ThumbnailParameterBuilder; import net.coobird.thumbnailator.filters.ImageFilter; import net.coobird.thumbnailator.makers.FixedSizeThumbnailMaker; import net.coobird.thumbnailator.makers.ScaledThumbnailMaker; import net.coobird.thumbnailator.name.Rename; import net.coobird.thumbnailator.resizers.DefaultResizerFactory; import net.coobird.thumbnailator.resizers.Resizer; import net.coobird.thumbnailator.tasks.ThumbnailTask; /** * This class provides static utility methods which perform generation of * thumbnails using Thumbnailator. *

* When images are resized, the aspect ratio of the images are preserved. * * @author coobird * */ public final class Thumbnailator { /** * This class is not intended to be instantiated. */ private Thumbnailator() {} /** * Creates a thumbnail from parameters specified in a {@link ThumbnailTask}. * * @param task A {@link ThumbnailTask} to execute. * @throws IOException Thrown when a problem occurs when creating a * thumbnail. */ public static void createThumbnail(ThumbnailTask task) throws IOException { ThumbnailParameter param = task.getParam(); // Obtain the original image. BufferedImage sourceImage = task.read(); // Decide the image type of the destination image. int imageType = param.getType(); /* * If the imageType indicates that the image type of the original image * should be used in the thumbnail, then obtain the image type of the * original. * * If the original type is a custom type, then the default image type * will be used. */ if (param.useOriginalImageType()) { int imageTypeToUse = sourceImage.getType(); if (imageTypeToUse == BufferedImage.TYPE_CUSTOM) { imageType = ThumbnailParameter.DEFAULT_IMAGE_TYPE; } else { imageType = sourceImage.getType(); } } BufferedImage destinationImage; if (param.getSize() != null) { // Get the dimensions of the original and thumbnail images. int destinationWidth = param.getSize().width; int destinationHeight = param.getSize().height; // Create the thumbnail. destinationImage = new FixedSizeThumbnailMaker() .size(destinationWidth, destinationHeight) .keepAspectRatio(param.isKeepAspectRatio()) .fitWithinDimensions(param.fitWithinDimenions()) .imageType(imageType) .resizerFactory(param.getResizerFactory()) .make(sourceImage); } else if (!Double.isNaN(param.getWidthScalingFactor())) { // Create the thumbnail. destinationImage = new ScaledThumbnailMaker() .scale(param.getWidthScalingFactor(), param.getHeightScalingFactor()) .imageType(imageType) .resizerFactory(param.getResizerFactory()) .make(sourceImage); } else { throw new IllegalStateException("Parameters to make thumbnail" + " does not have scaling factor nor thumbnail size specified."); } // Perform the image filters for (ImageFilter filter : param.getImageFilters()) { destinationImage = filter.apply(destinationImage); } // Write the thumbnail image to the destination. task.write(destinationImage); sourceImage.flush(); destinationImage.flush(); } /** * Creates a thumbnail. *

* The resulting thumbnail uses the default image type. *

* When the image is resized, the aspect ratio will be preserved. *

* When the specified dimensions does not have the same aspect ratio as the * source image, the specified dimensions will be used as the absolute * boundary of the thumbnail. *

* For example, if the source image of 100 pixels by 100 pixels, and the * desired thumbnail size is 50 pixels by 100 pixels, then the resulting * thumbnail will be 50 pixels by 50 pixels, as the constraint will be * 50 pixels for the width, and therefore, by preserving the aspect ratio, * the height will be required to be 50 pixels. *

* * @param img The source image. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @return Resulting thumbnail. */ public static BufferedImage createThumbnail( BufferedImage img, int width, int height ) { validateDimensions(width, height); Dimension imgSize = new Dimension(img.getWidth(), img.getHeight()); Dimension thumbnailSize = new Dimension(width, height); Resizer resizer = DefaultResizerFactory.getInstance() .getResizer(imgSize, thumbnailSize); BufferedImage thumbnailImage = new FixedSizeThumbnailMaker(width, height, true, true) .resizer(resizer) .make(img); return thumbnailImage; } /** * Creates a thumbnail from an source image and writes the thumbnail to * a destination file. *

* The image format to use for the thumbnail will be determined from the * file extension. However, if the image format cannot be determined, then, * the same image format as the original image will be used when writing * the thumbnail. * * @param inFile The {@link File} from which image data is read. * @param outFile The {@link File} to which thumbnail is written. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. */ public static void createThumbnail( File inFile, File outFile, int width, int height ) throws IOException { validateDimensions(width, height); if (inFile == null) { throw new NullPointerException("Input file is null."); } else if (outFile == null) { throw new NullPointerException("Output file is null."); } if (!inFile.exists()) { throw new IOException("Input file does not exist."); } Thumbnails.of(inFile) .size(width, height) .toFile(outFile); } /** * Creates a thumbnail from an image file, and returns as a * {@link BufferedImage}. * * @param f The {@link File} from which image data is read. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @return The thumbnail image as a {@link BufferedImage}. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. */ public static BufferedImage createThumbnail( File f, int width, int height ) throws IOException { validateDimensions(width, height); if (f == null) { throw new NullPointerException("Input file is null."); } return Thumbnails.of(f).size(width, height).asBufferedImage(); } /** * Creates a thumbnail from an {@link Image}. *

* The resulting {@link BufferedImage} uses the default image type. *

* When the image is resized, the aspect ratio will be preserved. *

* When the specified dimensions does not have the same aspect ratio as the * source image, the specified dimensions will be used as the absolute * boundary of the thumbnail. * * @param img The source image. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @return The thumbnail image as an {@link Image}. */ public static Image createThumbnail( Image img, int width, int height ) { validateDimensions(width, height); // Copy the image from Image into a new BufferedImage. BufferedImage srcImg = new BufferedImageBuilder( img.getWidth(null), img.getHeight(null) ).build(); Graphics g = srcImg.createGraphics(); g.drawImage(img, width, height, null); g.dispose(); return createThumbnail(srcImg, width, height); } /** * Creates a thumbnail from image data streamed from an {@link InputStream} * and streams the data out to an {@link OutputStream}. *

* The thumbnail will be stored in the same format as the original image. * * @param is The {@link InputStream} from which to obtain * image data. * @param os The {@link OutputStream} to send thumbnail data to. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. */ public static void createThumbnail( InputStream is, OutputStream os, int width, int height ) throws IOException { Thumbnailator.createThumbnail( is, os, ThumbnailParameter.ORIGINAL_FORMAT, width, height); } /** * Creates a thumbnail from image data streamed from an {@link InputStream} * and streams the data out to an {@link OutputStream}, with the specified * format for the output data. * * @param is The {@link InputStream} from which to obtain * image data. * @param os The {@link OutputStream} to send thumbnail data to. * @param format The image format to use to store the thumbnail data. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. * @throws IllegalArgumentException If the specified output format is * not supported. */ public static void createThumbnail( InputStream is, OutputStream os, String format, int width, int height ) throws IOException { validateDimensions(width, height); if (is == null) { throw new NullPointerException("InputStream is null."); } else if (os == null) { throw new NullPointerException("OutputStream is null."); } Thumbnails.of(is) .size(width, height) .outputFormat(format) .toOutputStream(os); } /** * Creates thumbnails from a specified {@link Collection} of {@link File}s. * The filenames of the resulting thumbnails are determined by applying * the specified {@link Rename}. *

* The order of the thumbnail {@code File}s in the returned * {@code Collection} will be the same as the order as the source list. * * @param files A {@code Collection} containing {@code File} objects * of image files. * @param rename The renaming function to use. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. * * @deprecated This method has been deprecated in favor of using the * {@link Thumbnails#fromFiles(Iterable)} interface. * This method will be removed in 0.5.0, and will not be * further maintained. */ public static Collection createThumbnailsAsCollection( Collection files, Rename rename, int width, int height ) throws IOException { validateDimensions(width, height); if (files == null) { throw new NullPointerException("Collection of Files is null."); } if (rename == null) { throw new NullPointerException("Rename is null."); } ArrayList resultFiles = new ArrayList(); ThumbnailParameter param = new ThumbnailParameterBuilder() .size(width, height) .build(); for (File inFile : files) { File outFile = new File(inFile.getParent(), rename.apply(inFile.getName(), param)); createThumbnail(inFile, outFile, width, height); resultFiles.add(outFile); } return Collections.unmodifiableList(resultFiles); } /** * Creates thumbnails from a specified {@code Collection} of {@code File}s. * The filenames of the resulting thumbnails are determined by applying * the specified {@code Rename} function. * * @param files A {@code Collection} containing {@code File} objects * of image files. * @param rename The renaming function to use. * @param width The width of the thumbnail. * @param height The height of the thumbnail. * @throws IOException Thrown when a problem occurs when reading from * {@code File} representing an image file. * * @deprecated This method has been deprecated in favor of using the * {@link Thumbnails#fromFiles(Iterable)} interface. * This method will be removed in 0.5.0, and will not be * further maintained. */ public static void createThumbnails( Collection files, Rename rename, int width, int height ) throws IOException { validateDimensions(width, height); if (files == null) { throw new NullPointerException("Collection of Files is null."); } if (rename == null) { throw new NullPointerException("Rename is null."); } ThumbnailParameter param = new ThumbnailParameterBuilder() .size(width, height) .build(); for (File inFile : files) { File outFile = new File(inFile.getParent(), rename.apply(inFile.getName(), param)); createThumbnail(inFile, outFile, width, height); } } /** * Performs validation on the specified dimensions. *

* If any of the dimensions are less than or equal to 0, an * {@code IllegalArgumentException} is thrown with an message specifying the * reason for the exception. *

* This method is used to perform a check on the output dimensions of a * thumbnail for the {@link Thumbnails#createThumbnail} methods. * * @param width The width to validate. * @param height The height to validate. */ private static void validateDimensions(int width, int height) { if (width <= 0 && height <= 0) { throw new IllegalArgumentException( "Destination image dimensions must not be less than " + "0 pixels." ); } else if (width <= 0 || height <= 0) { String dimension = width == 0 ? "width" : "height"; throw new IllegalArgumentException( "Destination image " + dimension + " must not be " + "less than or equal to 0 pixels." ); } } }