View Javadoc

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              //opacity
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              //position
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              //orientation
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              //rendering hints
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         // draw image on background
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         // Convert back and return
125         return (PlanarImage) JAI.create("AWTImage", (Image) backgroundImage);
126     }
127 }