View Javadoc

1   /*
2    * Copyright 2016-2016 Hippo B.V. (http://www.onehippo.com)
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.onehippo.forge.gallerymagick.core.command;
17  
18  import java.awt.image.BufferedImage;
19  import java.io.File;
20  import java.io.IOException;
21  import java.util.Iterator;
22  
23  import javax.imageio.IIOImage;
24  import javax.imageio.ImageIO;
25  import javax.imageio.ImageReader;
26  import javax.imageio.ImageWriteParam;
27  import javax.imageio.ImageWriter;
28  import javax.imageio.stream.FileImageInputStream;
29  import javax.imageio.stream.FileImageOutputStream;
30  import javax.imageio.stream.ImageInputStream;
31  import javax.imageio.stream.ImageOutputStream;
32  
33  import org.apache.commons.io.FilenameUtils;
34  import org.apache.commons.io.IOUtils;
35  import org.imgscalr.Scalr;
36  import org.onehippo.forge.gallerymagick.core.ImageDimension;
37  
38  /**
39   * Utility to identify or resize images using Scalr library.
40   */
41  public class ScalrProcessorUtils {
42  
43      private ScalrProcessorUtils() {
44      }
45  
46      /**
47       * Detects the {@code sourceFile} and returns the size dimension from it.
48       * @param sourceFile source image file
49       * @return Detects the {@code sourceFile} and returns the size dimension from it
50       * @throws IOException if IO exception occurs
51       */
52      public static ImageDimension identifyDimension(File sourceFile) throws IOException {
53          ImageDimension dimension = null;
54          String extension = FilenameUtils.getExtension(sourceFile.getName());
55          Iterator<ImageReader> it = ImageIO.getImageReadersBySuffix(extension);
56  
57          if (!it.hasNext()) {
58              throw new IllegalArgumentException("Unsupported file name extension: " + sourceFile);
59          }
60  
61          ImageReader reader = null;
62  
63          try {
64              reader = getImageReader(sourceFile);
65              int width = reader.getWidth(reader.getMinIndex());
66              int height = reader.getHeight(reader.getMinIndex());
67              dimension = ImageDimension.from(width, height);
68          } finally {
69              if (reader != null) {
70                  reader.dispose();
71              }
72          }
73  
74          return dimension;
75      }
76  
77      /**
78       * Resize the given image {@code sourceFile} with resizing it to {@code width} and {@code height}
79       * and store the resized image to {@code targetFile}.
80       * @param sourceFile source image file
81       * @param targetFile target image file
82       * @param dimension image dimension
83       * @throws IOException if IO exception occurs
84       */
85      public static void resizeImage(File sourceFile, File targetFile, ImageDimension dimension) throws IOException {
86          resizeImage(sourceFile, targetFile, dimension, (String[]) null);
87      }
88  
89      /**
90       * Resize the given image {@code sourceFile} with resizing it to {@code width} and {@code height}
91       * and store the resized image to {@code targetFile}, with appending {@code extraOptions} in the command line if provided.
92       * @param sourceFile source image file
93       * @param targetFile target image file
94       * @param dimension image dimension
95       * @param extraOptions extra command line options
96       * @throws IOException if IO exception occurs
97       */
98      public static void resizeImage(File sourceFile, File targetFile, ImageDimension dimension, String... extraOptions)
99              throws IOException {
100         if (dimension == null) {
101             throw new IllegalArgumentException("Invalid dimension: " + dimension);
102         }
103 
104         ImageReader reader = null;
105         ImageWriter writer = null;
106 
107         try {
108             reader = getImageReader(sourceFile);
109 
110             if (reader == null) {
111                 throw new IllegalArgumentException("Unsupported image file name extension for reading: " + sourceFile);
112             }
113 
114             writer = getImageWriter(targetFile);
115 
116             if (writer == null) {
117                 throw new IllegalArgumentException("Unsupported image file name extension for writing: " + targetFile);
118             }
119 
120             BufferedImage sourceImage = reader.read(0);
121             BufferedImage resizedImage;
122             if (dimension.getHeight() == 0 && dimension.getWidth() == 0) {
123                 resizedImage = sourceImage;
124             } else {
125                 Scalr.Mode mode = Scalr.Mode.AUTOMATIC;
126                 if (dimension.getWidth() == 0) {
127                     mode = Scalr.Mode.FIT_TO_HEIGHT;
128                 } else if (dimension.getHeight() == 0) {
129                     mode = Scalr.Mode.FIT_TO_WIDTH;
130                 }
131                 resizedImage = Scalr.resize(sourceImage, Scalr.Method.QUALITY, mode,
132                         dimension.getWidth(), dimension.getHeight());
133             }
134 
135             final ImageWriteParam writeParam = writer.getDefaultWriteParam();
136 
137             if (writeParam.canWriteCompressed()) {
138                 String[] compressionTypes = writeParam.getCompressionTypes();
139 
140                 if (compressionTypes != null && compressionTypes.length > 0) {
141                     writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
142                     writeParam.setCompressionType(compressionTypes[0]);
143                     writeParam.setCompressionQuality(1.0f);
144                 }
145             }
146 
147             final IIOImage iioImage = new IIOImage(resizedImage, null, null);
148             writer.write(null, iioImage, writeParam);
149         } finally {
150             if (reader != null) {
151                 reader.dispose();
152             }
153             if (writer != null) {
154                 writer.dispose();
155             }
156         }
157     }
158 
159     /**
160      * Creates and returns an {@link ImageReader} instance from the {@code sourceFile}.
161      * @param sourceFile source file
162      * @return an {@link ImageReader} instance
163      * @throws IOException if IOException occurs
164      */
165     private static ImageReader getImageReader(File sourceFile) throws IOException {
166         ImageReader reader = null;
167         String extension = FilenameUtils.getExtension(sourceFile.getName());
168         Iterator<ImageReader> it = ImageIO.getImageReadersBySuffix(extension);
169 
170         if (it.hasNext()) {
171             reader = it.next();
172             ImageInputStream input = new FileImageInputStream(sourceFile);
173             reader.setInput(input);
174         }
175 
176         return reader;
177     }
178 
179     /**
180      * Creates and returns an {@link ImageWriter} instance from the {@code targetFile}.
181      * @param targetFile target file
182      * @return an {@link ImageWriter} instance
183      * @throws IOException if IOException occurs
184      */
185     private static ImageWriter getImageWriter(File targetFile) throws IOException {
186         ImageWriter writer = null;
187         String extension = FilenameUtils.getExtension(targetFile.getName());
188         Iterator<ImageWriter> it = ImageIO.getImageWritersBySuffix(extension);
189 
190         if (it.hasNext()) {
191             writer = it.next();
192             ImageOutputStream output = new FileImageOutputStream(targetFile);
193             writer.setOutput(output);
194         }
195 
196         return writer;
197     }
198 }