KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > images > JAIImageConverter


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.util.images;
11
12 import java.awt.image.renderable.ParameterBlock JavaDoc;
13 import javax.media.jai.*;
14 import javax.media.jai.operator.*;
15 import java.awt.image.IndexColorModel JavaDoc;
16 import java.awt.Transparency JavaDoc;
17 import java.util.*;
18 import java.util.regex.*;
19 import java.io.*;
20 import com.sun.media.jai.codec.*;
21
22 import org.mmbase.util.logging.*;
23
24 /**
25  * Converts Images using image Java Advanced Imaging
26  *
27  * @author Daniel Ockeloen
28  * @author Martijn Houtman (JAI fix)
29  * @version $Id: JAIImageConverter.java,v 1.4 2006/08/23 15:18:56 michiel Exp $
30  */

31 public class JAIImageConverter implements ImageConverter {
32
33     private static final Logger log = Logging.getLoggerInstance(JAIImageConverter.class);
34
35     /**
36      * @javadoc
37      */

38     public void init(Map params) {
39         log.info("Starting JAI convertor");
40     }
41
42
43     /**
44      * @javadoc
45      */

46     public byte[] convertImage(byte[] input, String JavaDoc sourceFormat, List commands) {
47         String JavaDoc format;
48         byte[] pict=null;
49         try {
50             ByteArraySeekableStream bin = new ByteArraySeekableStream(input);
51             PlanarImage img = JAI.create("stream", bin);
52
53             // determine outputformat
54
format = getConvertFormat(commands);
55             if (format.equals("asis")) format = sourceFormat;
56
57             // correct for gif transparency
58
if (! (format.equals("gif") || format.equals("png")) &&
59                 img.getColorModel()instanceof IndexColorModel JavaDoc) {
60               IndexColorModel JavaDoc icm = (IndexColorModel JavaDoc) img.getColorModel();
61               if (icm.getTransparency() == Transparency.BITMASK) {
62                 byte[][] data = new byte[3][icm.getMapSize()];
63                 icm.getReds(data[0]);
64                 icm.getGreens(data[1]);
65                 icm.getBlues(data[2]);
66                 LookupTableJAI lut = new LookupTableJAI(data);
67                 img = JAI.create("lookup", img, lut);
68                 log.debug("palette-color image converted to RGB");
69               }
70             }
71
72             img = doConvertCommands(img, commands);
73
74             ByteArrayOutputStream bout = new ByteArrayOutputStream();
75
76             JAI.create("encode", img, bout, format, null);
77             pict = bout.toByteArray();
78         } catch(Exception JavaDoc e) {
79             log.error(Logging.stackTrace(e));
80         }
81         return pict;
82     }
83
84     /**
85      * Obtains the image format from the parameters list.
86      * Note that JAI is not likely to produce outputs
87      * for GIF (due to the license).
88      * @param params the list of conversion paarmeters
89      * @return the specified format, or the default image format is unspecified
90      */

91     private String JavaDoc getConvertFormat(List params) {
92         String JavaDoc format = null;
93
94         for (Iterator t = params.iterator(); t.hasNext();) {
95             String JavaDoc key=(String JavaDoc)t.next();
96             int pos = key.indexOf('(');
97             int pos2 = key.lastIndexOf(')');
98             if (pos!=-1 && pos2!=-1) {
99                 String JavaDoc type = key.substring(0, pos);
100                 String JavaDoc cmd = key.substring(pos + 1, pos2);
101                 if (type.equals("f")) {
102                     if (! (cmd.equals("asis") && format != null)) {
103                         format = cmd.toLowerCase();
104                     }
105                     break;
106                 }
107             }
108         }
109         if (format == null) format = Factory.getDefaultImageFormat();
110         // fix jpg format name
111
if (format.equals("jpg")) format="jpeg";
112         return format;
113     }
114     /**
115      * @javadoc
116      */

117     private PlanarImage doConvertCommands(PlanarImage img, List params) {
118         Iterator t = params.iterator();
119         while (t.hasNext()) {
120             try {
121                 String JavaDoc key=(String JavaDoc)t.next();
122                 int pos = key.indexOf('(');
123                 int pos2 = key.lastIndexOf(')');
124                 if (pos!=-1 && pos2 != -1) {
125                     String JavaDoc type = key.substring(0, pos);
126                     String JavaDoc cmd = key.substring(pos + 1, pos2);
127                     String JavaDoc[] tokens = cmd.split("[x,\\n\\r]");
128                     if (log.isDebugEnabled()) {
129                         log.debug("getCommands(): type=" + type + " cmd=" + cmd);
130                         log.debug("Image is now " + img.getWidth() + "x" + img.getHeight());
131                         log.debug(" or " + img.getMinX() + "-" + img.getMaxX() + ".." + img.getMinY() + "-" + img.getMaxY());
132                     }
133                     // Following code translates some MMBase specific things
134
// to imagemagick's convert arguments.
135
// using this conversion ensures compatibility between systems
136
type = Imaging.getAlias(type);
137                     if (type.equals("geometry")) {
138                         String JavaDoc xString = tokens.length > 0 ? tokens[0] : "";
139                         String JavaDoc yString = tokens.length > 1 ? tokens[1] : "";
140                         
141                         Matcher matchX = Imaging.GEOMETRY.matcher(xString);
142                         xString = matchX.matches() ? matchX.group(1) : "";
143                         Matcher matchY = Imaging.GEOMETRY.matcher(yString);
144                         yString = matchY.matches() ? matchY.group(1) : "";
145                         
146                         String JavaDoc options = (matchX.matches() ? matchX.group(2) : "") + (matchY.matches() ? matchY.group(2) : "");
147                         
148                         boolean aspectRatio = true;
149                         boolean area = false;
150                         boolean percentage = false;
151                         
152                         for (int j = 0 ; j < options.length(); j++) {
153                             char o = options.charAt(j);
154                             if (o == '%') percentage = true;
155                             if (o == '@') area = true;
156                             if (o == '!') aspectRatio = false;
157                         }
158                         
159                         int x = "".equals(xString) ? 0 : Integer.parseInt(xString);
160                         int y = "".equals(yString) ? 0 : Integer.parseInt(yString);
161                         
162                         if (x == 0) {
163                             x = Math.round((float) img.getWidth() * y / img.getHeight());
164                         }
165                         if (area) {
166                             float a = x;
167                             if (img.getWidth() * img.getHeight() > a) {
168                                 float ratio = (float) img.getWidth() / img.getHeight();;
169                                 x = (int) Math.floor(Math.sqrt(a * ratio));
170                                 y = (int) Math.floor(Math.sqrt(a / ratio));
171                             } else {
172                                 x = img.getWidth();
173                                 y = img.getHeight();
174                             }
175                         }
176
177                         if (y == 0) {
178                             y = Math.round((float) img.getHeight() * x / img.getWidth());
179                         }
180                         
181                         if (percentage) {
182                             x = img.getWidth() * x / 100;
183                             y = img.getHeight() * y / 100;
184                             aspectRatio = false;
185                         }
186                         img = size(img, x, y, aspectRatio);
187                     } else if (type.equals("border")) {
188                         int x = Integer.parseInt(tokens[0]);
189                         int y = tokens.length > 1 ? Integer.parseInt(tokens[1]) : x;
190                         img = border(img, x ,y);
191                     } else if (type.equals("rotate")) {
192                         int a = Integer.parseInt(tokens[0]);
193                         img = rotate(img, 0, 0,a);
194                     } else if (type.equals("part")) {
195                         int x1 = Integer.parseInt(tokens[0]);
196                         int y1 = Integer.parseInt(tokens[1]);
197                         int x2 = Integer.parseInt(tokens[2]);
198                         int y2 = Integer.parseInt(tokens[3]);
199                         if (x2 > img.getWidth()) x2 = img.getWidth();
200                         if (y2 > img.getHeight()) y2 = img.getHeight();
201                         if (x1 > x2) x1 = x2 - 1;
202                         if (y1 > y2) y1 = y2 - 1;
203                         img = crop(img, x1, y1, x2, y2);
204                     }
205                 } else {
206                     if (key.equals("negate")) {
207                         img = negate(img);
208                     } else if (key.equals("border")) {
209                         img = border(img, 1, 1);
210                     } else if (key.equals("flop")) {
211                         img = flop(img);
212                     } else if (key.equals("flip")) {
213                         img = flip(img);
214                     }
215                 }
216             } catch(Exception JavaDoc e) {
217                 log.error(e.getMessage(), e);
218             }
219         }
220         return img;
221     }
222
223     /**
224      * @javadoc
225      */

226     protected static PlanarImage crop(PlanarImage inImg,int x1,int y1, int x2,int y2) {
227         Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
228         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
229         params.addSource(inImg);
230         params.add((float)x1); // x
231
params.add((float)y1); // y
232
params.add((float)(x2 - x1)); // width
233
params.add((float)(y2 - y1)); // height
234
params.add(interp); // interpolation method
235
PlanarImage outImg = JAI.create("crop", params);
236         return outImg;
237     }
238
239     /**
240      * Performs the 's' or 'geometry' operation:
241      * Resize an image using specified width and height.
242      * @param inImg the image to transform
243      * @param width new width of the image
244      * @param height new height of the image
245      * @param maintainAspectRation if true, width and height are maximums: aspect ratio is maintained
246      * @return the transformed image
247      */

248     protected static PlanarImage size(PlanarImage inImg,int width,int height, boolean maintainAspectRation) {
249         Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
250         int curwidth=inImg.getWidth();
251         int curheight=inImg.getHeight();
252         float sx=((float)width/curwidth);
253         float sy=((float)height/curheight);
254         if (maintainAspectRation) {
255             // use the smallest scale if aspect ratio is to be maintained
256
if (sy<sx) {
257                 sx=sy;
258             } else {
259                 sy=sx;
260             }
261         }
262         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
263         params.addSource(inImg);
264         params.add(sx); // x scale
265
params.add(sy); // y scale
266
params.add(0F); // x trans
267
params.add(0F); // y trans
268
params.add(interp); // interpolation method
269
PlanarImage outImg = JAI.create("scale", params);
270         return outImg;
271     }
272
273     /**
274      * Performs the 'dia' or 'negate' operation.
275      * Replace every pixel with its complementary color (white becomes black, yellow becomes blue, etc.)
276      * @param inImg the image to transform
277      * @return the transformed image
278      */

279     protected static PlanarImage negate(PlanarImage inImg) {
280         Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
281         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
282         params.addSource(inImg);
283         params.add(interp); // interpolation method
284
PlanarImage outImg = JAI.create("invert", params);
285         return outImg;
286     }
287
288     /**
289      * Performs the 'rotate' operation: rotates an image.
290      * @param inImg the image to transform
291      * @param x xposition of the rotation
292      * @param y yposition of the rotation
293      * @param a angle of the rotation
294      * @return the transformed image
295      */

296     protected static PlanarImage rotate(PlanarImage inImg,int x,int y,int a) {
297         Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
298         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
299         params.addSource(inImg);
300         params.add((float)x); // x org
301
params.add((float)y); // y org
302
params.add((float)Math.toRadians((double)(a))); // angle
303
params.add(interp); // interpolation method
304
PlanarImage outImg = JAI.create("rotate", params);
305         return outImg;
306     }
307
308     /**
309      * Performs the 'border' operation:
310      * Adds a border to an image using the specified horizontal and vertical padding.
311      * @param inImg the image to transform
312      * @param xpadding the horizontal padding
313      * @param ypadding the vertical padding
314      * @return the transformed image
315      */

316     protected static PlanarImage border(PlanarImage inImg, int xpadding,int ypadding) {
317         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
318         params.addSource(inImg);
319         params.add(xpadding); // leftPad
320
params.add(xpadding); // rightPad
321
params.add(ypadding); // topPad
322
params.add(ypadding); // bottomPad
323
params.add(BorderExtender.BORDER_ZERO); // type
324
params.add(null); // constants (ignored)
325

326         PlanarImage outImg = JAI.create("border", params);
327         return outImg;
328     }
329
330     /**
331      * Performs the 'flop' or 'flipx' operation:
332      * Flip an image across an imaginary horizontal line that runs through the center of the image.
333      * @param inImg the image to transform
334      * @return the transformed image
335      */

336     protected static PlanarImage flop(PlanarImage inImg) {
337         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
338         params.addSource(inImg);
339         params.add(TransposeDescriptor.FLIP_HORIZONTAL); // flip over X
340
PlanarImage outImg = JAI.create("transpose", params);
341         return outImg;
342     }
343
344     /**
345      * Performs the 'flip' or 'flipy' operation:
346      * Flip an image across an imaginary vertical line that runs through the center of the image.
347      * @param inImg the image to transform
348      * @return the transformed image
349      */

350     protected static PlanarImage flip(PlanarImage inImg) {
351         ParameterBlock JavaDoc params = new ParameterBlock JavaDoc();
352         params.addSource(inImg);
353         params.add(TransposeDescriptor.FLIP_VERTICAL); // flip over Y
354
PlanarImage outImg = JAI.create("transpose", params);
355         return outImg;
356     }
357
358     /**
359      * @javadoc
360      */

361     protected static PlanarImage loadImage(String JavaDoc filename) {
362         ParameterBlock JavaDoc pb = new ParameterBlock JavaDoc();
363         pb.add(filename);
364         PlanarImage image = JAI.create("fileload",pb);
365         if (image==null) {
366             log.warn("Can't load image");
367         }
368         return image;
369     }
370
371
372 }
373
Popular Tags