1 package org.jmage.filter.merge;
2
3 import org.apache.log4j.Logger;
4 import org.apache.log4j.Priority;
5 import org.jmage.filter.FilterException;
6 import org.jmage.filter.TwinResourceImageFilter;
7
8 import javax.media.jai.JAI;
9 import javax.media.jai.PlanarImage;
10 import java.awt.*;
11 import java.awt.image.BufferedImage;
12 import java.util.HashMap;
13 import java.util.Properties;
14
15 /***
16 * Puts the image on a configured background image. The Resulting image will have the proportions
17 * of the background image. Note that background images must be higher *and* wider than the
18 * image that is supposed to overlay them. Specify the following imageProperties to change
19 * the appearance:<p>
20 * <p/>
21 * IMAGE_URI: the image to put as background.<br>
22 * OPACITY: [0-100] opacity percentage, where 0 is transparent and 100 is opaque.<br>
23 * ORIENTATION: [0-360] where values are in degrees. For convenience, use the constants defined, i.e "ORIENTATION_NORTH" (the default)<br>
24 * POSITION_X: horizontal overlay position on the background<br>
25 * POSITION_Y: vertical overlay position on the background<br>
26 */
27 public class BackgroundImageFilter extends TwinResourceImageFilter {
28
29 public static final String OPACITY = "OPACITY";
30 public static final String DEFAULT_OPACITY = "100";
31
32 public static final String ORIENTATION = "ORIENTATION";
33 public static final String ORIENTATION_NORTH = "0";
34 public static final String ORIENTATION_NORTHEAST = "45";
35 public static final String ORIENTATION_EAST = "90";
36 public static final String ORIENTATION_SOUTHEAST = "135";
37 public static final String ORIENTATION_SOUTH = "180";
38 public static final String ORIENTATION_SOUTHWEST = "225";
39 public static final String ORIENTATION_WEST = "270";
40 public static final String ORIENTATION_NORTHWEST = "315";
41 public static final String DEFAULT_ORIENTATION = ORIENTATION_NORTH;
42
43 public static final String POSITION_X = "POSITION_X";
44 public static final String POSITION_Y = "POSITION_Y";
45 public static final String DEFAULT_POSITION_X = "0";
46 public static final String DEFAULT_POSITION_Y = "0";
47
48 protected BufferedImage backgroundImage;
49 protected Graphics2D backgroundGraphics;
50 protected int px = 0;
51 protected int py = 0;
52 protected RenderingHints renderingHints;
53 protected double orientation;
54 protected float opacity;
55
56 protected static Logger log = Logger.getLogger(BackgroundImageFilter.class.getName());
57 private static final String OPACITY_RANGE_ERROR = "values are only allowed ranging from 0-100, out of range error: ";
58 private static final String ORIENTATION_RANGE_ERROR = "values are only allowed ranging from 0-100, out of range error: ";
59 private static final String IMAGE_ERROR = "unable to create image from URI: ";
60 private static final String POSITION_RANGE_ERROR = "position values x/y are only allowed greater than 0 ";
61
62 /***
63 * Initialize the ImageFilter
64 */
65 public void initialize(Properties filterProperties) throws FilterException {
66 try {
67 super.initialize(filterProperties);
68
69
70 opacity = Float.valueOf(filterProperties.getProperty(OPACITY, DEFAULT_OPACITY)).floatValue();
71 assert (opacity >= 1f && opacity <= 100f) : OPACITY + OPACITY_RANGE_ERROR + opacity;
72 opacity /= 100f;
73
74
75 px = Integer.decode(filterProperties.getProperty(POSITION_X, DEFAULT_POSITION_X)).intValue();
76 py = Integer.decode(filterProperties.getProperty(POSITION_Y, DEFAULT_POSITION_Y)).intValue();
77
78 assert (px >= 0 && py >= 0) : POSITION_RANGE_ERROR + px + "/" + py;
79
80
81 orientation = Double.valueOf(filterProperties.getProperty(ORIENTATION, DEFAULT_ORIENTATION)).doubleValue();
82 assert (orientation >= 0 && orientation <= 360) : ORIENTATION + ORIENTATION_RANGE_ERROR + orientation;
83 orientation /= 180f;
84
85
86 HashMap paramMap = new HashMap();
87 paramMap.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
88 paramMap.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
89 paramMap.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
90 paramMap.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
91 renderingHints = new RenderingHints(paramMap);
92
93 this.filterProperties = filterProperties;
94 if (log.isDebugEnabled()) log.debug(INITIALIZED);
95 } catch (Throwable t) {
96 String message = NOT_INITIALIZED + t.getMessage();
97 this.filterProperties = null;
98 if (log.isEnabledFor(Priority.ERROR)) log.error(message);
99 throw new FilterException(message);
100 }
101 }
102
103 /***
104 * Overlay image with another image
105 *
106 * @throws org.jmage.filter.FilterException
107 * if an error occurs during filtering
108 */
109 public PlanarImage filter(PlanarImage image) throws FilterException {
110 super.filter(image);
111 backgroundImage = resourceImage.getAsBufferedImage();
112 backgroundGraphics = (Graphics2D) backgroundImage.createGraphics();
113 backgroundGraphics.setRenderingHints(renderingHints);
114 backgroundGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
115
116
117 if (image.getHeight() > backgroundImage.getHeight() ||
118 (image.getWidth() > backgroundImage.getWidth())) {
119 throw new FilterException("background image dimensions need to be equal or larger foreground image");
120 }
121 backgroundGraphics.drawImage(image.getAsBufferedImage(), px, py, null);
122 backgroundGraphics.dispose();
123
124
125 return (PlanarImage) JAI.create("AWTImage", (Image) backgroundImage);
126 }
127 }