Package net.sf.jiga.xtended.impl

Source Code of net.sf.jiga.xtended.impl.SpriteIO

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package net.sf.jiga.xtended.impl;

import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
import com.sun.media.imageio.plugins.tiff.EXIFTIFFTagSet;
import com.sun.media.imageio.plugins.tiff.TIFFDirectory;
import com.sun.media.imageio.plugins.tiff.TIFFField;
import com.sun.media.imageio.plugins.tiff.TIFFImageReadParam;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import com.sun.media.imageio.plugins.tiff.TIFFTagSet;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.imageio.IIOImage;
import javax.imageio.IIOParamController;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.event.IIOWriteProgressListener;
import javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileCacheImageInputStream;
import javax.imageio.stream.FileCacheImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.PerspectiveTransform;
import javax.media.jai.RenderedOp;
import javax.media.jai.WarpPerspective;
import net.sf.jiga.xtended.JXAException;
import net.sf.jiga.xtended.impl.game.gl.GLFX;
import net.sf.jiga.xtended.impl.system.BufferIO;
import net.sf.jiga.xtended.impl.system.ImagePool;
import net.sf.jiga.xtended.impl.system.JXAenvUtils2;
import net.sf.jiga.xtended.impl.system.RefPool;
import net.sf.jiga.xtended.impl.system.SfMediaTracker;
import net.sf.jiga.xtended.impl.system.ThreadBlock;
import net.sf.jiga.xtended.impl.system.ThreadBlockData;
import net.sf.jiga.xtended.kernel.DebugMap;
import net.sf.jiga.xtended.kernel.Debugger;
import net.sf.jiga.xtended.kernel.ExtensionsClassLoader;
import net.sf.jiga.xtended.kernel.FileHelper;
import net.sf.jiga.xtended.kernel.JXAenvUtils;
import net.sf.jiga.xtended.ui.ImageCollection;

/**
*
* @author www.b23prodtm.info
*/
public class SpriteIO implements Debugger {

    private final static long hash = System.nanoTime();
    static Map<String, IIOParamController> IIOControllers = Collections.synchronizedMap(new HashMap<String, IIOParamController>());
    /**
     * RGB - no headroom/no footroom
     */
    static final float[] referenceBlackWhiteRGB_NOHead_NOFoot = new float[]{0, 255, 0, 255, 0, 255};
    /**
     * returns the current IIOMetadata instance. it is NOT stored until the
     * Sprite instance is serialized or one of the
     * {@link #writeImageToIOStream(OutputStream) writeImage...()} is called.
     *
     * @return
     *
     * public IIOMetadata getMetadata() { return metadata; }
     */
    /**
     * sets up the current IIOMetadata instance. it is NOT stored until the
     * Sprite instance is serialized or one of the
     * {@link #writeImageToIOStream(OutputStream) writeImage...()} is called.
     *
     * @param metadata the specified IIOMetadata to associate, if possible
     *
     * public void setMetadata(IIOMetadata metadata) { this.metadata = metadata;
     * }
     */
    /**
     * its recommended to use power-of-two sizes
     */
    public static Dimension _WRITE_TILES_DIMENSION = BufferIO._WRITE_TILES_DIMENSION;
    /**
     * YCbCr - CCIR Recommendation 601.1 headroom/footroom
     */
    static final float[] referenceBlackWhiteYCbCr_601_1 = new float[]{15, 235, 128, 240, 128, 240};
    /**
     * this system property is read at first static time and defines the
     * TIFFImageWriter IIOMetadata
     * {@linkplain BaselineTIFFTagSet#TAG_REFERENCE_BLACK_WHITE ReferenceBlackWhite}
     * with no Head/Footroom if set to true (
     *
     * @see http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf#page=86
     * TIFF 6.0 spec document}
     * @default jxa.tiff.nohf=false
     */
    public static boolean _useTIFF_NOHead_NOFoot = Boolean.getBoolean("jxa.tiff.nohf");
    /**
     * YCbCr coefficients CCIR Recommandation 601.1
     */
    static final float[] ycbcrCoefficients_601_1 = new float[]{299.0F / 1000.0F, 587.0F / 1000.0F, 114.0F / 1000.0F};
    /**
     * * EXIF 2.2 output for all TIFF images. (EXPERIMENTAL)
     *
     * @default jxa.tiff.exif=false
     */
    public static boolean _useTIFF_EXIF = Boolean.getBoolean("jxa.tiff.exif");
    /**
     * RGB - CCIR Recommendation 601.1 headroom/footroom
     */
    static final float[] referenceBlackWhiteRGB_601_1 = new float[]{16, 235, 16, 235, 16, 235};
    /**
     * YCbCr coefficients CCIR Recommandation 709
     */
    static final float[] ycbcrCoefficients_709 = new float[]{2125.0F / 10000.0F, 7154.0F / 10000.0F, 721.0F / 10000.0F};
    /**
     * * Unforced TIFF RGB PhotometricInterpretation (slower and buggy if
     * enabled)
     *
     * @default jxa.tiff.norgb=false
     */
    public static boolean _useTIFF_UnforcedRGB = Boolean.getBoolean("jxa.tiff.norgb");
    /**
     * YCbCr - no headroom/no footroom
     */
    static final float[] referenceBlackWhiteYCbCr_NOHead_NOFoot = new float[]{0, 255, 128, 255, 128, 255};
    /**
     * minimal pixels size of thumbnails cannot be greater than
     * {@link #_WRITE_TILES_DIMENSION}
     */
    public static int _MIN_THUMBNAILS_SIZE = 16;

    /**
     * TIFFImageWriter will create and return a TIFFDirectory metadata (IFD)
     * {@link #prepareTileWrite(boolean)}
     *
     * @param w
     * @param pmetadata
     * @param iwp
     * @param its
     * @return
     * @discussion
     * {@link http://download.java.net/media/jai-imageio/javadoc/1.1/com/sun/media/imageio/plugins/tiff/package-summary.html#EXIFStructure tiff plugin}
     */
    public static IIOMetadata _getIIOMforImageType(ImageWriter w, IIOMetadata pmetadata, ImageTypeSpecifier its, ImageWriteParam iwp) {
        IIOMetadata metadata = w.getDefaultImageMetadata(its, iwp);
        if (pmetadata != null && metadata != null) {
            if (metadata.getClass().isInstance(pmetadata)) {
                metadata = w.convertImageMetadata(pmetadata, its, iwp);
            }
        }
        if (w instanceof TIFFImageWriter) {
            TIFFTag ttagRefBW = BaselineTIFFTagSet.getInstance().getTag(BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE);
            TIFFTag ttagPhoto = BaselineTIFFTagSet.getInstance().getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
            TIFFTag ttagCoeff = BaselineTIFFTagSet.getInstance().getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS);
            TIFFDirectory tifd;
            try {
                tifd = metadata == null ? new TIFFDirectory(new TIFFTagSet[]{BaselineTIFFTagSet.getInstance()}, null) : TIFFDirectory.createFromMetadata(metadata);
                if (!_useTIFF_UnforcedRGB) {
                    tifd.removeTIFFField(ttagPhoto.getNumber());
                    tifd.addTIFFField(new TIFFField(ttagPhoto, BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB));
                }
                if (tifd.containsTIFFField(ttagPhoto.getNumber())) {
                    int photometric = tifd.getTIFFField(ttagPhoto.getNumber()).getAsInt(0);
                    float[] referenceBlackWhite;
                    float[] ycbcrCoefficients = null;
                    switch (photometric) {
                        case BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB:
                            referenceBlackWhite = _useTIFF_NOHead_NOFoot ? referenceBlackWhiteRGB_NOHead_NOFoot : referenceBlackWhiteRGB_601_1;
                            break;
                        case BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR:
                            referenceBlackWhite = _useTIFF_NOHead_NOFoot ? referenceBlackWhiteYCbCr_NOHead_NOFoot : referenceBlackWhiteYCbCr_601_1;
                            ycbcrCoefficients = _useTIFF_NOHead_NOFoot ? ycbcrCoefficients_709 : ycbcrCoefficients_601_1;
                            break;
                        default:
                            referenceBlackWhite = null;
                            break;
                    }
                    if (referenceBlackWhite != null) {
                        tifd.removeTIFFField(ttagRefBW.getNumber());
                        tifd.addTIFFField(new TIFFField(ttagRefBW, TIFFTag.TIFF_FLOAT, 6, referenceBlackWhite));
                        if (ycbcrCoefficients != null) {
                            tifd.removeTIFFField(ttagCoeff.getNumber());
                            tifd.addTIFFField(new TIFFField(ttagCoeff, TIFFTag.TIFF_FLOAT, 3, ycbcrCoefficients));
                        }
                        if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                            System.out.print("TIFFField ReferenceBlackWhite ");
                            for (float f : referenceBlackWhite) {
                                System.out.print(" " + f);
                            }
                            System.out.println();
                        }
                    }
                }
                if (_useTIFF_EXIF) {
                    TIFFTagSet exif = EXIFTIFFTagSet.getInstance();
                    tifd.addTagSet(exif);
                    tifd.addTIFFField(new TIFFField(exif.getTag(EXIFTIFFTagSet.TAG_EXIF_VERSION), TIFFTag.TIFF_UNDEFINED, 4, EXIFTIFFTagSet.EXIF_VERSION_2_2));
                }
                metadata = tifd.getAsMetadata();
            } catch (IIOInvalidTreeException ex) {
                if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class)) {
                    ex.printStackTrace();
                }
            }
        }
        return metadata;
    }

    /**
     * adds an IIOController as defined in JAI/JIIO (this is currently not used)
     *
     * @param mime the mime-type to control
     * @param iioc the parameters controller to use
     */
    public static void _addIIOController(String mime, IIOParamController iioc) {
        IIOControllers.put(mime, iioc);
    }

    /**
     * returns the current associated IIOController for the specified mime-type
     * (not used)
     *
     * @param mime the specified mime-type
     * @return the current associated IIOController for the specified mime-type
     */
    public static IIOParamController _getIIOController(String mime) {
        return IIOControllers.get(mime);
    }

    /**
     * {@link #prepareTileWrite(boolean)}
     *
     * @param type
     * @return
     */
    public static ImageTypeSpecifier _getITS(int type) {
        return ImageTypeSpecifier.createFromBufferedImageType(type);
    }

    /**
     * {@link #prepareTileWrite(boolean)}
     *
     * @param data
     * @return
     */
    public static ImageTypeSpecifier _getITS(RenderedImage data) {
        return ImageTypeSpecifier.createFromRenderedImage(data);
    }

    /**
     * {@link #prepareTileWrite(boolean)}
     *
     * @param w
     * @param pmetadata may be null and the default data is returned, otherwise
     * it is converted
     * @param iwp
     * @return ImageWriters that don't make use of stream metadata return null
     * (single-image mime-types file format).
     */
    public static IIOMetadata _getIIOMforStream(ImageWriter w, IIOMetadata pmetadata, ImageWriteParam iwp) {
        IIOMetadata metadata = w.getDefaultStreamMetadata(iwp);
        if (pmetadata != null && metadata != null) {
            if (metadata.getClass().isInstance(pmetadata)) {
                metadata = w.convertStreamMetadata(pmetadata, iwp);
            }
        }
        return metadata;
    }

    /**
     * Instances sp new BufferedImage from an image object.
     *
     * @param size dimensions
     * @param type the BufferedImage type to create
     * @return BufferedImage created
     * @see java.awt.image.BufferedImage
     */
    public static BufferedImage createBufferedImage(Dimension size, int type) {
        Dimension d = new Dimension(Math.max(1, Math.abs(size.width)), Math.max(1, Math.abs(size.height)));
        Image i = ImagePool.getInstance().findVacantImage(Sprite.BUFFERED, type, d);
        BufferedImage bdata = i == null ? new BufferedImage(d.width, d.height, type) : (BufferedImage) i;
        Graphics2D g = bdata.createGraphics();
        Color c = g.getColor();
        g.setColor(Color.WHITE);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 0.0F));
        g.fillRect(0, 0, d.width, d.height);
        g.setComposite(AlphaComposite.SrcOver);
        g.setColor(c);
        g.dispose();
        return bdata;
    }
    transient boolean IIOcontrollerEnabled = false;

    /**
     * returns the hash code for this Sprite
     */
    @Override
    public int hashCode() {
        return (int) hash;
    }

    /**
     * checks for equality of hash codes
     *
     * @param o the object instance to compare against
     */
    @Override
    public boolean equals(Object o) {
        return o != null ? hash == o.hashCode() : false;
    }
    /**
     * the image file cache directory to use
     */
    protected static String image_dir = "cache" + File.separator + "JXAimageIO";
    /*
     * SFmedia tracker
     */
    public final static SfMediaTracker _mt = new SfMediaTracker();
    /*
     * media tracker (links to the {@link #_mt SFmediatracker})
     */
    public MediaTracker mt = _mt;

    /**
     * the set of IIOReadProgressListener's
     */
    protected transient Set<IIOReadProgressListener> rProgList = Collections.synchronizedSet(new HashSet<IIOReadProgressListener>());
    /**
     * the set of IIOWriteProgressListener's
     */
    protected transient Set<IIOWriteProgressListener> wTileProgList = Collections.synchronizedSet(new HashSet<IIOWriteProgressListener>());
    /**
     * the set of IIOReadWarningListener's
     */
    protected transient Set<IIOReadWarningListener> rWarnList = Collections.synchronizedSet(new HashSet<IIOReadWarningListener>());
    /**
     * rendering hint protected transient RenderingHints rendering = new
     * RenderingHints(null);
     */
    /**
     *
     */
    protected int trackerPty = (int) hash;
    /**
     * the set of IIOWriteProgressListener's
     */
    protected transient Set<IIOWriteProgressListener> wProgList = Collections.synchronizedSet(new HashSet<IIOWriteProgressListener>());
    /**
     * the set of IIOReadProgressListener's
     */
    protected transient Set<IIOReadProgressListener> rTileProgList = Collections.synchronizedSet(new HashSet<IIOReadProgressListener>());
    /**
     * ImageObserver to avoid Garbage flushing protected Component obs;
     */
    protected transient Component obs = null;
    /**
     * the set of IIOWriteWarningListener's
     */
    protected transient Set<IIOWriteWarningListener> wWarnList = Collections.synchronizedSet(new HashSet<IIOWriteWarningListener>());

    public SpriteIO() {
    }

    protected static File _getIIOTmpDir() {
        File tmpDir;
        if (!(tmpDir = new File(FileHelper._TMPDIRECTORY.getPath() + File.separator + image_dir)).isDirectory()) {
            tmpDir.mkdirs();
            FileHelper._makeWritable(tmpDir);
        }
        return tmpDir;
    }
    /**
     * ExtensionsClassloader enforces loading Sprite resource when in resource
     * mode (a classloader issue)
     *
     * @default false.
     */
    public final static String JXA_ECLRES = "jxa.ecl.res";

    protected static boolean isExtClassLoaderRes() {
        return Boolean.getBoolean(JXA_ECLRES);
    }

    /**
     * use {@link JXAenvUtils#_BIGBUFFER_SIZE} large bufferedinput/outputstreams
     *
     * @default false
     */
    public static boolean bigBuffer = false;

    /**
     * returns sp compatible JIIO reader for the specified mime-type
     *
     * @param n the index of the reader if you want sp specific version of the
     * reader (user's savvy), default 0
     * @param mime the mime-type to look for
     * @return the ImageReader that fits the mime-type
     */
    protected static ImageReader _getReader(int n, String mime) {
        ImageReader r = null;
        IIOReadProgressAdapter rpl = new IIOReadProgressAdapter(DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID));
        IIOReadWarningAdapter rwl = new IIOReadWarningAdapter(DebugMap._getInstance().isDebuggerEnabled(Sprite.class));
        int i = 0;
        for (Iterator readers = ImageIO.getImageReadersByMIMEType(mime); readers.hasNext(); i++) {
            r = (ImageReader) readers.next();
            if (i != n) {
                continue;
            }
            r.addIIOReadProgressListener(rpl);
            r.addIIOReadWarningListener(rwl);
            if (i == n) {
                return r;
            }
            i++;
        }
        return null;
    }

    /**
     * retrieves an available ImageReader instance for this Sprite
     *
     * @param n reader index in ImageIO
     * @return ImageReader instance
     * @see #mime
     */
    protected ImageReader getReader(int n, String mime) {
        ImageReader r = _getReader(n, mime);
        if (r == null) {
            return null;
        }
        synchronized (rProgList) {
            for (Iterator<IIOReadProgressListener> it = rProgList.iterator(); it.hasNext();) {
                r.addIIOReadProgressListener(it.next());
            }
        }
        synchronized (rWarnList) {
            for (Iterator<IIOReadWarningListener> it = rWarnList.iterator(); it.hasNext();) {
                r.addIIOReadWarningListener(it.next());
            }
        }
        return r;
    }

    /**
     * returns sp specific ImageWriter for the specified mime-type
     *
     * @param n index of the ImageWriter to use (user's savvy)
     * @param mime the mime-type to look for (e.g. image/jpeg)
     * @return the requested ImageWriter
     */
    protected static ImageWriter _getWriter(int n, String mime) {
        ImageWriter w = null;
        IIOWriteProgressAdapter wpl = new IIOWriteProgressAdapter(DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID));
        IIOWriteWarningAdapter wwl = new IIOWriteWarningAdapter(DebugMap._getInstance().isDebuggerEnabled(Sprite.class));
        int i = 0;
        for (Iterator writers = ImageIO.getImageWritersByMIMEType(mime); writers.hasNext();) {
            w = (ImageWriter) writers.next();
            if (i != n) {
                continue;
            }
            w.addIIOWriteProgressListener(wpl);
            w.addIIOWriteWarningListener(wwl);
            if (i == n) {
                return w;
            }
            i++;
        }
        return null;
    }

    /**
     * retrieves an available ImageWriter instance for this Sprite
     *
     * @param n writer index in ImageIO
     * @return ImageWriter instance
     * @see #mime
     */
    protected ImageWriter getWriter(int n, String mime) {
        ImageWriter w = _getWriter(n, mime);
        if (w == null) {
            return w;
        }
        synchronized (wProgList) {
            for (Iterator<IIOWriteProgressListener> it = wProgList.iterator(); it.hasNext();) {
                w.addIIOWriteProgressListener(it.next());
            }
        }
        synchronized (wWarnList) {
            for (Iterator<IIOWriteWarningListener> it = wWarnList.iterator(); it.hasNext();) {
                w.addIIOWriteWarningListener(it.next());
            }
        }
        return w;
    }
    /**
     * String for the no source available state
     */
    protected static final String NO_SOURCE = "Offscreen Image";

    /**
     * suppress leading "/" for compliance with the classloader.getResource()
     */
    protected static String _contextResource(String src) {
        while (src.startsWith("/") && src.length() > 1) {
            src = src.substring(1);
        }
        return src;
    }

    protected static ImageReader __getInput(Object src, boolean innerResource, ImageReader r, boolean useCache) throws IOException, IllegalArgumentException {
        RandomAccessFile raf = null;
        InputStream is = null;
        File tmpDir;
        if (!(tmpDir = new File(FileHelper._TMPDIRECTORY.getPath() + File.separator + image_dir)).isDirectory()) {
            tmpDir.mkdirs();
            FileHelper._makeWritable(tmpDir);
        }
        if (src == null) {
            throw new JXAException("src is null !");
        } else {
            if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                System.out.println("New IIO Input " + (useCache ? "(may be cached)" : "(direct)") + ": " + src.getClass().getName() + " " + r.getFormatName());
            }
        }
        if (!innerResource && (src instanceof String)) {
            File inputFile = new File((String) src);
            if (!inputFile.isFile()) {
                throw new JXAException(src + " cannot be read");
            }
            raf = new RandomAccessFile(inputFile, "r");
            is = JXAenvUtils2.__getBuffered(new FileInputStream(raf.getFD()), bigBuffer);
            if (useCache) {
                r.setInput(new FileCacheImageInputStream(is, tmpDir));
            } else {
                r.setInput(ImageIO.createImageInputStream(is));
            }
        } else if (src instanceof ImageInputStream) {
            r.setInput(src);
        } else if (src instanceof InputStream) {
            is = JXAenvUtils2.__getBuffered((InputStream) src, bigBuffer);
            if (useCache) {
                r.setInput(new FileCacheImageInputStream(is, tmpDir));
            } else {
                r.setInput(ImageIO.createImageInputStream(is));
            }
        } else if (src instanceof String) {
            if (!src.equals(NO_SOURCE)) {
                if (!isExtClassLoaderRes()) {
                    is = JXAenvUtils2.__getBuffered(Sprite.class.getResourceAsStream((String) src), bigBuffer);
                } else {
                    is = JXAenvUtils2.__getBuffered(ExtensionsClassLoader.getInstance().getClassLoader().getResourceAsStream(_contextResource((String) src)), bigBuffer); /*
                     * Thread.currentThread().getContextClassLoader().getResourceAsStream(_contextResource((String)
                     * src));
                     */

                }
                if (useCache) {
                    r.setInput(new FileCacheImageInputStream(is, tmpDir));
                } else {
                    r.setInput(ImageIO.createImageInputStream(is));
                }
            } else {
                throw new JXAException("reading is not supported from " + src);
            }
        } else if (src instanceof File) {
            raf = new RandomAccessFile((File) src, "r");
            is = JXAenvUtils2.__getBuffered(new FileInputStream(raf.getFD()), bigBuffer);
            if (useCache) {
                r.setInput(new FileCacheImageInputStream(is, tmpDir));
            } else {
                r.setInput(ImageIO.createImageInputStream(is));
            }
        } else {
            throw new JXAException(src.getClass() + " input is not supported");
        }
        RefPool.getInstance().queueRef(is, false);
        return r;
    }

    private static ImageWriter __getOutput(Object dst, ImageWriter w, boolean useCache) throws IOException {
        RandomAccessFile raf = null;
        OutputStream os = null;
        File tmpDir = _getIIOTmpDir();
        if (dst == null) {
            throw new JXAException("dst is not supported : null");
        } else {
            if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                System.out.println("New IIO Output " + (useCache ? "(may be cached)" : "(direct)") + ": " + dst.getClass().getName() + " " + w.getOriginatingProvider().getFormatNames()[0]);
            }
        }
        if (dst instanceof String) {
            File outputFile = new File((String) dst);
            raf = new RandomAccessFile(outputFile, "rw");
            os = JXAenvUtils2.__getBuffered(new FileOutputStream(raf.getFD()), bigBuffer);
            if (useCache) {
                w.setOutput(new FileCacheImageOutputStream(os, tmpDir));
            } else {
                w.setOutput(ImageIO.createImageOutputStream(os));
            }
        } else if (dst instanceof OutputStream) {
            os = JXAenvUtils2.__getBuffered((OutputStream) dst, bigBuffer);
            if (useCache) {
                w.setOutput(new FileCacheImageOutputStream(os, tmpDir));
            } else {
                w.setOutput(ImageIO.createImageOutputStream(os));
            }
        } else if (dst instanceof File) {
            raf = new RandomAccessFile((File) dst, "rw");
            os = JXAenvUtils2.__getBuffered(new FileOutputStream(raf.getFD()), bigBuffer);
            if (useCache) {
                w.setOutput(new FileCacheImageOutputStream(os, tmpDir));
            } else {
                w.setOutput(ImageIO.createImageOutputStream(os));
            }
        } else if (dst instanceof ImageOutputStream) {
            w.setOutput(dst);
        } else {
            throw new JXAException(dst.getClass() + " output is not supported");
        }
        RefPool.getInstance().queueRef(os, false);
        return w;
    }

    /**
     * DOES NOT WORK WITH IMAGEPRODUCER AS {@linkplain #getSource() SOURCE}
     */
    protected Dimension getNumTilesXY(ImageReader r) {
        Dimension tiles = _WRITE_TILES_DIMENSION;
        try {
            Dimension tiledImage = new Dimension(r.getWidth(0), r.getHeight(0));
            final int tilesX = (int) Math.ceil((float) tiledImage.width / (float) tiles.width);
            final int tilesY = (int) Math.ceil((float) tiledImage.height / (float) tiles.height);
            if (tilesX <= 0 || tilesY <= 0) {
                if (isDebugEnabled() && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                    System.err.println("Tiles are 1 to 1 " + tiledImage + " = " + tiles);
                }
                return new Dimension(1, 1);
            }
            return new Dimension(tilesX, tilesY);
        } catch (IOException ex) {
            if (isDebugEnabled()) {
                ex.printStackTrace();
            }
            return new Dimension(1, 1);
        }
    }

    /**
     * @param output must be a compatible output stream or file.
     * @return a bitwise combination of the _WRITE_SEQUENCE, _WRITE_INSERT,
     * _WRITE_REPLACE
     * @see #endWrite(javax.imageio.ImageWriter, boolean)
     * @throws JXAException if the output is not compatible.
     */
    public int prepareWrite(Dimension outputSize, ImageWriter w, ImageTypeSpecifier its, ImageWriteParam iwp, boolean useCache, Object output, Image data, int _type) throws IOException, InterruptedException {
        return _prepareWrite(outputSize, w, its, iwp, useCache, output, data, _type);
    }

    /**
     * Writer capabilities Flags.
     */
    public final static int _WRITE_SEQUENCE = 0x1, _WRITE_INSERT = 0x2, _WRITE_REPLACE = 0x4;

    /**
     * @param readerInput must be filled with an input already
     * @return a bitwise combination of the {@link #_WRITE_SEQUENCE}, {@link _WRITE_INSERT},
     * {@link #_WRITE_REPLACE} that is available (prepareWriteSequence is
     * already called in this case) or 0 if none functionality is available.
     * @see #endWrite(javax.imageio.ImageWriter, boolean)
     * @throws JXAException if the output is not compatible.
     */
    public int prepareWrite(Dimension outputSize, ImageWriter w, ImageTypeSpecifier its, ImageWriteParam iwp, boolean useCache, Object output, ImageReader readerInput, int _type) throws IOException, InterruptedException {
        return _prepareWrite(outputSize, w, its, iwp, useCache, output, readerInput, _type);
    }

    private transient ThreadBlockData<Integer> writeBlock = new ThreadBlockData<Integer>(0);

    private int _prepareWrite(Dimension outputSize, ImageWriter w, ImageTypeSpecifier its, ImageWriteParam iwp, boolean useCache, Object output, Object dataSource, int _type) throws IOException, InterruptedException {
        int ret = 0;
        writeBlock.begin();
        w = __getOutput(output, w, useCache);
        IIOMetadata metadata = dataSource instanceof ImageReader ? ((ImageReader) dataSource).getImageMetadata(0) : null;
        metadata = metadata instanceof IIOMetadata ? _getIIOMforImageType(w, metadata, its, iwp) : _getIIOMforDefaultImage(w, its, iwp);
        IIOMetadata streamMetadata = dataSource instanceof ImageReader ? ((ImageReader) dataSource).getStreamMetadata() : null;
        if (w.canWriteSequence()) {
            ret |= _WRITE_SEQUENCE;
            notifyIIOWriteListenersProgress(wTileProgList, w, 0);
            w.prepareWriteSequence(_getIIOMforStream(w, streamMetadata, iwp));
            if (w.canInsertEmpty(-1)) {
                ret |= _WRITE_INSERT;
                w.prepareInsertEmpty(-1, its, outputSize.width, outputSize.height, metadata,
                        null, /*
                         * thumbnail (has to be appended after IFD)
                         */
                        iwp);
                w.endInsertEmpty();
                ret |= w.canReplacePixels(0) ? _WRITE_REPLACE : 0;
                if (_useTIFF_EXIF && dataSource instanceof ImageReader) {
                    List<BufferedImage> thumbnails = getThumbnails(((ImageReader) dataSource), _MIN_THUMBNAILS_SIZE, _type);
                    if (!thumbnails.isEmpty()) {
                        w.writeToSequence(new IIOImage(thumbnails.get(0), null, _getIIOMforDefaultImage(w, _getITS(thumbnails.get(0)), iwp)), iwp);
                    }
                }
            }
        }
        /**
         * register in Threadblock the data of the writer flags
         */
        writeBlock.setTdata(ret);
        return ret;
    }

    /**
     * ends upon a write block started with {@link #prepareWrite(java.awt.Dimension, javax.imageio.ImageWriter, javax.imageio.ImageTypeSpecifier, javax.imageio.ImageWriteParam, boolean, java.lang.Object, java.awt.Image)
     * } or {@link #prepareWrite(java.awt.Dimension, javax.imageio.ImageWriter, javax.imageio.ImageTypeSpecifier, javax.imageio.ImageWriteParam, boolean, java.lang.Object, javax.imageio.ImageReader)
     * <br><b>Closes any open stream specified as output after the write
     * finishes.</b>
     */
    public void endWrite(ImageWriter w) throws IOException {
        if (!writeBlock.isOn()) {
            throw new JXAException(JXAException.LEVEL.SYSTEM, "not in write code block, use prepareWrite()-or-prepareTileWrite() before");
        }
        if (w.canWriteSequence() && (writeBlock.getTdata() & _WRITE_SEQUENCE) != 0) {
            w.endWriteSequence();
        }
        writeBlock.removeTdata();
        notifyIIOWriteListenersComplete(
                wTileProgList, w);
        ((ImageOutputStream) w.getOutput()).flush();
        ((ImageOutputStream) w.getOutput()).close();
        w.dispose();
        writeBlock.end();
    }

    /**
     * write to ImageWrite output from a RenderedImage input
     *
     * @param imgMetadata image metadata that can be obtained from the
     * ImageReader or with
     * {@link #_getIIOMforImageType(javax.imageio.ImageWriter, javax.imageio.metadata.IIOMetadata, javax.imageio.ImageTypeSpecifier, javax.imageio.ImageWriteParam) IIOMforImage..()}.
     * @param strMetadata stream metadata, that can be obtained from the
     * ImageReader or let it null. Default IIOM. is used in that case.
     */
    public void writeToOutput(IIOMetadata imgMetadata, IIOMetadata strMetadata, ImageWriter w, ImageWriteParam iwp, RenderedImage ndata) throws IOException, InterruptedException {
        if (!writeBlock.isOn()) {
            throw new JXAException(JXAException.LEVEL.SYSTEM, "not in write code block, use prepareWrite() before");
        }
        /**
         * untiled picture
         */
        IIOImage iioimage = new IIOImage((RenderedImage) ndata, null, imgMetadata);
        if (w.canWriteSequence()) {
            w.writeToSequence(iioimage, iwp);
        } else {
            w.write(_getIIOMforStream(w, strMetadata, iwp), iioimage, iwp);
        }
    }

    /**
     * write to ImageWrite output from ImageReader input, the output may be a
     * sequence of image and thus will append the image that is read.
     * <br> write to the output untiled
     *
     * @param isize input and output size (unmutable size)
     */
    public void writeToOutput(Dimension isize, ImageWriter w, ImageWriteParam iwp, ImageReader r, int _type, Object baseTransform) throws IOException, InterruptedException {
        writeToOutput(isize, w, iwp, r, _type, 0, baseTransform);
    }

    /**
     * write to ImageWrite output from ImageReader input, the output may be a
     * sequence of image and thus will append the image that is read at the
     * specified index.
     * <br> write (append if a sequence is possible) to the output untiled
     *
     * @param isize input and output size (unmutable size)
     * @param imageIndex index of the image to read in the input stream
     */
    public void writeToOutput(Dimension isize, ImageWriter w, ImageWriteParam iwp, ImageReader r, int _type, int imageIndex, Object baseTransform) throws IOException, InterruptedException {
        if (!writeBlock.isOn()) {
            throw new JXAException(JXAException.LEVEL.SYSTEM, "not in write code block, use prepareWrite() before");
        }
        IIOMetadata metadata = r.getImageMetadata(0);
        metadata = metadata instanceof IIOMetadata ? _getIIOMforImageType(w, metadata, _getITS(_type), iwp) : _getIIOMforDefaultImage(w, _getITS(_type), iwp);
        RenderedImage dataDst;
        BufferedImage i;
        i = r.read(imageIndex, _getIRP(r, _type));
        trackImage(trackerPty, i);
        waitFor(trackerPty);
        untrackImage(trackerPty, i);
        if (baseTransform instanceof PerspectiveTransform) {
            ParameterBlock pb = new ParameterBlock();
            pb.addSource(i);
            /**
             * add scale to specified size for the current data size to handle
             * correct data transform see UP ^^
             */
            pb.add(new WarpPerspective((PerspectiveTransform) baseTransform));
            pb.add(Interpolation.getInstance(Interpolation.INTERP_NEAREST));
            RenderedOp warpOp = JAI.create("warp", pb);
            dataDst = (RenderedImage) warpOp.createInstance();
        } else {
            if (baseTransform == null) {
                baseTransform = new AffineTransform();
            }
            dataDst = createBufferedImage(isize, _type);
            Graphics dataG = Sprite._createImageGraphics((BufferedImage) dataDst);
            Graphics2D g = Sprite.wrapRendering(dataG);
            g.drawRenderedImage(i, (AffineTransform) baseTransform);
            g.dispose();
            ((BufferedImage) dataDst).flush();
        }
        i.flush();
        writeToOutput(metadata, r.getStreamMetadata(), w, iwp, dataDst);
    }

    /**
     * write to ImageWrite output from ImageReader input
     * <br> {@link #prepareWrite(java.awt.Dimension, javax.imageio.ImageWriter, javax.imageio.ImageTypeSpecifier, javax.imageio.ImageWriteParam, boolean, java.lang.Object, javax.imageio.ImageReader)
     * } must have returned true, for a sequence of image data is going to be
     * written to the output.
     *
     * @param isize input and output size (unmutable size)
     * @param tilesSize tile image width and height (may not be smaller that
     * {@link #_WRITE_TILES_DIMENSION})
     * @param w
     * @param iwp
     * @param r
     * @param baseTransform
     * @throws java.io.IOException
     * @throws java.lang.InterruptedException
     */
    public void writeToOutputTiled(Dimension isize, Dimension tilesSize, ImageWriter w, ImageWriteParam iwp, ImageReader r, int _type, Object baseTransform) throws IOException, InterruptedException {
        /**
         * it is a tiled picture
         */
        Dimension numTiles = getNumTilesXY(r);
        ImageReadParam irp = _getIRP(r, _type);
        /*
         * NEVER ! w.prepareReplacePixels(0, new
         * Rectangle(dim));
         */
        for (int y = 0; y < numTiles.height; y++) {
            for (int x = 0; x < numTiles.width; x++) {
                Rectangle sroi = new Rectangle(x * tilesSize.width, y * tilesSize.height, tilesSize.width, tilesSize.height).intersection(new Rectangle(isize));
                if (sroi.isEmpty()) {
                    continue;
                }
                irp.setSourceRegion(sroi);
                BufferedImage b = r.read(0, irp);
                if (b.getType() != _type) {
                    b = _convertToBuffered(b, _type, obs, true);
                }
                trackImage(trackerPty, b);
                waitFor(
                        trackerPty);
                untrackImage(trackerPty, b);
                Rectangle replace = new Rectangle(x * tilesSize.width, y * tilesSize.height, tilesSize.width, tilesSize.height).intersection(new Rectangle(isize));
                iwp.setDestinationOffset(replace.getLocation());
                /**
                 * it's actually the destination rectangle size
                 */
                iwp.setSourceRegion(new Rectangle(replace.getSize()));
                w.prepareReplacePixels(0, replace);
                w.replacePixels(b, iwp);
                w.endReplacePixels();
                b.flush();
                notifyIIOWriteListenersProgress(
                        wTileProgList, w, (float) (y * numTiles.width + x) / (float) (numTiles.width * numTiles.height));
            }
        }
    }

    static {
        DebugMap._getInstance().associateDebugLevel(SpriteIO.class, Sprite.DBUG_RENDER_LOW);
    }

    public boolean isDebugEnabled() {
        return DebugMap._getInstance().isDebuggerEnabled(SpriteIO.class);
    }

    public void setDebugEnabled(boolean b) {
        DebugMap._getInstance().setDebuggerEnabled(b, SpriteIO.class);
    }

    /**
     *
     * @param l
     * @param source
     * @param index
     */
    public static void notifyIIOWriteListenersStarted(Set<IIOWriteProgressListener> l, ImageWriter source, int index) {
        synchronized (l) {
            for (Iterator<IIOWriteProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageStarted(source, index);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     * @param percentageDone
     */
    public static void notifyIIOWriteListenersProgress(Set<IIOWriteProgressListener> l, ImageWriter source, float percentageDone) {
        synchronized (l) {
            for (Iterator<IIOWriteProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageProgress(source, percentageDone);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     */
    public static void notifyIIOWriteListenersComplete(Set<IIOWriteProgressListener> l, ImageWriter source) {
        synchronized (l) {
            for (Iterator<IIOWriteProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageComplete(source);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     */
    public static void notifyIIOWriteListenersAborted(Set<IIOWriteProgressListener> l, ImageWriter source) {
        synchronized (l) {
            for (Iterator<IIOWriteProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().writeAborted(source);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     * @param index
     */
    public static void notifyIIOReadListenersStarted(Set<IIOReadProgressListener> l, ImageReader source, int index) {
        synchronized (l) {
            for (Iterator<IIOReadProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageStarted(source, index);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     * @param percentageDone
     */
    public static void notifyIIOReadListenersProgress(Set<IIOReadProgressListener> l, ImageReader source, float percentageDone) {
        synchronized (l) {
            for (Iterator<IIOReadProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageProgress(source, percentageDone);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     */
    public static void notifyIIOReadListenersComplete(Set<IIOReadProgressListener> l, ImageReader source) {
        synchronized (l) {
            for (Iterator<IIOReadProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().imageComplete(source);
            }
        }
    }

    /**
     *
     * @param l
     * @param source
     */
    public static void notifyIIOReadListenersAborted(Set<IIOReadProgressListener> l, ImageReader source) {
        synchronized (l) {
            for (Iterator<IIOReadProgressListener> it = l.iterator(); it.hasNext();) {
                it.next().readAborted(source);
            }
        }
    }

    /**
     * TIFFImageWriter will create and return a TIFFDirectory metadata (IFD)
     * {@link #prepareTileWrite(boolean)}
     *
     * @param w
     * @param its
     * @param iwp
     * @return
     * @discussion <a
     * href="http://download.java.net/media/jai-imageio/javadoc/1.1/com/sun/media/imageio/plugins/tiff/package-summary.html#EXIFStructure"/>tiff
     * plugin</a>
     */
    public static IIOMetadata _getIIOMforDefaultImage(ImageWriter w, ImageTypeSpecifier its, ImageWriteParam iwp) {
        return _getIIOMforImageType(w, null, its, iwp);
    }

    /**
     * @return default param and correct destinationtype to match bufferedType
     * @param bufferedType it will be attempted to match the specified
     * bufferedtype at reading, but it is not guarranteed that the resulting
     * BufferedImage has the specified type
     * @see ImageReader#getImageTypes(int)
     */
    protected static ImageReadParam _getIRP(ImageReader r, int bufferedType) {
        ImageReadParam irp = r.getDefaultReadParam();
        ImageTypeSpecifier itsDef = _getITS(bufferedType);
        if (r.getInput() != null) {
            try {
                irp.setDestinationType(r.getRawImageType(0));
                for (Iterator<ImageTypeSpecifier> it = r.getImageTypes(0); it.hasNext();) {
                    ImageTypeSpecifier its = it.next();
                    if (its.equals(itsDef)) {
                        irp.setDestinationType(its);
                        break;
                    }
                }
            } catch (Throwable ex) {
                if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class)) {
                    ex.printStackTrace();
                }
            }
        }
        if (irp instanceof TIFFImageReadParam) {
            if (_useTIFF_EXIF) {
                ((TIFFImageReadParam) irp).addAllowedTagSet(EXIFTIFFTagSet.getInstance());
            }
            if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class) && irp.getDestinationType() != null) {
                try {
                    System.out.println("imagereader will use " + ImageCollection.BUFFERED_TYPE.valueOf(irp.getDestinationType().getBufferedImageType()) + " for " + r.getFormatName());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return irp;
    }

    protected static ImageWriteParam _getIWP(ImageWriter w, Dimension srcDim, String mime, int bufferedType, float compressionQuality) {
        ImageWriteParam iwp = w.getDefaultWriteParam();
        boolean found = false;
        for (String m : w.getOriginatingProvider().getMIMETypes()) {
            if (m.equals(mime)) {
                found = true;
                break;
            }
        }
        if (!found) {
            throw new JXAException("incompatible mime type specified " + mime + " for writer " + w.toString());
        }
        iwp.setDestinationType(_getITS(bufferedType));
        if (iwp.canWriteTiles()) {
            /*
             * if (_WRITE_TILES_DIMENSION.width < srcDim.width ||
             * _WRITE_TILES_DIMENSION.height < srcDim.height) {
             */
            /*
             * iwp.setTilingMode(iwp.MODE_EXPLICIT);
             * iwp.setTiling(_WRITE_TILES_DIMENSION.width,
             * _WRITE_TILES_DIMENSION.height, 0, 0);
             */
            /*
             * } else { iwp.setTilingMode(iwp.MODE_DISABLED); }
             */
        }
        if (iwp.canWriteCompressed()) {
            String css = ImageCollection._getCompressionType(mime, bufferedType);
            try {
                if (css != null) {
                    if (compressionQuality >= 0f) {
                        iwp.setCompressionMode(iwp.MODE_EXPLICIT);
                        iwp.setCompressionType(css);
                        iwp.setCompressionQuality(compressionQuality);
                    } else {
                        iwp.setCompressionMode(iwp.MODE_COPY_FROM_METADATA);
                    }
                } else {
                    iwp.setCompressionMode(iwp.MODE_DISABLED);
                }
            } catch (RuntimeException ex) {
                if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class)) {
                    ex.printStackTrace();
                }
                try {
                    iwp.setCompressionMode(iwp.MODE_DEFAULT);
                } catch (RuntimeException ex2) {
                    if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class)) {
                        ex.printStackTrace();
                    }
                }
            }
        }

        if (DebugMap._getInstance().isDebuggerEnabled(Sprite.class)) {
            System.out.print("imagewriter will use " + ImageCollection.BUFFERED_TYPE.valueOf(iwp.getDestinationType().getBufferedImageType()) + " for " + w.getOriginatingProvider().getFormatNames()[0]);
            if (iwp.canWriteCompressed()) {
                switch (iwp.getCompressionMode()) {
                    case ImageWriteParam.MODE_EXPLICIT:
                        System.out.println(" w/ " + iwp.getLocalizedCompressionTypeName());
                        break;
                    case ImageWriteParam.MODE_DEFAULT:
                        System.out.println(" w/ default compression.");
                        break;
                    default:
                        System.out.println(" w/o compressing.");
                        break;
                }
            } else {
                System.out.println(" uncompressed.");
            }
        }
        return iwp;
    }

    /**
     * wait for the data to be loaded with the mediatracker
     *
     * @throws InterruptedException
     */
    protected void waitFor(Image data) throws InterruptedException {
        InterruptedException interrupted = null;
        if (data != null) {
            trackImage(trackerPty, data);
        }
        try {
            waitFor(trackerPty);
        } catch (InterruptedException ex) {
            interrupted = ex;
        } finally {
            if (data != null) {
                untrackImage(trackerPty, data);
            }
            if (interrupted != null) {
                throw interrupted;
            }
        }
    }

    /**
     * waits for the image data to load completely
     *
     * @param id the id of the data in the MediaTracker
     * @see #setTrackerPty(int)
     * @see MediaTracker#waitForId(int)
     */
    protected void waitFor(int id) throws InterruptedException {
        /*if (load) {*/
        while (!mt.checkID(id)) {
            mt.waitForID(id, 10);
        }
        if (!mt.isErrorID(id)) {
            if (isDebugEnabled() && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                System.out.println(toString() + " is loaded, mt-id " + id + ".");
            }
        } else {
            if (isDebugEnabled() && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
                System.err.println(toString() + " has error(s), mt-id " + id + ".");
            }/*
             clearResource();
             }*/

        }
    }

    /**
     * Tracks the image for loading with the current MediaTracker.
     *
     * @param id the id to set up in the MediaTracker
     * @param dat the Image instance to add to the MediaTracker
     * @see #setTrackerPty(int)
     */
    protected void untrackImage(int id, Image data) {
        if (data != null) {
            mt.removeImage(data, id);
        }
    }

    /**
     * Tracks the image for loading with the current MediaTracker. (CAUTION :
     * don't forget to {@link #untrack(int, image)} after completion of loading,
     * or the image will rest in heap memory)
     *
     * @param id the id to set up in the MediaTracker
     * @param dat the Image instance to add to the MediaTracker
     * @see #setTrackerPty(int)
     */
    protected void trackImage(int id, Image data) {
        if (data != null) {
            mt.addImage(data, id);
            ImagePool.getInstance().queueImage(data, false);
            data.setAccelerationPriority(1.0F);
        } else if (isDebugEnabled() && DebugMap._getInstance().isDebugLevelEnabled(DebugMap._getInstance()._VOID)) {
            System.out.println(" no data to track !");
        }
        ImagePool.getInstance().cleanup();
    }

    protected BufferedImage _convertToBuffered(Object data, int _type, Component pobs, boolean flush) throws InterruptedException {
        this.obs = pobs;
        BufferedImage bdata = null;
        if (data == null) {
            if (isDebugEnabled()) {
                System.err.println("no data to convert " + toString());
            }
            return null;
        }
        if (data instanceof Image) {
            trackImage(trackerPty, (Image) data);
            waitFor(trackerPty);
            untrackImage(trackerPty, (Image) data);
        }
        Dimension dim = new Dimension();
        if (data instanceof RenderedImage) {
            dim = new Dimension(((RenderedImage) data).getWidth(), ((RenderedImage) data).getHeight());
        } else {
            dim = new Dimension(((Image) data).getWidth(obs), ((Image) data).getHeight(obs));
        }
        bdata = createBufferedImage(dim, _type);
        Graphics dataG = Sprite._createImageGraphics(bdata);
        Graphics2D g = Sprite.wrapRendering(dataG);
        if (data instanceof RenderedImage) {
            g.drawRenderedImage((RenderedImage) data, new AffineTransform());
        } else {
            g.drawImage((Image) data, new AffineTransform(), obs);
        }
        dataG.dispose();
        if (data instanceof Image) {
            if (flush) {
                ((Image) data).flush();
            }
        }
        return bdata;
    }

    /**
     * attempt to retrieve thumbnails, or create one with the reader data
     *
     * @param r
     * @param minSize min size for thumbnails, if it appears that the source
     * picture is smaller or equal to that size, no thumbnail should be
     * returned.
     * @param bufferedType target type
     * @return
     * @throws IOException
     */
    protected List<BufferedImage> getThumbnails(ImageReader r, int minSize, int bufferedType) throws IOException, InterruptedException {
        List<BufferedImage> thumbnails = Collections.synchronizedList(new ArrayList<BufferedImage>());
        /*
         * return thumbnails;
         */
        ImageReadParam irp = _getIRP(r, bufferedType);
        Dimension dim = new Dimension(r.getWidth(0), r.getHeight(0));
        Dimension thumbs = _WRITE_TILES_DIMENSION;
        while ((thumbs.width >= dim.width || thumbs.height >= dim.height) && thumbs.width > minSize && thumbs.height > minSize) {
            thumbs = new Dimension((int) Math.max(minSize, thumbs.width / 4.), (int) Math.max(minSize, thumbs.height / 4.));
        }
        thumbs.height = Math.max(1, Math.round(thumbs.width / r.getAspectRatio(0)));
        if (thumbs.equals(dim)) {
            return thumbnails;
        }
        BufferedImage im = null;
        if (r.hasThumbnails(0)) {
            for (int i = 0; i < r.getNumThumbnails(0); i++) {
                thumbnails.add(im = r.readThumbnail(0, i));
                mt.addImage(im, 0);
                mt.waitForID(0);
                mt.removeImage(im, 0);
            }
        } else if (r.getNumImages(true) > 1 && r instanceof TIFFImageReader) {
            thumbnails.add(im = r.read(1, irp));
            mt.addImage(im, 0);
            mt.waitForID(0);
            mt.removeImage(im, 0);
        } else {
            if (irp.canSetSourceRenderSize()) {
                irp.setSourceRenderSize(thumbs);
            } else {
                int x = Math.round((dim.width - thumbs.width) / 2f);
                int y = Math.round((dim.height - thumbs.height) / 2f);
                irp.setSourceRegion(new Rectangle(x, y, thumbs.width, thumbs.height));
            }
            thumbnails.add(im = r.read(0, irp));
            mt.addImage(im, 0);
            mt.waitForID(0);
            mt.removeImage(im, 0);
        }
        for (int i = 0; i < thumbnails.size(); i++) {
            BufferedImage b = thumbnails.get(i);
            if (b.getType() != bufferedType) {
                thumbnails.set(i, _convertToBuffered((RenderedImage) b, bufferedType, obs, true));
            }
        }
        return thumbnails;
    }

    /**
     * removes an IIOWriteProgressListener from this Sprite instance
     *
     * @param l the listener that will be removed from the listeners set
     */
    public void removeIIOTileWriteProgressListener(IIOWriteProgressListener l) {
        wTileProgList.remove(l);
    }

    /**
     * removes an IIOReadProgressListener from this Sprite instance
     *
     * @param l the listener instance that will be removed from the listeners
     * set
     */
    public void removeIIOTileReadProgressListener(IIOReadProgressListener l) {
        rTileProgList.remove(l);
    }

    /**
     * adds an IIOReadProgressListener to this Sprite instance
     *
     * @param l the listener instance that will listen to each read operation
     * progress
     */
    public void addIIOReadProgressListener(IIOReadProgressListener l) {
        rProgList.add(l);
    }

    /**
     * removes an IIOWriteProgressListener from this Sprite instance
     *
     * @param l the listener that will be removed from the listeners set
     */
    public void removeIIOWriteProgressListener(IIOWriteProgressListener l) {
        wProgList.remove(l);
    }

    /**
     * removes an IIOReadWarningListener from this Sprite instance
     *
     * @param l the listener instance that will be removed from the listeners
     * set
     */
    public void removeIIOReadWarningListener(IIOReadWarningListener l) {
        rWarnList.remove(l);
    }

    /**
     * removes an IIOWriteWarningListener from this Sprite instance
     *
     * @param l the listener that will be removed from the listeners set
     */
    public void removeIIOWriteWarningListener(IIOWriteWarningListener l) {
        wWarnList.remove(l);
    }

    /**
     * adds an IIOWriteWarningListener to this Sprite instance
     *
     * @param l the listener that will listen to each write oparation warning
     */
    public void addIIOWriteWarningListener(IIOWriteWarningListener l) {
        wWarnList.add(l);
    }

    /**
     * returns true or false, whether the IIOController is enabled or not, resp.
     * if available. (not used)
     *
     * @return true or false, whether the IIOController should be enabled or
     * not, resp.
     */
    public boolean isIIOcontrollerEnabled() {
        return IIOcontrollerEnabled;
    }

    /**
     * adds an IIOWriteProgressListener to this Sprite instance
     *
     * @param l the listener that will listen to each write operation progress
     * (tile mode muste be enabled and image/tiff must be the
     * {@link #getStoreMime() store mime type})
     */
    public void addIIOTileWriteProgressListener(IIOWriteProgressListener l) {
        wTileProgList.add(l);
    }

    /**
     * adds an IIOReadWarninListener to this Sprite instance
     *
     * @param l the listener instance that will listen to each read operation
     * warning
     */
    public void addIIOReadWarningListener(IIOReadWarningListener l) {
        rWarnList.add(l);
    }

    /**
     * removes an IIOReadProgressListener from this Sprite instance
     *
     * @param l the listener instance that will be removed from the listeners
     * set
     */
    public void removeIIOReadProgressListener(IIOReadProgressListener l) {
        rProgList.remove(l);
    }

    /**
     * adds an IIOReadProgressListener to this Sprite instance
     *
     * @param l the listener instance that will listen to each tile read
     * operation progress (tile mode must be enabled)
     */
    public void addIIOTileReadProgressListener(IIOReadProgressListener l) {
        rTileProgList.add(l);
    }

    /**
     * adds an IIOWriteProgressListener to this Sprite instance
     *
     * @param l the listener that will listen to each write operation progress
     */
    public void addIIOWriteProgressListener(IIOWriteProgressListener l) {
        wProgList.add(l);
    }

    /**
     * dis/enables the IIOController for this Sprite instance (this is currently
     * not used)
     *
     * @param IIOcontrollerEnabled dis/enables the IIOController
     */
    public void setIIOcontrollerEnabled(boolean IIOcontrollerEnabled) {
        this.IIOcontrollerEnabled = IIOcontrollerEnabled;
    }

}
TOP

Related Classes of net.sf.jiga.xtended.impl.SpriteIO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.