KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > taglibs > util > ScaleImageTag


1 /**
2  *
3  * Magnolia and its source-code is licensed under the LGPL.
4  * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
5  * When copying, adapting, or redistributing this document in keeping with the guidelines above,
6  * you are required to provide proper attribution to obinary.
7  * If you reproduce or distribute the document without making any substantive modifications to its content,
8  * please use the following attribution line:
9  *
10  * Copyright 1993-2006 obinary Ltd. (http://www.obinary.com) All rights reserved.
11  *
12  */

13 package info.magnolia.cms.taglibs.util;
14
15 import info.magnolia.cms.beans.config.ContentRepository;
16 import info.magnolia.cms.core.Content;
17 import info.magnolia.cms.core.HierarchyManager;
18 import info.magnolia.cms.core.ItemType;
19 import info.magnolia.cms.core.NodeData;
20 import info.magnolia.cms.util.Resource;
21 import info.magnolia.context.MgnlContext;
22
23 import java.awt.Graphics2D JavaDoc;
24 import java.awt.Image JavaDoc;
25 import java.awt.image.BufferedImage JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileNotFoundException JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31
32 import javax.imageio.ImageIO JavaDoc;
33 import javax.jcr.AccessDeniedException;
34 import javax.jcr.PathNotFoundException;
35 import javax.jcr.RepositoryException;
36 import javax.servlet.http.HttpServletRequest JavaDoc;
37 import javax.servlet.jsp.JspException JavaDoc;
38 import javax.servlet.jsp.JspWriter JavaDoc;
39 import javax.servlet.jsp.PageContext JavaDoc;
40 import javax.servlet.jsp.tagext.SimpleTagSupport JavaDoc;
41
42 import org.apache.log4j.Logger;
43
44
45 /**
46  * Tag that creates a scaled copy of an image. The maximum width and height of the images can be specified via the
47  * attributes. <br />
48  * <br />
49  * If the scaled image with the specified name does not exist in the repository, then this tag will create it and save
50  * it. If the scaled image already exists, then it will not be recreated. <br />
51  * <br />
52  * The name of the node that contains the original image is set by the attribute 'parentContentNode', and the name of
53  * the nodeData for the image is set by the attribute 'parentNodeDataName'. If 'parentContentNode' is null, the local
54  * content node is used. <br />
55  * <br />
56  * The name of the content node that contains the new scaled image is set by the attribute 'imageContentNodeName'. This
57  * node is created under the original image node. This ensures that, if the original images is deleted, so are all the
58  * scaled versions. <br />
59  * <br />
60  * This tag writes out the handle of the content node that contains the image. <br />
61  * <br />
62  * @author Patrick Janssen
63  * @author Fabrizio Giustina
64  * @version 1.0
65  */

66 public class ScaleImageTag extends SimpleTagSupport JavaDoc {
67
68     /**
69      * Location for folder for temporary image creation.
70      */

71     private static final String JavaDoc TEMP_IMAGE_NAME = "tmp-img";
72
73     /**
74      * Name of properties node that describes an image. This gets combined with to the name of the image.
75      */

76     private static final String JavaDoc PROPERTIES_NODE_NAME = "_properties";
77
78     /**
79      * The name of the fileName nodeData in the properties node.
80      */

81     private static final String JavaDoc PROPERTIES_FILENAME = "fileName";
82
83     /**
84      * The name of the size nodeData in the properties node.
85      */

86     private static final String JavaDoc PROPERTIES_SIZE = "size";
87
88     /**
89      * The name of the extension nodeData in the properties node.
90      */

91     private static final String JavaDoc PROPERTIES_EXTENSION = "extension";
92
93     /**
94      * The value of the extension nodeData in the properties node.
95      */

96     private static final String JavaDoc PROPERTIES_EXTENSION_VALUE = "PNG";
97
98     /**
99      * The name of the contentType nodeData in the properties node.
100      */

101     private static final String JavaDoc PROPERTIES_CONTENTTYPE = "contentType";
102
103     /**
104      * The valye of the contentType nodeData in the properties node.
105      */

106     private static final String JavaDoc PROPERTIES_CONTENTTYPE_VALUE = "image/png";
107
108     /**
109      * Attribute: Image maximum height
110      */

111     private int maxHeight = 0;
112
113     /**
114      * Attribute: Image maximum width
115      */

116     private int maxWidth = 0;
117
118     /**
119      * Attribute: The name of the new content node to create
120      */

121     private String JavaDoc imageContentNodeName;
122
123     /**
124      * Attribute: The node that contains the original image. If null, the default will be the local content node.
125      */

126     private String JavaDoc parentContentNodeName;
127
128     /**
129      * Attribute: The name of the data node that contains the existing image.
130      */

131     private String JavaDoc parentNodeDataName;
132
133     /**
134      * Logger.
135      */

136     private static Logger log = Logger.getLogger(ScaleImageTag.class);
137
138     /**
139      * Setter for the <code>maxHeight</code> tag attribute.
140      * @param maxHeight
141      */

142     public void setMaxHeight(int maxHeight) {
143         this.maxHeight = maxHeight;
144     }
145
146     /**
147      * Setter for the <code>maxWidth</code> tag attribute.
148      * @param maxWidth
149      */

150     public void setMaxWidth(int maxWidth) {
151         this.maxWidth = maxWidth;
152     }
153
154     /**
155      * Setter for the <code>parentContentNodeName</code> tag attribute.
156      * @param parentContentNodeName
157      */

158     public void setParentContentNodeName(String JavaDoc parentContentNodeName) {
159         this.parentContentNodeName = parentContentNodeName;
160     }
161
162     /**
163      * Setter for the <code>parentNodeDataName</code> tag attribute.
164      * @param parentNodeDataName
165      */

166     public void setParentNodeDataName(String JavaDoc parentNodeDataName) {
167         this.parentNodeDataName = parentNodeDataName;
168     }
169
170     /**
171      * Setter for the <code>imageContentNodeName</code> tag attribute.
172      * @param imageContentNodeName
173      */

174     public void setImageContentNodeName(String JavaDoc imageContentNodeName) {
175         this.imageContentNodeName = imageContentNodeName;
176     }
177
178     /**
179      * Do thia tag
180      */

181     public void doTag() throws JspException JavaDoc {
182         // initialize everything
183
HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc) ((PageContext JavaDoc) this.getJspContext()).getRequest();
184         Content parentContentNode;
185         Content imageContentNode;
186         JspWriter JavaDoc out = this.getJspContext().getOut();
187
188         try {
189
190             // set the parent node that contains the original image
191
if ((this.parentContentNodeName == null) || (this.parentContentNodeName.equals(""))) {
192                 parentContentNode = Resource.getLocalContentNode(req);
193             }
194             else {
195                 HierarchyManager hm = MgnlContext.getHierarchyManager(ContentRepository.WEBSITE);
196                 // if this name starts with a '/', then assume it is a node handle
197
// otherwise assume that its is a path relative to the local content node
198
if (this.parentContentNodeName.startsWith("/")) {
199                     parentContentNode = hm.getContent(this.parentContentNodeName);
200                 }
201                 else {
202                     String JavaDoc handle = Resource.getLocalContentNode(req).getHandle();
203                     parentContentNode = hm.getContent(handle + "/" + this.parentContentNodeName);
204                 }
205             }
206
207             // check if the new image node exists, if not then create it
208
if (parentContentNode.hasContent(this.imageContentNodeName)) {
209                 imageContentNode = parentContentNode.getContent(this.imageContentNodeName);
210             }
211             else {
212                 // create the node
213
imageContentNode = parentContentNode.createContent(this.imageContentNodeName, ItemType.CONTENTNODE);
214                 parentContentNode.save();
215             }
216             // if the node does not have the image data, then create the data
217
if (!imageContentNode.hasNodeData(this.parentNodeDataName)) {
218                 this.createImageNodeData(parentContentNode, imageContentNode);
219             }
220             // write out the handle for the new image and exit
221
out.write(imageContentNode.getHandle());
222
223         }
224         catch (PathNotFoundException e) {
225             log.error("PathNotFoundException occured in ScaleImage tag: " + e.getMessage(), e);
226         }
227         catch (AccessDeniedException e) {
228             log.error("AccessDeniedException occured in ScaleImage tag: " + e.getMessage(), e);
229         }
230         catch (RepositoryException e) {
231             log.error("RepositoryException occured in ScaleImage tag: " + e.getMessage(), e);
232         }
233         catch (FileNotFoundException JavaDoc e) {
234             log.error("FileNotFoundException occured in ScaleImage tag: " + e.getMessage(), e);
235         }
236         catch (IOException JavaDoc e) {
237             log.error("IOException occured in ScaleImage tag: " + e.getMessage(), e);
238         }
239         this.cleanUp();
240     }
241
242     /**
243      * Set objects to null
244      */

245     public void cleanUp() {
246         this.parentNodeDataName = null;
247         this.imageContentNodeName = null;
248         this.maxWidth = 0;
249         this.maxHeight = 0;
250     }
251
252     /**
253      * Create an image file that is a scaled version of the original image
254      * @param the original image file
255      * @return the new image file
256      */

257     private void createImageNodeData(Content parentContentNode, Content imageContentNode) throws PathNotFoundException,
258         RepositoryException, IOException JavaDoc {
259         // create the nodeData for the image
260
NodeData newNodeData = imageContentNode.createNodeData(this.parentNodeDataName);
261         // get the original image, as a buffered image
262
InputStream JavaDoc oriImgStr = parentContentNode.getNodeData(this.parentNodeDataName).getStream();
263         BufferedImage JavaDoc oriImgBuff = ImageIO.read(oriImgStr);
264         oriImgStr.close();
265         // create the new image file
266
File JavaDoc newImgFile = this.scaleImage(oriImgBuff);
267         long fileSize = newImgFile.length();
268         InputStream JavaDoc newImgStr = new FileInputStream JavaDoc(newImgFile);
269         newNodeData.setValue(newImgStr);
270         newImgStr.close();
271         newImgFile.delete();
272         // create the properties node for the image
273
Content newPropsNode = imageContentNode.createContent(
274             this.parentNodeDataName + PROPERTIES_NODE_NAME,
275             ItemType.CONTENTNODE);
276         NodeData size = newPropsNode.createNodeData(PROPERTIES_SIZE);
277         size.setValue(fileSize);
278         NodeData extension = newPropsNode.createNodeData(PROPERTIES_EXTENSION);
279         extension.setValue(PROPERTIES_EXTENSION_VALUE);
280         NodeData contentType = newPropsNode.createNodeData(PROPERTIES_CONTENTTYPE);
281         contentType.setValue(PROPERTIES_CONTENTTYPE_VALUE);
282         NodeData fileName = newPropsNode.createNodeData(PROPERTIES_FILENAME);
283         fileName.setValue(this.imageContentNodeName);
284         // save everything
285
imageContentNode.save(); // TO DO : does this save the properties node???
286
newPropsNode.save();
287     }
288
289     /**
290      * Create an image file that is a scaled version of the original image
291      * @param the original image file
292      * @return the new image file
293      */

294     private File JavaDoc scaleImage(BufferedImage JavaDoc oriImgBuff) throws IOException JavaDoc {
295         // get the dimesnions of the original image
296
int oriWidth = oriImgBuff.getWidth();
297         int oriHeight = oriImgBuff.getHeight();
298         // get scale factor for the new image
299
double scaleFactor = this.scaleFactor(oriWidth, oriHeight);
300         // get the width and height of the new image
301
int newWidth = new Double JavaDoc(oriWidth * scaleFactor).intValue();
302         int newHeight = new Double JavaDoc(oriHeight * scaleFactor).intValue();
303         // create the thumbnail as a buffered image
304
Image JavaDoc newImg = oriImgBuff.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
305         BufferedImage JavaDoc newImgBuff = new BufferedImage JavaDoc(
306             newImg.getWidth(null),
307             newImg.getHeight(null),
308             BufferedImage.TYPE_INT_RGB);
309         Graphics2D JavaDoc g = newImgBuff.createGraphics();
310         g.drawImage(newImg, 0, 0, null);
311         g.dispose();
312         // create the new image file in the temporary dir
313
File JavaDoc newImgFile = File.createTempFile(TEMP_IMAGE_NAME, PROPERTIES_EXTENSION_VALUE);
314
315         ImageIO.write(newImgBuff, PROPERTIES_EXTENSION_VALUE, newImgFile);
316         // return the file
317
return newImgFile;
318     }
319
320     /**
321      * Calculate the scale factor for the image
322      * @param the image width
323      * @param the image height
324      * @return the scale factor
325      */

326     private double scaleFactor(int width, int height) {
327         double scaleFactor;
328         if (this.maxWidth <= 0 && this.maxHeight <= 0) {
329             // may a copy at the same size
330
scaleFactor = 1;
331         }
332         else if (this.maxWidth <= 0) {
333             // use height
334
scaleFactor = this.maxHeight / height;
335         }
336         else if (this.maxHeight <= 0) {
337             // use width
338
scaleFactor = (double) this.maxWidth / (double) width;
339         }
340         else {
341             // create two scale factors, and see which is smaller
342
double scaleFactorWidth = (double) this.maxWidth / (double) width;
343             double scaleFactorHeight = (double) this.maxHeight / (double) height;
344             scaleFactor = Math.min(scaleFactorWidth, scaleFactorHeight);
345         }
346         return scaleFactor;
347     }
348 }
349
Popular Tags