001: /**
002: * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
003: *
004: * This program is free software; you can redistribute it and/or modify
005: * it under the terms of the latest version of the GNU Lesser General
006: * Public License as published by the Free Software Foundation;
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public License
014: * along with this program (LICENSE.txt); if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
016: */package org.jamwiki.utils;
017:
018: import java.awt.Graphics2D;
019: import java.awt.Image;
020: import java.awt.image.BufferedImage;
021: import java.io.File;
022: import java.io.FileInputStream;
023: import java.io.FileOutputStream;
024: import javax.imageio.ImageIO;
025: import net.sf.ehcache.Element;
026: import org.jamwiki.Environment;
027: import org.jamwiki.model.WikiImage;
028: import org.jamwiki.model.WikiFile;
029:
030: /**
031: * Utility methods for readding images from disk, saving images to disk,
032: * resizing images, and returning information about images such as width and
033: * height.
034: */
035: public class ImageUtil {
036:
037: private static final WikiLogger logger = WikiLogger
038: .getLogger(ImageUtil.class.getName());
039: private static final String CACHE_IMAGES = "org.jamwiki.utils.ImageUtils.CACHE_IMAGES";
040:
041: /**
042: *
043: */
044: private ImageUtil() {
045: }
046:
047: /**
048: *
049: */
050: private static int calculateImageIncrement(int maxDimension) {
051: int increment = Environment
052: .getIntValue(Environment.PROP_IMAGE_RESIZE_INCREMENT);
053: double result = Math.ceil((double) maxDimension
054: / (double) increment)
055: * increment;
056: return (int) result;
057: }
058:
059: /**
060: * Convert a Java Image object to a Java BufferedImage object.
061: */
062: private static BufferedImage imageToBufferedImage(Image image)
063: throws Exception {
064: BufferedImage bufferedImage = new BufferedImage(image
065: .getWidth(null), image.getHeight(null),
066: BufferedImage.TYPE_INT_RGB);
067: Graphics2D graphics = bufferedImage.createGraphics();
068: graphics.drawImage(image, 0, 0, null);
069: graphics.dispose();
070: return bufferedImage;
071: }
072:
073: /**
074: * Given a virtualWiki and WikiFIle that correspond to an existing image,
075: * return the WikiImage object. In addition, an optional maxDimension
076: * parameter may be specified, in which case a resized version of the image
077: * may be created.
078: *
079: * @param wikiFile Given a WikiFile object, use it to initialize a
080: * WikiImage object.
081: * @param maxDimension The maximum width or height for the initialized
082: * WikiImage object. Setting this value to 0 or less will cause the
083: * value to be ignored.
084: * @return An initialized WikiImage object.
085: * @throws Exception Thrown if an error occurs while initializing the
086: * WikiImage object.
087: */
088: public static WikiImage initializeImage(WikiFile wikiFile,
089: int maxDimension) throws Exception {
090: if (wikiFile == null) {
091: throw new IllegalArgumentException(
092: "wikiFile may not be null");
093: }
094: WikiImage wikiImage = new WikiImage(wikiFile);
095: BufferedImage imageObject = null;
096: if (maxDimension > 0) {
097: imageObject = ImageUtil
098: .resizeImage(wikiImage, maxDimension);
099: setScaledDimensions(imageObject, wikiImage, maxDimension);
100: } else {
101: File imageFile = new File(Environment
102: .getValue(Environment.PROP_FILE_DIR_FULL_PATH),
103: wikiImage.getUrl());
104: imageObject = ImageUtil.loadImage(imageFile);
105: wikiImage.setWidth(imageObject.getWidth());
106: wikiImage.setHeight(imageObject.getHeight());
107: }
108: return wikiImage;
109: }
110:
111: /**
112: * Given a File object, determine if the file is an image or if it is some
113: * other type of file. Note that this method will read in the entire file,
114: * so there are performance implications for large files.
115: *
116: * @param file The File object for the file that is being examined.
117: * @return Returns <code>true</code> if the file is an image object.
118: * @throws Exception Thrown if any error occurs while reading the file.
119: */
120: public static boolean isImage(File file) throws Exception {
121: return (ImageUtil.loadImage(file) != null);
122: }
123:
124: /**
125: * Given a file that corresponds to an existing image, return a
126: * BufferedImage object.
127: */
128: private static BufferedImage loadImage(File file) throws Exception {
129: BufferedImage image = null;
130: String key = file.getPath();
131: Element cacheElement = WikiCache.retrieveFromCache(
132: CACHE_IMAGES, key);
133: if (cacheElement != null) {
134: return (BufferedImage) cacheElement.getObjectValue();
135: }
136: FileInputStream fis = null;
137: try {
138: fis = new FileInputStream(file);
139: image = ImageIO.read(fis);
140: WikiCache.addToCache(CACHE_IMAGES, key, image);
141: return image;
142: } finally {
143: if (fis != null) {
144: try {
145: fis.close();
146: } catch (Exception e) {
147: }
148: }
149: }
150: }
151:
152: /**
153: * Resize an image, using a maximum dimension value. Image dimensions will
154: * be constrained so that the proportions are the same, but neither the width
155: * or height exceeds the value specified.
156: */
157: private static BufferedImage resizeImage(WikiImage wikiImage,
158: int maxDimension) throws Exception {
159: File imageFile = new File(Environment
160: .getValue(Environment.PROP_FILE_DIR_FULL_PATH),
161: wikiImage.getUrl());
162: BufferedImage original = ImageUtil.loadImage(imageFile);
163: maxDimension = calculateImageIncrement(maxDimension);
164: int increment = Environment
165: .getIntValue(Environment.PROP_IMAGE_RESIZE_INCREMENT);
166: if (increment <= 0
167: || (maxDimension > original.getWidth() && maxDimension > original
168: .getHeight())) {
169: // let the browser scale the image
170: return original;
171: }
172: String newUrl = wikiImage.getUrl();
173: int pos = newUrl.lastIndexOf('.');
174: if (pos > -1) {
175: newUrl = newUrl.substring(0, pos) + "-" + maxDimension
176: + "px" + newUrl.substring(pos);
177: } else {
178: newUrl += "-" + maxDimension + "px";
179: }
180: wikiImage.setUrl(newUrl);
181: File newImageFile = new File(Environment
182: .getValue(Environment.PROP_FILE_DIR_FULL_PATH), newUrl);
183: if (newImageFile.exists()) {
184: return ImageUtil.loadImage(newImageFile);
185: }
186: int width = -1;
187: int height = -1;
188: if (original.getWidth() >= original.getHeight()) {
189: width = maxDimension;
190: } else {
191: height = maxDimension;
192: }
193: Image resized = null;
194: try {
195: resized = original.getScaledInstance(width, height,
196: Image.SCALE_AREA_AVERAGING);
197: } catch (Throwable t) {
198: logger
199: .severe(
200: "Unable to resize image. This problem sometimes occurs due to dependencies between Java and X on UNIX systems. Consider enabling an X server or setting the java.awt.headless parameter to true for your JVM.",
201: t);
202: resized = original;
203: }
204: BufferedImage bufferedImage = null;
205: if (resized instanceof BufferedImage) {
206: bufferedImage = (BufferedImage) resized;
207: } else {
208: bufferedImage = ImageUtil.imageToBufferedImage(resized);
209: }
210: ImageUtil.saveImage(bufferedImage, newImageFile);
211: return bufferedImage;
212: }
213:
214: /**
215: * Save an image to a specified file.
216: */
217: private static void saveImage(BufferedImage image, File file)
218: throws Exception {
219: String filename = file.getName();
220: int pos = filename.lastIndexOf('.');
221: if (pos == -1 || (pos + 1) >= filename.length()) {
222: throw new Exception("Unknown image type " + filename);
223: }
224: String imageType = filename.substring(pos + 1);
225: File imageFile = new File(file.getParent(), filename);
226: FileOutputStream fos = null;
227: try {
228: fos = new FileOutputStream(imageFile);
229: ImageIO.write(image, imageType, fos);
230: } finally {
231: if (fos != null) {
232: try {
233: fos.close();
234: } catch (Exception e) {
235: }
236: }
237: }
238: }
239:
240: /**
241: *
242: */
243: private static void setScaledDimensions(
244: BufferedImage bufferedImage, WikiImage wikiImage,
245: int maxDimension) {
246: int width = bufferedImage.getWidth();
247: int height = bufferedImage.getHeight();
248: if (width >= height) {
249: height = (int) Math
250: .floor(((double) maxDimension / (double) width)
251: * (double) height);
252: width = maxDimension;
253: } else {
254: width = (int) Math
255: .floor(((double) maxDimension / (double) height)
256: * (double) width);
257: height = maxDimension;
258: }
259: wikiImage.setWidth(width);
260: wikiImage.setHeight(height);
261: }
262: }
|