GdkPixbufDecoder.java [plain text]
package gnu.java.awt.peer.gtk;
import gnu.classpath.Configuration;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
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;
public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
{
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary("gtkpeer");
}
initStaticState ();
}
static native void initStaticState();
private final int native_state = GtkGenericPeer.getUniqueInteger ();
private boolean initialized = false;
Vector curr;
native void initState ();
native void pumpBytes (byte[] bytes, int len);
native void finish ();
static native void streamImage(int[] bytes, String format, int width, int height, boolean hasAlpha, DataOutput sink);
static final ColorModel cm = new DirectColorModel (32, 0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff);
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);
}
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);
}
}
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);
}
}
public void produce (Vector v, InputStream is) throws IOException
{
curr = v;
byte bytes[] = new byte[4096];
int len = 0;
initState();
while ((len = is.read (bytes)) != -1)
pumpBytes (bytes, len);
for (int i = 0; i < curr.size (); i++)
{
ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
}
curr = null;
}
public void finalize()
{
finish();
}
public static class ImageFormatSpec
{
public String name;
public boolean writable = false;
public ArrayList mimeTypes = new ArrayList();
public ArrayList extensions = new ArrayList();
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 imageFormatSpecs;
public static ImageFormatSpec registerFormat(String name, boolean writable)
{
ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
synchronized(GdkPixbufDecoder.class)
{
if (imageFormatSpecs == null)
imageFormatSpecs = new ArrayList();
imageFormatSpecs.add(ifs);
}
return ifs;
}
static String[] getFormatNames(boolean writable)
{
ArrayList names = new ArrayList();
synchronized (imageFormatSpecs)
{
Iterator i = imageFormatSpecs.iterator();
while (i.hasNext())
{
ImageFormatSpec ifs = (ImageFormatSpec) i.next();
if (writable && !ifs.writable)
continue;
names.add(ifs.name);
Iterator j = ifs.extensions.iterator();
while (j.hasNext())
names.add((String) j.next());
}
}
Object[] objs = names.toArray();
String[] strings = new String[objs.length];
for (int i = 0; i < objs.length; ++i)
strings[i] = (String) objs[i];
return strings;
}
static String[] getFormatExtensions(boolean writable)
{
ArrayList extensions = new ArrayList();
synchronized (imageFormatSpecs)
{
Iterator i = imageFormatSpecs.iterator();
while (i.hasNext())
{
ImageFormatSpec ifs = (ImageFormatSpec) i.next();
if (writable && !ifs.writable)
continue;
Iterator j = ifs.extensions.iterator();
while (j.hasNext())
extensions.add((String) j.next());
}
}
Object[] objs = extensions.toArray();
String[] strings = new String[objs.length];
for (int i = 0; i < objs.length; ++i)
strings[i] = (String) objs[i];
return strings;
}
static String[] getFormatMimeTypes(boolean writable)
{
ArrayList mimeTypes = new ArrayList();
synchronized (imageFormatSpecs)
{
Iterator i = imageFormatSpecs.iterator();
while (i.hasNext())
{
ImageFormatSpec ifs = (ImageFormatSpec) i.next();
if (writable && !ifs.writable)
continue;
Iterator j = ifs.mimeTypes.iterator();
while (j.hasNext())
mimeTypes.add((String) j.next());
}
}
Object[] objs = mimeTypes.toArray();
String[] strings = new String[objs.length];
for (int i = 0; i < objs.length; ++i)
strings[i] = (String) objs[i];
return strings;
}
static String findFormatName(Object ext, boolean needWritable)
{
if (ext == null)
throw new IllegalArgumentException("extension is null");
if (!(ext instanceof String))
throw new IllegalArgumentException("extension is not a string");
String str = (String) ext;
Iterator i = imageFormatSpecs.iterator();
while (i.hasNext())
{
ImageFormatSpec ifs = (ImageFormatSpec) i.next();
if (needWritable && !ifs.writable)
continue;
if (ifs.name.equals(str))
return str;
Iterator j = ifs.extensions.iterator();
while (j.hasNext())
{
String extension = (String)j.next();
if (extension.equals(str))
return ifs.name;
}
j = ifs.mimeTypes.iterator();
while (j.hasNext())
{
String mimeType = (String)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
{
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 = GdkGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras);
if (pixels == null)
{
BufferedImage img = new BufferedImage(width, height,
(model != null && model.hasAlpha() ?
BufferedImage.TYPE_INT_ARGB
: 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 = GdkGraphics2D.findSimpleIntegerArray (img.getColorModel(),
img.getRaster());
model = img.getColorModel();
}
processImageStarted(1);
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
(DataOutput) this.getOutput());
processImageComplete();
}
}
private static class GdkPixbufReader
extends ImageReader
implements ImageConsumer
{
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)
{
bufferedImage = new BufferedImage (width, height, (model != null && model.hasAlpha() ?
BufferedImage.TYPE_INT_ARGB
: 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;
}
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 getImageTypes(int imageIndex)
throws IOException
{
BufferedImage img = getBufferedImage();
Vector vec = new Vector();
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);
dec = new GdkPixbufDecoder((InputStream) getInput());
}
public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException
{
return getBufferedImage ();
}
}
public static BufferedImage createBufferedImage (String filename)
{
GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
"png", new GdkPixbufDecoder (filename));
return r.getBufferedImage ();
}
public static BufferedImage createBufferedImage (URL u)
{
GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
"png", new GdkPixbufDecoder (u));
return r.getBufferedImage ();
}
public static BufferedImage createBufferedImage (byte[] imagedata, int imageoffset,
int imagelength)
{
GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(),
"png", new GdkPixbufDecoder (imagedata,
imageoffset,
imagelength));
return r.getBufferedImage ();
}
public static BufferedImage createBufferedImage (ImageProducer producer)
{
GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), "png" , null);
producer.startProduction(r);
return r.getBufferedImage ();
}
}