1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.taglibs.util;
35
36 import info.magnolia.cms.beans.config.ContentRepository;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.HierarchyManager;
39 import info.magnolia.cms.core.ItemType;
40 import info.magnolia.cms.util.NodeDataUtil;
41 import info.magnolia.cms.taglibs.Resource;
42 import info.magnolia.context.MgnlContext;
43
44 import java.awt.Graphics2D;
45 import java.awt.Image;
46 import java.awt.image.BufferedImage;
47 import java.io.File;
48 import java.io.FileNotFoundException;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.util.Calendar;
52
53 import javax.imageio.ImageIO;
54 import javax.jcr.AccessDeniedException;
55 import javax.jcr.PathNotFoundException;
56 import javax.jcr.RepositoryException;
57 import javax.servlet.jsp.JspException;
58 import javax.servlet.jsp.JspWriter;
59
60 import org.slf4j.LoggerFactory;
61 import org.slf4j.Logger;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class ScaleImageTag extends BaseImageTag {
89 private static final Logger log = LoggerFactory.getLogger(ScaleImageTag.class);
90
91
92
93
94 private static final String TEMP_IMAGE_NAME = "tmp-img";
95
96
97
98
99 private static final String PROPERTIES_EXTENSION_VALUE = "PNG";
100
101
102
103
104 private int maxHeight = 0;
105
106
107
108
109 private int maxWidth = 0;
110
111
112
113
114
115
116 private boolean allowOversize = true;
117
118
119
120
121 private String imageContentNodeName;
122
123
124
125
126 private String parentNodeDataName;
127
128
129
130
131
132 public void setMaxHeight(int maxHeight) {
133 this.maxHeight = maxHeight;
134 }
135
136
137
138
139
140 public void setMaxWidth(int maxWidth) {
141 this.maxWidth = maxWidth;
142 }
143
144
145
146
147
148 public void setAllowOversize(boolean allowOversize) {
149 this.allowOversize = allowOversize;
150 }
151
152
153
154
155
156 public void setParentContentNodeName(String parentContentNodeName) {
157 this.parentContentNodeName = parentContentNodeName;
158 }
159
160
161
162
163
164 public void setParentNodeDataName(String parentNodeDataName) {
165 this.parentNodeDataName = parentNodeDataName;
166 }
167
168
169
170
171
172 public void setImageContentNodeName(String imageContentNodeName) {
173 this.imageContentNodeName = imageContentNodeName;
174 }
175
176
177
178
179 public void doTag() throws JspException {
180
181 Content parentContentNode;
182 Content imageContentNode;
183 JspWriter out = this.getJspContext().getOut();
184
185 try {
186
187
188 if ((this.parentContentNodeName == null) || (this.parentContentNodeName.equals(""))) {
189 parentContentNode = Resource.getLocalContentNode();
190 }
191 else {
192 HierarchyManager hm = MgnlContext.getHierarchyManager(ContentRepository.WEBSITE);
193
194
195 if (this.parentContentNodeName.startsWith("/")) {
196 parentContentNode = hm.getContent(this.parentContentNodeName);
197 }
198 else {
199 String handle = Resource.getLocalContentNode().getHandle();
200 parentContentNode = hm.getContent(handle + "/" + this.parentContentNodeName);
201 }
202 }
203
204
205 if (parentContentNode.hasContent(this.imageContentNodeName)) {
206 imageContentNode = parentContentNode.getContent(this.imageContentNodeName);
207 }
208 else {
209
210 imageContentNode = parentContentNode.createContent(this.imageContentNodeName, ItemType.CONTENTNODE);
211 parentContentNode.save();
212 }
213
214
215 if (!imageContentNode.hasNodeData(this.parentNodeDataName) || rescale(parentContentNode, imageContentNode)) {
216 this.createImageNodeData(parentContentNode, imageContentNode);
217 }
218
219 StringBuffer handle = new StringBuffer(imageContentNode.getHandle());
220 handle.append("/");
221 handle.append(getFilename());
222 out.write(handle.toString());
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 e) {
234 log.error("FileNotFoundException occured in ScaleImage tag: " + e.getMessage(), e);
235 }
236 catch (IOException e) {
237 log.error("IOException occured in ScaleImage tag: " + e.getMessage(), e);
238 }
239 this.cleanUp();
240 }
241
242
243
244
245
246
247
248
249 protected boolean rescale(Content parentContentNode, Content imageContentNode) {
250 Calendar parentModified = parentContentNode.getMetaData().getModificationDate() != null ? parentContentNode
251 .getMetaData()
252 .getModificationDate() : parentContentNode.getMetaData().getCreationDate();
253
254 Calendar imageModified = imageContentNode.getMetaData().getModificationDate() != null ? imageContentNode
255 .getMetaData()
256 .getModificationDate() : imageContentNode.getMetaData().getCreationDate();
257
258 if (parentModified.after(imageModified)) {
259 return true;
260 }
261 else {
262 int originalHeight = (int) imageContentNode.getNodeData("maxHeight").getLong();
263 int originalWidth = (int) imageContentNode.getNodeData("maxWidth").getLong();
264
265 return originalHeight != maxHeight || originalWidth != maxWidth;
266 }
267 }
268
269
270
271
272 public void cleanUp() {
273 this.parentNodeDataName = null;
274 this.imageContentNodeName = null;
275 this.maxWidth = 0;
276 this.maxHeight = 0;
277 }
278
279
280
281
282
283 private void createImageNodeData(Content parentContentNode, Content imageContentNode) throws PathNotFoundException,
284 RepositoryException, IOException {
285
286
287 InputStream oriImgStr = parentContentNode.getNodeData(this.parentNodeDataName).getStream();
288 BufferedImage oriImgBuff = ImageIO.read(oriImgStr);
289 oriImgStr.close();
290
291 File newImgFile = this.scaleImage(oriImgBuff);
292
293 NodeDataUtil.getOrCreate(imageContentNode, "maxHeight").setValue(maxHeight);
294 NodeDataUtil.getOrCreate(imageContentNode, "maxWidth").setValue(maxWidth);
295
296 createImageNode(newImgFile, imageContentNode);
297
298 newImgFile.delete();
299 }
300
301
302
303
304
305
306 private File scaleImage(BufferedImage oriImgBuff) throws IOException {
307
308 int oriWidth = oriImgBuff.getWidth();
309 int oriHeight = oriImgBuff.getHeight();
310
311 double scaleFactor = this.scaleFactor(oriWidth, oriHeight);
312
313 int newWidth = new Double(oriWidth * scaleFactor).intValue();
314 int newHeight = new Double(oriHeight * scaleFactor).intValue();
315
316 Image newImg = oriImgBuff.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
317 BufferedImage newImgBuff = new BufferedImage(
318 newImg.getWidth(null),
319 newImg.getHeight(null),
320 BufferedImage.TYPE_INT_RGB);
321 Graphics2D g = newImgBuff.createGraphics();
322 g.drawImage(newImg, 0, 0, null);
323 g.dispose();
324
325 File newImgFile = File.createTempFile(TEMP_IMAGE_NAME, PROPERTIES_EXTENSION_VALUE);
326
327 ImageIO.write(newImgBuff, PROPERTIES_EXTENSION_VALUE, newImgFile);
328
329 return newImgFile;
330 }
331
332
333
334
335
336
337
338 private double scaleFactor(int originalWidth, int originalHeight) {
339 double scaleFactor;
340
341 int scaleWidth = this.maxWidth;
342 int scaleHeight = this.maxHeight;
343
344 if (!this.allowOversize) {
345 scaleWidth = Math.min(this.maxWidth, originalWidth);
346 scaleHeight = Math.min(this.maxHeight, originalHeight);
347 }
348
349 if (scaleWidth <= 0 && scaleHeight <= 0) {
350
351 scaleFactor = 1;
352 }
353 else if (scaleWidth <= 0) {
354
355 scaleFactor = (double) scaleHeight / (double) originalHeight;
356 }
357 else if (scaleHeight <= 0) {
358
359 scaleFactor = (double) scaleWidth / (double) originalWidth;
360 }
361 else {
362
363 double scaleFactorWidth = (double) scaleWidth / (double) originalWidth;
364 double scaleFactorHeight = (double) scaleHeight / (double) originalHeight;
365 scaleFactor = Math.min(scaleFactorWidth, scaleFactorHeight);
366 }
367 return scaleFactor;
368 }
369
370 protected String getFilename() {
371 return this.parentNodeDataName;
372 }
373 }