mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			786 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			786 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* GdkPixbufDecoder.java -- Image data decoding object
 | |
|    Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package gnu.java.awt.peer.gtk;
 | |
| 
 | |
| import java.awt.image.BufferedImage;
 | |
| import java.awt.image.ColorModel;
 | |
| import java.awt.image.DirectColorModel;
 | |
| import java.awt.image.ImageConsumer;
 | |
| import java.awt.image.Raster;
 | |
| import java.awt.image.RenderedImage;
 | |
| import java.io.DataInput;
 | |
| import java.io.DataOutput;
 | |
| import java.io.IOException;
 | |
| import java.io.InputStream;
 | |
| import java.net.URL;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Hashtable;
 | |
| import java.util.Iterator;
 | |
| import java.util.Locale;
 | |
| import java.util.Vector;
 | |
| 
 | |
| import javax.imageio.IIOImage;
 | |
| import javax.imageio.ImageReadParam;
 | |
| import javax.imageio.ImageReader;
 | |
| import javax.imageio.ImageTypeSpecifier;
 | |
| import javax.imageio.ImageWriteParam;
 | |
| import javax.imageio.ImageWriter;
 | |
| import javax.imageio.metadata.IIOMetadata;
 | |
| import javax.imageio.spi.IIORegistry;
 | |
| import javax.imageio.spi.ImageReaderSpi;
 | |
| import javax.imageio.spi.ImageWriterSpi;
 | |
| import javax.imageio.stream.ImageInputStream;
 | |
| import javax.imageio.stream.ImageOutputStream;
 | |
| 
 | |
| import gnu.classpath.Configuration;
 | |
| import gnu.classpath.Pointer;
 | |
| 
 | |
| public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
 | |
| {
 | |
|   static
 | |
|   {
 | |
|     if (true) // GCJ LOCAL
 | |
|       {
 | |
|         System.loadLibrary("gtkpeer");
 | |
|       }
 | |
| 
 | |
|     initStaticState ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Lock that should be held for all gdkpixbuf operations. We don't use
 | |
|    * the global gdk_threads_enter/leave functions since gdkpixbuf
 | |
|    * operations can be done in parallel to drawing and manipulating gtk
 | |
|    * widgets.
 | |
|    */
 | |
|   static Object pixbufLock = new Object();
 | |
| 
 | |
|   static native void initStaticState();
 | |
|   private final int native_state = GtkGenericPeer.getUniqueInteger ();
 | |
| 
 | |
|   // initState() has been called, but pumpDone() has not yet been called.
 | |
|   private boolean needsClose = false;
 | |
| 
 | |
|   // the current set of ImageConsumers for this decoder
 | |
|   Vector curr;
 | |
| 
 | |
|   /**
 | |
|    * The pointer to the native pixbuf loader.
 | |
|    *
 | |
|    * This field is manipulated by native code. Don't change or remove
 | |
|    * without adjusting the native code.
 | |
|    */
 | |
|   private Pointer nativeDecoder;
 | |
| 
 | |
|   // interface to GdkPixbuf
 | |
|   // These native functions should be called with the pixbufLock held.
 | |
|   native void initState ();
 | |
|   native void pumpBytes (byte[] bytes, int len) throws IOException;
 | |
|   native void pumpDone () throws IOException;
 | |
|   native void finish (boolean needsClose);
 | |
| 
 | |
|   /**
 | |
|    * Converts given image to bytes.
 | |
|    * Will call the GdkPixbufWriter for each chunk.
 | |
|    */
 | |
|   static native void streamImage(int[] bytes, String format,
 | |
|                                  int width, int height,
 | |
|                                  boolean hasAlpha, GdkPixbufWriter writer);
 | |
| 
 | |
|   // gdk-pixbuf provids data in RGBA format
 | |
|   static final ColorModel cm = new DirectColorModel (32, 0xff000000,
 | |
|                                                      0x00ff0000,
 | |
|                                                      0x0000ff00,
 | |
|                                                      0x000000ff);
 | |
|   public GdkPixbufDecoder (DataInput datainput)
 | |
|   {
 | |
|     super (datainput);
 | |
|   }
 | |
| 
 | |
|   public GdkPixbufDecoder (InputStream in)
 | |
|   {
 | |
|     super (in);
 | |
|   }
 | |
| 
 | |
|   public GdkPixbufDecoder (String filename)
 | |
|   {
 | |
|     super (filename);
 | |
|   }
 | |
| 
 | |
|   public GdkPixbufDecoder (URL url)
 | |
|   {
 | |
|     super (url);
 | |
|   }
 | |
| 
 | |
|   public GdkPixbufDecoder (byte[] imagedata, int imageoffset, int imagelength)
 | |
|   {
 | |
|     super (imagedata, imageoffset, imagelength);
 | |
|   }
 | |
| 
 | |
|   // called back by native side: area_prepared_cb
 | |
|   void areaPrepared (int width, int height)
 | |
|   {
 | |
| 
 | |
|     if (curr == null)
 | |
|       return;
 | |
| 
 | |
|     for (int i = 0; i < curr.size (); i++)
 | |
|       {
 | |
|         ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
 | |
|         ic.setDimensions (width, height);
 | |
|         ic.setColorModel (cm);
 | |
|         ic.setHints (ImageConsumer.RANDOMPIXELORDER);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // called back by native side: area_updated_cb
 | |
|   void areaUpdated (int x, int y, int width, int height,
 | |
|                     int pixels[], int scansize)
 | |
|   {
 | |
|     if (curr == null)
 | |
|       return;
 | |
| 
 | |
|     for (int i = 0; i < curr.size (); i++)
 | |
|       {
 | |
|         ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
 | |
|         ic.setPixels (x, y, width, height, cm, pixels, 0, scansize);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // called from an async image loader of one sort or another, this method
 | |
|   // repeatedly reads bytes from the input stream and passes them through a
 | |
|   // GdkPixbufLoader using the native method pumpBytes. pumpBytes in turn
 | |
|   // decodes the image data and calls back areaPrepared and areaUpdated on
 | |
|   // this object, feeding back decoded pixel blocks, which we pass to each
 | |
|   // of the ImageConsumers in the provided Vector.
 | |
| 
 | |
|   public void produce (Vector v, InputStream is) throws IOException
 | |
|   {
 | |
|     curr = v;
 | |
| 
 | |
|     byte bytes[] = new byte[4096];
 | |
|     int len = 0;
 | |
|     synchronized(pixbufLock)
 | |
|       {
 | |
|         initState();
 | |
|       }
 | |
|     needsClose = true;
 | |
| 
 | |
|     // Note: We don't want the pixbufLock while reading from the InputStream.
 | |
|     while ((len = is.read (bytes)) != -1)
 | |
|       {
 | |
|         synchronized(pixbufLock)
 | |
|           {
 | |
|             pumpBytes (bytes, len);
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     synchronized(pixbufLock)
 | |
|       {
 | |
|         pumpDone();
 | |
|       }
 | |
| 
 | |
|     needsClose = false;
 | |
| 
 | |
|     for (int i = 0; i < curr.size (); i++)
 | |
|       {
 | |
|         ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
 | |
|         ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
 | |
|       }
 | |
| 
 | |
|     curr = null;
 | |
|   }
 | |
| 
 | |
|   public void finalize()
 | |
|   {
 | |
|     synchronized(pixbufLock)
 | |
|       {
 | |
|         finish(needsClose);
 | |
|       }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public static class ImageFormatSpec
 | |
|   {
 | |
|     public String name;
 | |
|     public boolean writable = false;
 | |
|     public ArrayList<String> mimeTypes = new ArrayList<String>();
 | |
|     public ArrayList<String> extensions = new ArrayList<String>();
 | |
| 
 | |
|     public ImageFormatSpec(String name, boolean writable)
 | |
|     {
 | |
|       this.name = name;
 | |
|       this.writable = writable;
 | |
|     }
 | |
| 
 | |
|     public synchronized void addMimeType(String m)
 | |
|     {
 | |
|       mimeTypes.add(m);
 | |
|     }
 | |
| 
 | |
|     public synchronized void addExtension(String e)
 | |
|     {
 | |
|       extensions.add(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static ArrayList<ImageFormatSpec> imageFormatSpecs;
 | |
| 
 | |
|   public static ImageFormatSpec registerFormat(String name, boolean writable)
 | |
|   {
 | |
|     ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
 | |
|     synchronized(GdkPixbufDecoder.class)
 | |
|       {
 | |
|         if (imageFormatSpecs == null)
 | |
|           imageFormatSpecs = new ArrayList<ImageFormatSpec>();
 | |
|         imageFormatSpecs.add(ifs);
 | |
|       }
 | |
|     return ifs;
 | |
|   }
 | |
| 
 | |
|   static String[] getFormatNames(boolean writable)
 | |
|   {
 | |
|     ArrayList<String> names = new ArrayList<String>();
 | |
|     synchronized (imageFormatSpecs)
 | |
|       {
 | |
|         Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
 | |
|         while (i.hasNext())
 | |
|           {
 | |
|             ImageFormatSpec ifs = i.next();
 | |
|             if (writable && !ifs.writable)
 | |
|               continue;
 | |
|             names.add(ifs.name);
 | |
| 
 | |
|             /*
 | |
|              * In order to make the filtering code work, we need to register
 | |
|              * this type under every "format name" likely to be used as a synonym.
 | |
|              * This generally means "all the extensions people might use".
 | |
|              */
 | |
| 
 | |
|             Iterator<String> j = ifs.extensions.iterator();
 | |
|             while (j.hasNext())
 | |
|               names.add(j.next());
 | |
|           }
 | |
|       }
 | |
|     return names.toArray(new String[names.size()]);
 | |
|   }
 | |
| 
 | |
|   static String[] getFormatExtensions(boolean writable)
 | |
|   {
 | |
|     ArrayList<String> extensions = new ArrayList<String>();
 | |
|     synchronized (imageFormatSpecs)
 | |
|       {
 | |
|         Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
 | |
|         while (i.hasNext())
 | |
|           {
 | |
|             ImageFormatSpec ifs = i.next();
 | |
|             if (writable && !ifs.writable)
 | |
|               continue;
 | |
|             Iterator<String> j = ifs.extensions.iterator();
 | |
|             while (j.hasNext())
 | |
|               extensions.add(j.next());
 | |
|           }
 | |
|       }
 | |
|     return extensions.toArray(new String[extensions.size()]);
 | |
|   }
 | |
| 
 | |
|   static String[] getFormatMimeTypes(boolean writable)
 | |
|   {
 | |
|     ArrayList<String> mimeTypes = new ArrayList<String>();
 | |
|     synchronized (imageFormatSpecs)
 | |
|       {
 | |
|         Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
 | |
|         while (i.hasNext())
 | |
|           {
 | |
|             ImageFormatSpec ifs = i.next();
 | |
|             if (writable && !ifs.writable)
 | |
|               continue;
 | |
|             Iterator<String> j = ifs.mimeTypes.iterator();
 | |
|             while (j.hasNext())
 | |
|               mimeTypes.add(j.next());
 | |
|           }
 | |
|       }
 | |
|     return mimeTypes.toArray(new String[mimeTypes.size()]);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   static String findFormatName(Object ext, boolean needWritable)
 | |
|   {
 | |
|     if (ext == null)
 | |
|       return null;
 | |
| 
 | |
|     if (!(ext instanceof String))
 | |
|       throw new IllegalArgumentException("extension is not a string");
 | |
| 
 | |
|     String str = (String) ext;
 | |
| 
 | |
|     Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
 | |
|     while (i.hasNext())
 | |
|       {
 | |
|         ImageFormatSpec ifs = i.next();
 | |
| 
 | |
|         if (needWritable && !ifs.writable)
 | |
|           continue;
 | |
| 
 | |
|         if (ifs.name.equals(str))
 | |
|           return str;
 | |
| 
 | |
|         Iterator<String> j = ifs.extensions.iterator();
 | |
|         while (j.hasNext())
 | |
|           {
 | |
|             String extension = j.next();
 | |
|             if (extension.equals(str))
 | |
|               return ifs.name;
 | |
|           }
 | |
| 
 | |
|         j = ifs.mimeTypes.iterator();
 | |
|         while (j.hasNext())
 | |
|           {
 | |
|             String mimeType = j.next();
 | |
|             if (mimeType.equals(str))
 | |
|               return ifs.name;
 | |
|           }
 | |
|       }
 | |
|     throw new IllegalArgumentException("unknown extension '" + str + "'");
 | |
|   }
 | |
| 
 | |
|   private static GdkPixbufReaderSpi readerSpi;
 | |
|   private static GdkPixbufWriterSpi writerSpi;
 | |
| 
 | |
|   public static synchronized GdkPixbufReaderSpi getReaderSpi()
 | |
|   {
 | |
|     if (readerSpi == null)
 | |
|       readerSpi = new GdkPixbufReaderSpi();
 | |
|     return readerSpi;
 | |
|   }
 | |
| 
 | |
|   public static synchronized GdkPixbufWriterSpi getWriterSpi()
 | |
|   {
 | |
|     if (writerSpi == null)
 | |
|       writerSpi = new GdkPixbufWriterSpi();
 | |
|     return writerSpi;
 | |
|   }
 | |
| 
 | |
|   public static void registerSpis(IIORegistry reg)
 | |
|   {
 | |
|     reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class);
 | |
|     reg.registerServiceProvider(getWriterSpi(), ImageWriterSpi.class);
 | |
|   }
 | |
| 
 | |
|   public static class GdkPixbufWriterSpi extends ImageWriterSpi
 | |
|   {
 | |
|     public GdkPixbufWriterSpi()
 | |
|     {
 | |
|       super("GdkPixbuf", "2.x",
 | |
|             GdkPixbufDecoder.getFormatNames(true),
 | |
|             GdkPixbufDecoder.getFormatExtensions(true),
 | |
|             GdkPixbufDecoder.getFormatMimeTypes(true),
 | |
|             "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriter",
 | |
|             new Class[] { ImageOutputStream.class },
 | |
|             new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReaderSpi" },
 | |
|             false, null, null, null, null,
 | |
|             false, null, null, null, null);
 | |
|     }
 | |
| 
 | |
|     public boolean canEncodeImage(ImageTypeSpecifier ts)
 | |
|     {
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     public ImageWriter createWriterInstance(Object ext)
 | |
|     {
 | |
|       return new GdkPixbufWriter(this, ext);
 | |
|     }
 | |
| 
 | |
|     public String getDescription(java.util.Locale loc)
 | |
|     {
 | |
|       return "GdkPixbuf Writer SPI";
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   public static class GdkPixbufReaderSpi extends ImageReaderSpi
 | |
|   {
 | |
|     public GdkPixbufReaderSpi()
 | |
|     {
 | |
|       super("GdkPixbuf", "2.x",
 | |
|             GdkPixbufDecoder.getFormatNames(false),
 | |
|             GdkPixbufDecoder.getFormatExtensions(false),
 | |
|             GdkPixbufDecoder.getFormatMimeTypes(false),
 | |
|             "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReader",
 | |
|             new Class[] { ImageInputStream.class },
 | |
|             new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriterSpi" },
 | |
|             false, null, null, null, null,
 | |
|             false, null, null, null, null);
 | |
|     }
 | |
| 
 | |
|     public boolean canDecodeInput(Object obj)
 | |
|     {
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     public ImageReader createReaderInstance(Object ext)
 | |
|     {
 | |
|       return new GdkPixbufReader(this, ext);
 | |
|     }
 | |
| 
 | |
|     public String getDescription(Locale loc)
 | |
|     {
 | |
|       return "GdkPixbuf Reader SPI";
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class GdkPixbufWriter
 | |
|     extends ImageWriter implements Runnable
 | |
|   {
 | |
|     String ext;
 | |
|     public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext)
 | |
|     {
 | |
|       super(ownerSpi);
 | |
|       this.ext = findFormatName(ext, true);
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata convertImageMetadata (IIOMetadata inData,
 | |
|                                              ImageTypeSpecifier imageType,
 | |
|                                              ImageWriteParam param)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata convertStreamMetadata (IIOMetadata inData,
 | |
|                                               ImageWriteParam param)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType,
 | |
|                                                 ImageWriteParam param)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata getDefaultStreamMetadata (ImageWriteParam param)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|   public void write (IIOMetadata streamMetadata, IIOImage i, ImageWriteParam param)
 | |
|     throws IOException
 | |
|     {
 | |
|       RenderedImage image = i.getRenderedImage();
 | |
|       Raster ras = image.getData();
 | |
|       int width = ras.getWidth();
 | |
|       int height = ras.getHeight();
 | |
|       ColorModel model = image.getColorModel();
 | |
|       int[] pixels = CairoGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras);
 | |
| 
 | |
|       if (pixels == null)
 | |
|         {
 | |
|           BufferedImage img;
 | |
|           if(model != null && model.hasAlpha())
 | |
|             img = CairoSurface.getBufferedImage(width, height);
 | |
|           img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
 | |
|           int[] pix = new int[4];
 | |
|           for (int y = 0; y < height; ++y)
 | |
|             for (int x = 0; x < width; ++x)
 | |
|               img.setRGB(x, y, model.getRGB(ras.getPixel(x, y, pix)));
 | |
|           pixels = CairoGraphics2D.findSimpleIntegerArray (img.getColorModel(),
 | |
|                                                          img.getRaster());
 | |
|           model = img.getColorModel();
 | |
|         }
 | |
| 
 | |
|       Thread workerThread = new Thread(this, "GdkPixbufWriter");
 | |
|       workerThread.start();
 | |
|       processImageStarted(1);
 | |
|       synchronized(pixbufLock)
 | |
|         {
 | |
|           streamImage(pixels, this.ext, width, height, model.hasAlpha(),
 | |
|                       this);
 | |
|         }
 | |
|       synchronized(data)
 | |
|         {
 | |
|           data.add(DATADONE);
 | |
|           data.notifyAll();
 | |
|         }
 | |
| 
 | |
|       while (workerThread.isAlive())
 | |
|         {
 | |
|           try
 | |
|             {
 | |
|               workerThread.join();
 | |
|             }
 | |
|           catch (InterruptedException ioe)
 | |
|             {
 | |
|               // Ignored.
 | |
|             }
 | |
|         }
 | |
| 
 | |
|       if (exception != null)
 | |
|         throw exception;
 | |
| 
 | |
|       processImageComplete();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Object marking end of data from native streamImage code.
 | |
|      */
 | |
|     private static final Object DATADONE = new Object();
 | |
| 
 | |
|     /**
 | |
|      * Holds the data gotten from the native streamImage code.
 | |
|      * A worker thread will pull data out.
 | |
|      * Needs to be synchronized for access.
 | |
|      * The special object DATADONE is added when all data has been delivered.
 | |
|      */
 | |
|     private ArrayList<Object> data = new ArrayList<Object>();
 | |
| 
 | |
|     /**
 | |
|      * Holds any IOException thrown by the run method that needs
 | |
|      * to be rethrown by the write method.
 | |
|      */
 | |
|     private IOException exception;
 | |
| 
 | |
|     /** Callback for streamImage native code. **/
 | |
|     private void write(byte[] bs)
 | |
|     {
 | |
|       synchronized(data)
 | |
|         {
 | |
|           data.add(bs);
 | |
|           data.notifyAll();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void run()
 | |
|     {
 | |
|       boolean done = false;
 | |
|       while (!done)
 | |
|         {
 | |
|           synchronized(data)
 | |
|             {
 | |
|               while (data.isEmpty())
 | |
|                 {
 | |
|                   try
 | |
|                     {
 | |
|                       data.wait();
 | |
|                     }
 | |
|                   catch (InterruptedException ie)
 | |
|                     {
 | |
|                       /* ignore */
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|               Object o = data.remove(0);
 | |
|               if (o == DATADONE)
 | |
|                 done = true;
 | |
|               else
 | |
|                 {
 | |
|                   DataOutput out = (DataOutput) getOutput();
 | |
|                   try
 | |
|                     {
 | |
|                       out.write((byte[]) o);
 | |
|                     }
 | |
|                   catch (IOException ioe)
 | |
|                     {
 | |
|                       // We are only interested in the first exception.
 | |
|                       if (exception == null)
 | |
|                         exception = ioe;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class GdkPixbufReader
 | |
|     extends ImageReader
 | |
|     implements ImageConsumer
 | |
|   {
 | |
|     // ImageConsumer parts
 | |
|     GdkPixbufDecoder dec;
 | |
|     BufferedImage bufferedImage;
 | |
|     ColorModel defaultModel;
 | |
|     int width;
 | |
|     int height;
 | |
|     String ext;
 | |
| 
 | |
|     public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext)
 | |
|     {
 | |
|       super(ownerSpi);
 | |
|       this.ext = findFormatName(ext, false);
 | |
|     }
 | |
| 
 | |
|     public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext,
 | |
|                            GdkPixbufDecoder d)
 | |
|     {
 | |
|       this(ownerSpi, ext);
 | |
|       dec = d;
 | |
|     }
 | |
| 
 | |
|     public void setDimensions(int w, int h)
 | |
|     {
 | |
|       processImageStarted(1);
 | |
|       width = w;
 | |
|       height = h;
 | |
|     }
 | |
| 
 | |
|     public void setProperties(Hashtable props) {}
 | |
| 
 | |
|     public void setColorModel(ColorModel model)
 | |
|     {
 | |
|       defaultModel = model;
 | |
|     }
 | |
| 
 | |
|     public void setHints(int flags) {}
 | |
| 
 | |
|     public void setPixels(int x, int y, int w, int h,
 | |
|                           ColorModel model, byte[] pixels,
 | |
|                           int offset, int scansize)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     public void setPixels(int x, int y, int w, int h,
 | |
|                           ColorModel model, int[] pixels,
 | |
|                           int offset, int scansize)
 | |
|     {
 | |
|       if (model == null)
 | |
|         model = defaultModel;
 | |
| 
 | |
|       if (bufferedImage == null)
 | |
|         {
 | |
|           if(model != null && model.hasAlpha())
 | |
|             bufferedImage = new BufferedImage (width, height,
 | |
|                                                BufferedImage.TYPE_INT_ARGB);
 | |
|           else
 | |
|             bufferedImage = new BufferedImage (width, height,
 | |
|                                                BufferedImage.TYPE_INT_RGB);
 | |
|         }
 | |
| 
 | |
|       int pixels2[];
 | |
|       if (model != null)
 | |
|         {
 | |
|           pixels2 = new int[pixels.length];
 | |
|           for (int yy = 0; yy < h; yy++)
 | |
|             for (int xx = 0; xx < w; xx++)
 | |
|               {
 | |
|                 int i = yy * scansize + xx;
 | |
|                 pixels2[i] = model.getRGB (pixels[i]);
 | |
|               }
 | |
|         }
 | |
|       else
 | |
|         pixels2 = pixels;
 | |
| 
 | |
|       bufferedImage.setRGB (x, y, w, h, pixels2, offset, scansize);
 | |
|       processImageProgress(y / (height == 0 ? 1 : height));
 | |
|     }
 | |
| 
 | |
|     public void imageComplete(int status)
 | |
|     {
 | |
|       processImageComplete();
 | |
|     }
 | |
| 
 | |
|     public BufferedImage getBufferedImage()
 | |
|     {
 | |
|       if (bufferedImage == null && dec != null)
 | |
|         dec.startProduction (this);
 | |
|       return bufferedImage;
 | |
|     }
 | |
| 
 | |
|     // ImageReader parts
 | |
| 
 | |
|     public int getNumImages(boolean allowSearch)
 | |
|       throws IOException
 | |
|     {
 | |
|       return 1;
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata getImageMetadata(int i)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     public IIOMetadata getStreamMetadata()
 | |
|       throws IOException
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
 | |
|       throws IOException
 | |
|     {
 | |
|       BufferedImage img = getBufferedImage();
 | |
|       Vector<ImageTypeSpecifier> vec = new Vector<ImageTypeSpecifier>();
 | |
|       vec.add(new ImageTypeSpecifier(img));
 | |
|       return vec.iterator();
 | |
|     }
 | |
| 
 | |
|     public int getHeight(int imageIndex)
 | |
|       throws IOException
 | |
|     {
 | |
|       return getBufferedImage().getHeight();
 | |
|     }
 | |
| 
 | |
|     public int getWidth(int imageIndex)
 | |
|       throws IOException
 | |
|     {
 | |
|       return getBufferedImage().getWidth();
 | |
|     }
 | |
| 
 | |
|     public void setInput(Object input,
 | |
|                          boolean seekForwardOnly,
 | |
|                          boolean ignoreMetadata)
 | |
|     {
 | |
|       super.setInput(input, seekForwardOnly, ignoreMetadata);
 | |
|       Object get = getInput();
 | |
|       if (get instanceof InputStream)
 | |
|         dec = new GdkPixbufDecoder((InputStream) get);
 | |
|       else if (get instanceof DataInput)
 | |
|         dec = new GdkPixbufDecoder((DataInput) get);
 | |
|       else
 | |
|         throw new IllegalArgumentException("input object not supported: "
 | |
|                                            + get);
 | |
|     }
 | |
| 
 | |
|     public BufferedImage read(int imageIndex, ImageReadParam param)
 | |
|       throws IOException
 | |
|     {
 | |
|       return getBufferedImage ();
 | |
|     }
 | |
|   }
 | |
| }
 |