001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.shared.media.impl;
034:
035: import com.flexive.shared.exceptions.FxApplicationException;
036: import com.flexive.shared.media.FxMetadata;
037: import org.apache.commons.lang.StringUtils;
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040: import org.apache.sanselan.ImageFormat;
041: import org.apache.sanselan.ImageInfo;
042: import org.apache.sanselan.Sanselan;
043: import org.apache.sanselan.common.IImageMetadata;
044: import org.apache.sanselan.common.ImageMetadata;
045:
046: import javax.imageio.ImageIO;
047: import javax.swing.*;
048: import java.awt.*;
049: import java.awt.image.BufferedImage;
050: import java.io.File;
051: import java.util.ArrayList;
052: import java.util.HashMap;
053: import java.util.List;
054:
055: /**
056: * Java native Engine
057: * This engine relies on java image io and apache sanselan
058: *
059: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
060: * @version $Rev
061: */
062: public class FxMediaNativeEngine {
063: private static final transient Log LOG = LogFactory
064: .getLog(FxMediaNativeEngine.class);
065:
066: /**
067: * Scale an image and return the dimensions (width and height) as int array
068: *
069: * @param original original file
070: * @param scaled scaled file
071: * @param extension extension
072: * @param width desired width
073: * @param height desired height
074: * @return actual width ([0]) and height ([1]) of scaled image
075: * @throws FxApplicationException on errors
076: */
077: public static int[] scale(File original, File scaled,
078: String extension, int width, int height)
079: throws FxApplicationException {
080: BufferedImage bi;
081: try {
082: bi = ImageIO.read(original);
083: } catch (Exception e) {
084: LOG.info("Failed to read " + original.getName()
085: + " using ImageIO, trying sanselan");
086: try {
087: bi = Sanselan.getBufferedImage(original);
088: } catch (Exception e1) {
089: throw new FxApplicationException(LOG,
090: "ex.media.readFallback.error", original
091: .getName(), extension, e.getMessage(),
092: e1.getMessage());
093: }
094: }
095: int scaleWidth = bi.getWidth(null);
096: int scaleHeight = bi.getHeight(null);
097: double scaleX = (double) width / scaleWidth;
098: double scaleY = (double) height / scaleHeight;
099: double scale = Math.min(scaleX, scaleY);
100: scaleWidth = (int) ((double) scaleWidth * scale);
101: scaleHeight = (int) ((double) scaleHeight * scale);
102: Image scaledImage;
103: GraphicsConfiguration gc = GraphicsEnvironment
104: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
105: .getDefaultConfiguration();
106: BufferedImage bi2 = gc.createCompatibleImage(scaleWidth,
107: scaleHeight, bi.getTransparency());
108: Graphics2D g = bi2.createGraphics();
109: if (scale < 0.3) {
110: scaledImage = bi.getScaledInstance(scaleWidth, scaleHeight,
111: Image.SCALE_SMOOTH);
112: new ImageIcon(scaledImage).getImage();
113: g.drawImage(scaledImage, 0, 0, scaleWidth, scaleHeight,
114: null);
115: } else {
116: g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
117: RenderingHints.VALUE_INTERPOLATION_BICUBIC);
118: g.drawImage(bi, 0, 0, scaleWidth, scaleHeight, null);
119: }
120: String eMsg;
121: boolean fallback;
122: try {
123: fallback = !ImageIO.write(bi2, extension.substring(1),
124: scaled);
125: eMsg = "No ImageIO writer found.";
126: } catch (Exception e) {
127: eMsg = e.getMessage();
128: fallback = true;
129: }
130: if (fallback) {
131: try {
132: ImageFormat iFormat;
133: if (".BMP".equals(extension))
134: iFormat = ImageFormat.IMAGE_FORMAT_BMP;
135: else if (".TIF".equals(extension))
136: iFormat = ImageFormat.IMAGE_FORMAT_TIFF;
137: else if (".PNG".equals(extension))
138: iFormat = ImageFormat.IMAGE_FORMAT_PNG;
139: else
140: iFormat = ImageFormat.IMAGE_FORMAT_GIF;
141: Sanselan
142: .writeImage(bi2, scaled, iFormat, new HashMap());
143: } catch (Exception e1) {
144: throw new FxApplicationException(LOG,
145: "ex.media.write.error", scaled.getName(),
146: extension, eMsg + ", " + e1.getMessage());
147: }
148: }
149: return new int[] { scaleWidth, scaleHeight };
150: }
151:
152: /**
153: * Identify a file, returning metadata
154: *
155: * @param mimeType if not null it will be used to call the correct identify routine
156: * @param file the file to identify
157: * @return metadata
158: * @throws FxApplicationException on errors
159: */
160: public static FxMetadata identify(String mimeType, File file)
161: throws FxApplicationException {
162: try {
163: ImageInfo sii = Sanselan.getImageInfo(file);
164: IImageMetadata md = Sanselan.getMetadata(file);
165: List<FxMetadata.FxMetadataItem> metaItems;
166: if (md == null || md.getItems() == null)
167: metaItems = new ArrayList<FxMetadata.FxMetadataItem>(0);
168: else {
169: metaItems = new ArrayList<FxMetadata.FxMetadataItem>(md
170: .getItems().size());
171: for (Object o : md.getItems()) {
172: if (o instanceof ImageMetadata.Item) {
173: ImageMetadata.Item mdi = (ImageMetadata.Item) o;
174: if (!"Unknown".equals(mdi.getKeyword()))
175: metaItems
176: .add(new FxMetadata.FxMetadataItem(
177: mdi.getKeyword(),
178: parseText(mdi.getText())));
179: }
180: }
181: }
182: return new FxImageMetadataImpl(mimeType, file.getName(),
183: metaItems, sii.getWidth(), sii.getHeight(), sii
184: .getFormat().name, sii.getFormatName(), sii
185: .getCompressionAlgorithm(), sii
186: .getPhysicalWidthDpi(), sii
187: .getPhysicalHeightDpi(), sii
188: .getColorTypeDescription(), sii
189: .getUsesPalette(), sii.getBitsPerPixel(),
190: sii.getIsProgressive(), sii.getIsTransparent(),
191: Sanselan.getICCProfile(file));
192: } catch (Exception e) {
193: throw new FxApplicationException("ex.media.identify.error",
194: (file == null ? "unknown" : file.getName()),
195: mimeType, e.getMessage());
196: }
197: }
198:
199: /**
200: * Filter out '' from strings and avoid null-Strings
201: *
202: * @param text text to parse
203: * @return filtered text
204: */
205: private static String parseText(String text) {
206: if (StringUtils.isEmpty(text))
207: return "";
208: if (text.startsWith("'") && text.endsWith("'"))
209: return text.substring(1, text.length() - 1);
210: return text;
211: }
212: }
|