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.ContentUtil;
40 import info.magnolia.cms.util.HierarchyManagerUtil;
41 import info.magnolia.cms.util.NodeDataUtil;
42 import info.magnolia.context.MgnlContext;
43 import info.magnolia.jcr.util.NodeTypes;
44 import info.magnolia.repository.RepositoryConstants;
45
46 import java.awt.Graphics2D;
47 import java.awt.Image;
48 import java.awt.image.BufferedImage;
49 import java.io.File;
50 import java.io.FileNotFoundException;
51 import java.io.IOException;
52 import java.io.InputStream;
53 import java.util.Calendar;
54
55 import javax.imageio.ImageIO;
56 import javax.jcr.AccessDeniedException;
57 import javax.jcr.PathNotFoundException;
58 import javax.jcr.RepositoryException;
59 import javax.servlet.jsp.JspException;
60 import javax.servlet.jsp.JspWriter;
61
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64 import org.tldgen.annotations.BodyContent;
65 import org.tldgen.annotations.Tag;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @Tag(name = "scaleImage", bodyContent = BodyContent.EMPTY)
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
133 public void setMaxHeight(int maxHeight) {
134 this.maxHeight = maxHeight;
135 }
136
137
138
139
140
141
142 public void setMaxWidth(int maxWidth) {
143 this.maxWidth = maxWidth;
144 }
145
146
147
148
149
150
151 public void setAllowOversize(boolean allowOversize) {
152 this.allowOversize = allowOversize;
153 }
154
155
156
157
158
159
160 @Override
161 public void setParentContentNodeName(String parentContentNodeName) {
162 this.parentContentNodeName = parentContentNodeName;
163 }
164
165
166
167
168
169
170 public void setParentNodeDataName(String parentNodeDataName) {
171 this.parentNodeDataName = parentNodeDataName;
172 }
173
174
175
176
177
178
179 @Override
180 public void setImageContentNodeName(String imageContentNodeName) {
181 this.imageContentNodeName = imageContentNodeName;
182 }
183
184 @Override
185 public void doTag() throws JspException {
186
187 Content parentContentNode;
188 Content imageContentNode;
189 JspWriter out = this.getJspContext().getOut();
190
191 try {
192
193
194 if ((this.parentContentNodeName == null) || (this.parentContentNodeName.equals(""))) {
195 parentContentNode = ContentUtil.asContent(MgnlContext.getAggregationState().getCurrentContentNode());
196 } else {
197 HierarchyManager hm = HierarchyManagerUtil.asHierarchyManager(MgnlContext.getJCRSession(RepositoryConstants.WEBSITE));
198
199
200 if (this.parentContentNodeName.startsWith("/")) {
201 parentContentNode = hm.getContent(this.parentContentNodeName);
202 } else {
203 String handle = MgnlContext.getAggregationState().getCurrentContentNode().getPath();
204 parentContentNode = hm.getContent(handle + "/" + this.parentContentNodeName);
205 }
206 }
207
208
209 if (parentContentNode.hasContent(this.imageContentNodeName)) {
210 imageContentNode = parentContentNode.getContent(this.imageContentNodeName);
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 } catch (PathNotFoundException e) {
227 log.error("PathNotFoundException occured in ScaleImage tag: {}", e.getMessage(), e);
228 } catch (AccessDeniedException e) {
229 log.error("AccessDeniedException occured in ScaleImage tag: {}", e.getMessage(), e);
230 } catch (RepositoryException e) {
231 log.error("RepositoryException occured in ScaleImage tag: {}", e.getMessage(), e);
232 } catch (FileNotFoundException e) {
233 log.error("FileNotFoundException occured in ScaleImage tag: {}", e.getMessage(), e);
234 } catch (IOException e) {
235 log.error("IOException occured in ScaleImage tag: {}", e.getMessage(), e);
236 }
237 this.cleanUp();
238 }
239
240
241
242
243
244
245
246 @Deprecated
247 protected boolean rescale(Content parentContentNode, Content imageContentNode) {
248
249 try {
250 Calendar parentModified = NodeTypes.LastModified.getLastModified(parentContentNode.getJCRNode());
251 Calendar imageModified = NodeTypes.LastModified.getLastModified(imageContentNode.getJCRNode());
252
253 if (parentModified.after(imageModified)) {
254 return true;
255 }
256 } catch (RepositoryException e) {
257
258 return true;
259 }
260
261 int originalHeight = (int) imageContentNode.getNodeData("maxHeight").getLong();
262 int originalWidth = (int) imageContentNode.getNodeData("maxWidth").getLong();
263
264 return originalHeight != maxHeight || originalWidth != maxWidth;
265 }
266
267
268
269
270 public void cleanUp() {
271 this.parentNodeDataName = null;
272 this.imageContentNodeName = null;
273 this.maxWidth = 0;
274 this.maxHeight = 0;
275 }
276
277
278
279
280 private void createImageNodeData(Content parentContentNode, Content imageContentNode) throws PathNotFoundException,
281 RepositoryException, IOException {
282
283
284 InputStream oriImgStr = parentContentNode.getNodeData(this.parentNodeDataName).getStream();
285 BufferedImage oriImgBuff = ImageIO.read(oriImgStr);
286 oriImgStr.close();
287
288 File newImgFile = this.scaleImage(oriImgBuff);
289
290 NodeDataUtil.getOrCreate(imageContentNode, "maxHeight").setValue(maxHeight);
291 NodeDataUtil.getOrCreate(imageContentNode, "maxWidth").setValue(maxWidth);
292
293 createImageNode(newImgFile, imageContentNode);
294
295 newImgFile.delete();
296 }
297
298
299
300
301 private File scaleImage(BufferedImage oriImgBuff) throws IOException {
302
303 int oriWidth = oriImgBuff.getWidth();
304 int oriHeight = oriImgBuff.getHeight();
305
306 double scaleFactor = this.scaleFactor(oriWidth, oriHeight);
307
308 int newWidth = new Double(oriWidth * scaleFactor).intValue();
309 int newHeight = new Double(oriHeight * scaleFactor).intValue();
310
311 Image newImg = oriImgBuff.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
312 BufferedImage newImgBuff = new BufferedImage(
313 newImg.getWidth(null),
314 newImg.getHeight(null),
315 BufferedImage.TYPE_INT_RGB);
316 Graphics2D g = newImgBuff.createGraphics();
317 g.drawImage(newImg, 0, 0, null);
318 g.dispose();
319
320 File newImgFile = File.createTempFile(TEMP_IMAGE_NAME, PROPERTIES_EXTENSION_VALUE);
321
322 ImageIO.write(newImgBuff, PROPERTIES_EXTENSION_VALUE, newImgFile);
323
324 return newImgFile;
325 }
326
327
328
329
330 private double scaleFactor(int originalWidth, int originalHeight) {
331 double scaleFactor;
332
333 int scaleWidth = this.maxWidth;
334 int scaleHeight = this.maxHeight;
335
336 if (!this.allowOversize) {
337 scaleWidth = Math.min(this.maxWidth, originalWidth);
338 scaleHeight = Math.min(this.maxHeight, originalHeight);
339 }
340
341 if (scaleWidth <= 0 && scaleHeight <= 0) {
342
343 scaleFactor = 1;
344 } else if (scaleWidth <= 0) {
345
346 scaleFactor = (double) scaleHeight / (double) originalHeight;
347 } else if (scaleHeight <= 0) {
348
349 scaleFactor = (double) scaleWidth / (double) originalWidth;
350 } else {
351
352 double scaleFactorWidth = (double) scaleWidth / (double) originalWidth;
353 double scaleFactorHeight = (double) scaleHeight / (double) originalHeight;
354 scaleFactor = Math.min(scaleFactorWidth, scaleFactorHeight);
355 }
356 return scaleFactor;
357 }
358
359 @Override
360 protected String getFilename() {
361 return this.parentNodeDataName;
362 }
363 }