Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / gnu / java / awt / peer / gtk / GdkPixbufDecoder.java
blob85cb1e47a9e9e7083e205784b39716d054f36923
1 /* GdkPixbufDecoder.java -- Image data decoding object
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.awt.peer.gtk;
41 import gnu.classpath.Configuration;
43 import java.awt.image.BufferedImage;
44 import java.awt.image.ColorModel;
45 import java.awt.image.DirectColorModel;
46 import java.awt.image.ImageConsumer;
47 import java.awt.image.ImageProducer;
48 import java.awt.image.Raster;
49 import java.awt.image.RenderedImage;
50 import java.io.DataOutput;
51 import java.io.IOException;
52 import java.io.InputStream;
53 import java.net.URL;
54 import java.util.ArrayList;
55 import java.util.Hashtable;
56 import java.util.Iterator;
57 import java.util.Locale;
58 import java.util.Vector;
60 import javax.imageio.IIOImage;
61 import javax.imageio.ImageReadParam;
62 import javax.imageio.ImageReader;
63 import javax.imageio.ImageTypeSpecifier;
64 import javax.imageio.ImageWriteParam;
65 import javax.imageio.ImageWriter;
66 import javax.imageio.metadata.IIOMetadata;
67 import javax.imageio.spi.IIORegistry;
68 import javax.imageio.spi.ImageReaderSpi;
69 import javax.imageio.spi.ImageWriterSpi;
70 import javax.imageio.stream.ImageInputStream;
71 import javax.imageio.stream.ImageOutputStream;
73 public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
75 static
77 if (Configuration.INIT_LOAD_LIBRARY)
79 System.loadLibrary("gtkpeer");
81 initStaticState ();
84 static native void initStaticState();
85 private final int native_state = GtkGenericPeer.getUniqueInteger ();
87 // initState() has been called, but pumpDone() has not yet been called.
88 private boolean needsClose = false;
90 // the current set of ImageConsumers for this decoder
91 Vector curr;
93 // interface to GdkPixbuf
94 native void initState ();
95 native void pumpBytes (byte[] bytes, int len) throws IOException;
96 native void pumpDone () throws IOException;
97 native void finish (boolean needsClose);
98 static native void streamImage(int[] bytes, String format, int width, int height, boolean hasAlpha, DataOutput sink);
100 // gdk-pixbuf provids data in RGBA format
101 static final ColorModel cm = new DirectColorModel (32, 0xff000000,
102 0x00ff0000,
103 0x0000ff00,
104 0x000000ff);
105 public GdkPixbufDecoder (InputStream in)
107 super (in);
110 public GdkPixbufDecoder (String filename)
112 super (filename);
115 public GdkPixbufDecoder (URL url)
117 super (url);
120 public GdkPixbufDecoder (byte[] imagedata, int imageoffset, int imagelength)
122 super (imagedata, imageoffset, imagelength);
125 // called back by native side: area_prepared_cb
126 void areaPrepared (int width, int height)
129 if (curr == null)
130 return;
132 for (int i = 0; i < curr.size (); i++)
134 ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
135 ic.setDimensions (width, height);
136 ic.setColorModel (cm);
137 ic.setHints (ImageConsumer.RANDOMPIXELORDER);
141 // called back by native side: area_updated_cb
142 void areaUpdated (int x, int y, int width, int height,
143 int pixels[], int scansize)
145 if (curr == null)
146 return;
148 for (int i = 0; i < curr.size (); i++)
150 ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
151 ic.setPixels (x, y, width, height, cm, pixels, 0, scansize);
155 // called from an async image loader of one sort or another, this method
156 // repeatedly reads bytes from the input stream and passes them through a
157 // GdkPixbufLoader using the native method pumpBytes. pumpBytes in turn
158 // decodes the image data and calls back areaPrepared and areaUpdated on
159 // this object, feeding back decoded pixel blocks, which we pass to each
160 // of the ImageConsumers in the provided Vector.
162 public void produce (Vector v, InputStream is) throws IOException
164 curr = v;
166 byte bytes[] = new byte[4096];
167 int len = 0;
168 initState();
169 needsClose = true;
170 while ((len = is.read (bytes)) != -1)
171 pumpBytes (bytes, len);
172 pumpDone();
173 needsClose = false;
175 for (int i = 0; i < curr.size (); i++)
177 ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
178 ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
181 curr = null;
184 public void finalize()
186 finish(needsClose);
190 public static class ImageFormatSpec
192 public String name;
193 public boolean writable = false;
194 public ArrayList mimeTypes = new ArrayList();
195 public ArrayList extensions = new ArrayList();
197 public ImageFormatSpec(String name, boolean writable)
199 this.name = name;
200 this.writable = writable;
203 public synchronized void addMimeType(String m)
205 mimeTypes.add(m);
208 public synchronized void addExtension(String e)
210 extensions.add(e);
214 static ArrayList imageFormatSpecs;
216 public static ImageFormatSpec registerFormat(String name, boolean writable)
218 ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
219 synchronized(GdkPixbufDecoder.class)
221 if (imageFormatSpecs == null)
222 imageFormatSpecs = new ArrayList();
223 imageFormatSpecs.add(ifs);
225 return ifs;
228 static String[] getFormatNames(boolean writable)
230 ArrayList names = new ArrayList();
231 synchronized (imageFormatSpecs)
233 Iterator i = imageFormatSpecs.iterator();
234 while (i.hasNext())
236 ImageFormatSpec ifs = (ImageFormatSpec) i.next();
237 if (writable && !ifs.writable)
238 continue;
239 names.add(ifs.name);
242 * In order to make the filtering code work, we need to register
243 * this type under every "format name" likely to be used as a synonym.
244 * This generally means "all the extensions people might use".
247 Iterator j = ifs.extensions.iterator();
248 while (j.hasNext())
249 names.add((String) j.next());
252 Object[] objs = names.toArray();
253 String[] strings = new String[objs.length];
254 for (int i = 0; i < objs.length; ++i)
255 strings[i] = (String) objs[i];
256 return strings;
259 static String[] getFormatExtensions(boolean writable)
261 ArrayList extensions = new ArrayList();
262 synchronized (imageFormatSpecs)
264 Iterator i = imageFormatSpecs.iterator();
265 while (i.hasNext())
267 ImageFormatSpec ifs = (ImageFormatSpec) i.next();
268 if (writable && !ifs.writable)
269 continue;
270 Iterator j = ifs.extensions.iterator();
271 while (j.hasNext())
272 extensions.add((String) j.next());
275 Object[] objs = extensions.toArray();
276 String[] strings = new String[objs.length];
277 for (int i = 0; i < objs.length; ++i)
278 strings[i] = (String) objs[i];
279 return strings;
282 static String[] getFormatMimeTypes(boolean writable)
284 ArrayList mimeTypes = new ArrayList();
285 synchronized (imageFormatSpecs)
287 Iterator i = imageFormatSpecs.iterator();
288 while (i.hasNext())
290 ImageFormatSpec ifs = (ImageFormatSpec) i.next();
291 if (writable && !ifs.writable)
292 continue;
293 Iterator j = ifs.mimeTypes.iterator();
294 while (j.hasNext())
295 mimeTypes.add((String) j.next());
298 Object[] objs = mimeTypes.toArray();
299 String[] strings = new String[objs.length];
300 for (int i = 0; i < objs.length; ++i)
301 strings[i] = (String) objs[i];
302 return strings;
306 static String findFormatName(Object ext, boolean needWritable)
308 if (ext == null)
309 return null;
311 if (!(ext instanceof String))
312 throw new IllegalArgumentException("extension is not a string");
314 String str = (String) ext;
316 Iterator i = imageFormatSpecs.iterator();
317 while (i.hasNext())
319 ImageFormatSpec ifs = (ImageFormatSpec) i.next();
321 if (needWritable && !ifs.writable)
322 continue;
324 if (ifs.name.equals(str))
325 return str;
327 Iterator j = ifs.extensions.iterator();
328 while (j.hasNext())
330 String extension = (String)j.next();
331 if (extension.equals(str))
332 return ifs.name;
335 j = ifs.mimeTypes.iterator();
336 while (j.hasNext())
338 String mimeType = (String)j.next();
339 if (mimeType.equals(str))
340 return ifs.name;
343 throw new IllegalArgumentException("unknown extension '" + str + "'");
346 private static GdkPixbufReaderSpi readerSpi;
347 private static GdkPixbufWriterSpi writerSpi;
349 public static synchronized GdkPixbufReaderSpi getReaderSpi()
351 if (readerSpi == null)
352 readerSpi = new GdkPixbufReaderSpi();
353 return readerSpi;
356 public static synchronized GdkPixbufWriterSpi getWriterSpi()
358 if (writerSpi == null)
359 writerSpi = new GdkPixbufWriterSpi();
360 return writerSpi;
363 public static void registerSpis(IIORegistry reg)
365 reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class);
366 reg.registerServiceProvider(getWriterSpi(), ImageWriterSpi.class);
369 public static class GdkPixbufWriterSpi extends ImageWriterSpi
371 public GdkPixbufWriterSpi()
373 super("GdkPixbuf", "2.x",
374 GdkPixbufDecoder.getFormatNames(true),
375 GdkPixbufDecoder.getFormatExtensions(true),
376 GdkPixbufDecoder.getFormatMimeTypes(true),
377 "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriter",
378 new Class[] { ImageOutputStream.class },
379 new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReaderSpi" },
380 false, null, null, null, null,
381 false, null, null, null, null);
384 public boolean canEncodeImage(ImageTypeSpecifier ts)
386 return true;
389 public ImageWriter createWriterInstance(Object ext)
391 return new GdkPixbufWriter(this, ext);
394 public String getDescription(java.util.Locale loc)
396 return "GdkPixbuf Writer SPI";
401 public static class GdkPixbufReaderSpi extends ImageReaderSpi
403 public GdkPixbufReaderSpi()
405 super("GdkPixbuf", "2.x",
406 GdkPixbufDecoder.getFormatNames(false),
407 GdkPixbufDecoder.getFormatExtensions(false),
408 GdkPixbufDecoder.getFormatMimeTypes(false),
409 "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReader",
410 new Class[] { ImageInputStream.class },
411 new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriterSpi" },
412 false, null, null, null, null,
413 false, null, null, null, null);
416 public boolean canDecodeInput(Object obj)
418 return true;
421 public ImageReader createReaderInstance(Object ext)
423 return new GdkPixbufReader(this, ext);
426 public String getDescription(Locale loc)
428 return "GdkPixbuf Reader SPI";
432 private static class GdkPixbufWriter
433 extends ImageWriter
435 String ext;
436 public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext)
438 super(ownerSpi);
439 this.ext = findFormatName(ext, true);
442 public IIOMetadata convertImageMetadata (IIOMetadata inData,
443 ImageTypeSpecifier imageType,
444 ImageWriteParam param)
446 return null;
449 public IIOMetadata convertStreamMetadata (IIOMetadata inData,
450 ImageWriteParam param)
452 return null;
455 public IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType,
456 ImageWriteParam param)
458 return null;
461 public IIOMetadata getDefaultStreamMetadata (ImageWriteParam param)
463 return null;
466 public void write (IIOMetadata streamMetadata, IIOImage i, ImageWriteParam param)
467 throws IOException
469 RenderedImage image = i.getRenderedImage();
470 Raster ras = image.getData();
471 int width = ras.getWidth();
472 int height = ras.getHeight();
473 ColorModel model = image.getColorModel();
474 int[] pixels = GdkGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras);
476 if (pixels == null)
478 BufferedImage img = new BufferedImage(width, height,
479 (model != null && model.hasAlpha() ?
480 BufferedImage.TYPE_INT_ARGB
481 : BufferedImage.TYPE_INT_RGB));
482 int[] pix = new int[4];
483 for (int y = 0; y < height; ++y)
484 for (int x = 0; x < width; ++x)
485 img.setRGB(x, y, model.getRGB(ras.getPixel(x, y, pix)));
486 pixels = GdkGraphics2D.findSimpleIntegerArray (img.getColorModel(),
487 img.getRaster());
488 model = img.getColorModel();
491 processImageStarted(1);
492 streamImage(pixels, this.ext, width, height, model.hasAlpha(),
493 (DataOutput) this.getOutput());
494 processImageComplete();
498 private static class GdkPixbufReader
499 extends ImageReader
500 implements ImageConsumer
502 // ImageConsumer parts
503 GdkPixbufDecoder dec;
504 BufferedImage bufferedImage;
505 ColorModel defaultModel;
506 int width;
507 int height;
508 String ext;
510 public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext)
512 super(ownerSpi);
513 this.ext = findFormatName(ext, false);
516 public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext, GdkPixbufDecoder d)
518 this(ownerSpi, ext);
519 dec = d;
522 public void setDimensions(int w, int h)
524 processImageStarted(1);
525 width = w;
526 height = h;
529 public void setProperties(Hashtable props) {}
531 public void setColorModel(ColorModel model)
533 defaultModel = model;
536 public void setHints(int flags) {}
538 public void setPixels(int x, int y, int w, int h,
539 ColorModel model, byte[] pixels,
540 int offset, int scansize)
544 public void setPixels(int x, int y, int w, int h,
545 ColorModel model, int[] pixels,
546 int offset, int scansize)
548 if (model == null)
549 model = defaultModel;
551 if (bufferedImage == null)
553 bufferedImage = new BufferedImage (width, height, (model != null && model.hasAlpha() ?
554 BufferedImage.TYPE_INT_ARGB
555 : BufferedImage.TYPE_INT_RGB));
558 int pixels2[];
559 if (model != null)
561 pixels2 = new int[pixels.length];
562 for (int yy = 0; yy < h; yy++)
563 for (int xx = 0; xx < w; xx++)
565 int i = yy * scansize + xx;
566 pixels2[i] = model.getRGB (pixels[i]);
569 else
570 pixels2 = pixels;
572 bufferedImage.setRGB (x, y, w, h, pixels2, offset, scansize);
573 processImageProgress(y / (height == 0 ? 1 : height));
576 public void imageComplete(int status)
578 processImageComplete();
581 public BufferedImage getBufferedImage()
583 if (bufferedImage == null && dec != null)
584 dec.startProduction (this);
585 return bufferedImage;
588 // ImageReader parts
590 public int getNumImages(boolean allowSearch)
591 throws IOException
593 return 1;
596 public IIOMetadata getImageMetadata(int i)
598 return null;
601 public IIOMetadata getStreamMetadata()
602 throws IOException
604 return null;
607 public Iterator getImageTypes(int imageIndex)
608 throws IOException
610 BufferedImage img = getBufferedImage();
611 Vector vec = new Vector();
612 vec.add(new ImageTypeSpecifier(img));
613 return vec.iterator();
616 public int getHeight(int imageIndex)
617 throws IOException
619 return getBufferedImage().getHeight();
622 public int getWidth(int imageIndex)
623 throws IOException
625 return getBufferedImage().getWidth();
628 public void setInput(Object input,
629 boolean seekForwardOnly,
630 boolean ignoreMetadata)
632 super.setInput(input, seekForwardOnly, ignoreMetadata);
633 dec = new GdkPixbufDecoder((InputStream) getInput());
636 public BufferedImage read(int imageIndex, ImageReadParam param)
637 throws IOException
639 return getBufferedImage ();
643 // remaining helper class and static method is a convenience for the Gtk
644 // peers, for loading a BufferedImage in off a disk file without going
645 // through the whole imageio system.
647 public static BufferedImage createBufferedImage (String filename)
649 GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
650 "png", // reader auto-detects, doesn't matter
651 new GdkPixbufDecoder (filename));
652 return r.getBufferedImage ();
655 public static BufferedImage createBufferedImage (URL u)
657 GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
658 "png", // reader auto-detects, doesn't matter
659 new GdkPixbufDecoder (u));
660 return r.getBufferedImage ();
663 public static BufferedImage createBufferedImage (byte[] imagedata, int imageoffset,
664 int imagelength)
666 GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
667 "png", // reader auto-detects, doesn't matter
668 new GdkPixbufDecoder (imagedata,
669 imageoffset,
670 imagelength));
671 return r.getBufferedImage ();
674 public static BufferedImage createBufferedImage (ImageProducer producer)
676 GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), "png" /* ignored */, null);
677 producer.startProduction(r);
678 return r.getBufferedImage ();