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