Example usage for javax.imageio IIOImage IIOImage

List of usage examples for javax.imageio IIOImage IIOImage

Introduction

In this page you can find the example usage for javax.imageio IIOImage IIOImage.

Prototype

public IIOImage(Raster raster, List<? extends BufferedImage> thumbnails, IIOMetadata metadata) 

Source Link

Document

Constructs an IIOImage containing a Raster , and thumbnails and metadata associated with it.

Usage

From source file:org.deegree.securityproxy.wms.responsefilter.clipping.SimpleRasterClipper.java

private void writeImage(OutputStream destination, String format, BufferedImage outputImage)
        throws ClippingException, IOException {
    ImageWriter imageWriter = createImageWriter(format);
    ImageWriteParam writerParam = configureWriterParameters(format, imageWriter);
    imageWriter.setOutput(ImageIO.createImageOutputStream(destination));
    imageWriter.write(null, new IIOImage(outputImage, null, null), writerParam);
    imageWriter.dispose();//from  w  ww  .  j av a  2s  .c o  m
}

From source file:org.eclipse.birt.chart.device.svg.SVGGraphics2D.java

private Element createEmbeddeImage(BufferedImage img) {
    if (img == null) {
        return null;
    }/*w  w w.  ja v a2  s.com*/

    int width = img.getWidth();
    int height = img.getHeight();
    ImageWriter iw = ImageWriterFactory.instance().createByFormatName("png"); //$NON-NLS-1$
    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192 * 2);
    String sUrl = null;
    try {
        final ImageOutputStream ios = SecurityUtil.newImageOutputStream(baos);
        ImageWriteParam iwp = iw.getDefaultWriteParam();
        iw.setOutput(ios);
        iw.write((IIOMetadata) null, new IIOImage(img, null, null), iwp);
        img.flush();
        ios.close();
        sUrl = SVGImage.BASE64 + new String(Base64.encodeBase64(baos.toByteArray()));
    } catch (Exception ex) {
        logger.log(ex);
    } finally {
        iw.dispose();
    }

    Element elemG = dom.createElement("g"); //$NON-NLS-1$
    elemG.setAttribute("id", "img_" + img.hashCode()); //$NON-NLS-1$//$NON-NLS-2$
    Element elem = dom.createElement("image"); //$NON-NLS-1$
    elem.setAttribute("x", "0"); //$NON-NLS-1$//$NON-NLS-2$
    elem.setAttribute("y", "0"); //$NON-NLS-1$ //$NON-NLS-2$
    elem.setAttribute("width", Integer.toString(width)); //$NON-NLS-1$
    elem.setAttribute("height", Integer.toString(height)); //$NON-NLS-1$
    elem.setAttribute("xlink:href", sUrl); //$NON-NLS-1$
    elemG.appendChild(elem);

    return elemG;
}

From source file:org.eclipse.birt.chart.device.svg.SVGImage.java

public SVGImage(Image image, URL url, byte[] data) {
    super();/*  w  w  w  .  ja  va  2 s  .c o m*/
    this.image = image;
    this.url = url;
    this.data = data;
    if (url == null && data == null && image instanceof BufferedImage) {
        ImageWriter iw = ImageWriterFactory.instance().createImageWriter("png", "html"); //$NON-NLS-1$ //$NON-NLS-2$

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
            ImageOutputStream ios = SecurityUtil.newImageOutputStream(baos);
            ImageWriteParam iwp = iw.getDefaultWriteParam();
            iw.setOutput(ios);
            iw.write((IIOMetadata) null, new IIOImage((BufferedImage) image, null, null), iwp);
            ios.close();
            this.data = baos.toByteArray();
            baos.close();
        } catch (IOException e) {
            // do nothing
        } finally {
            iw.dispose();
        }

    }
}

From source file:org.egov.infra.utils.ImageUtils.java

public static File compressImage(final InputStream imageStream, String imageFileName, boolean closeStream)
        throws IOException {
    File compressedImage = Paths.get(imageFileName).toFile();
    try (final ImageOutputStream imageOutput = createImageOutputStream(compressedImage)) {
        ImageWriter writer = getImageWritersByFormatName(
                defaultString(getExtension(imageFileName), JPG_FORMAT_NAME)).next();
        writer.setOutput(imageOutput);/*from   w  ww. java2 s. co  m*/
        ImageWriteParam writeParam = writer.getDefaultWriteParam();
        if (writeParam.canWriteCompressed()) {
            writeParam.setCompressionMode(MODE_EXPLICIT);
            writeParam.setCompressionType(writeParam.getCompressionTypes()[0]);
            writeParam.setCompressionQuality(0.05F);
        }
        writer.write(null, new IIOImage(read(imageStream), null, null), writeParam);
        writer.dispose();
        if (closeStream)
            imageStream.close();
    }
    return compressedImage;
}

From source file:org.egov.works.abstractestimate.service.EstimatePhotographService.java

public File compressImage(final MultipartFile[] files) throws IOException, FileNotFoundException {

    final BufferedImage image = ImageIO.read(files[0].getInputStream());
    final File compressedImageFile = new File(files[0].getOriginalFilename());
    final OutputStream os = new FileOutputStream(compressedImageFile);
    String fileExtenstion = files[0].getOriginalFilename();
    fileExtenstion = fileExtenstion.substring(fileExtenstion.lastIndexOf(".") + 1);
    final Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(fileExtenstion);
    final ImageWriter writer = writers.next();
    final ImageOutputStream ios = ImageIO.createImageOutputStream(os);
    writer.setOutput(ios);// ww w .  j  av  a 2s .co  m
    final ImageWriteParam param = writer.getDefaultWriteParam();

    if (!fileExtenstion.equalsIgnoreCase("png")) {
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(0.5f);
    }
    writer.write(null, new IIOImage(image, null, null), param);

    os.close();
    ios.close();
    writer.dispose();
    return compressedImageFile;
}

From source file:org.forgerock.doc.maven.PNGUtils.java

private static void saveBufferedImage(final BufferedImage bufferedImage, final File outputFile,
        final int dotsPerInch) throws IOException {
    for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName("png"); iw.hasNext();) {
        ImageWriter writer = iw.next();
        ImageWriteParam writeParam = writer.getDefaultWriteParam();
        ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier
                .createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
        IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
        if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
            continue;
        }//  w w w  .ja va  2s.co m

        setDPI(metadata, dotsPerInch);

        final ImageOutputStream stream = ImageIO.createImageOutputStream(outputFile);
        try {
            writer.setOutput(stream);
            writer.write(metadata, new IIOImage(bufferedImage, null, metadata), writeParam);
        } finally {
            stream.close();
        }
        break;
    }
}

From source file:org.freecine.filmscan.Project.java

private void saveImage(RenderedImage img, File file) {
    // Find a writer for that file extensions
    // Try to determine the file type based on extension
    String ftype = "jpg";
    String imageFname = file.getName();
    int extIndex = imageFname.lastIndexOf(".") + 1;
    if (extIndex > 0) {
        ftype = imageFname.substring(extIndex);
    }//ww  w  . j  a v  a2 s  .  c  o m

    ImageWriter writer = null;
    Iterator iter = ImageIO.getImageWritersBySuffix(ftype);
    writer = (ImageWriter) iter.next();

    if (writer != null) {
        ImageOutputStream ios = null;
        try {
            // Prepare output file
            ios = ImageIO.createImageOutputStream(file);
            writer.setOutput(ios);
            // Set some parameters
            ImageWriteParam param = writer.getDefaultWriteParam();
            writer.write(null, new IIOImage(img, null, null), param);

            // Cleanup
            ios.flush();

        } catch (IOException ex) {
            log.severe("Error saving image " + file.getAbsolutePath() + ": " + ex.getMessage());
        } finally {
            if (ios != null) {
                try {
                    ios.close();
                } catch (IOException e) {
                    log.severe("Error closing output stream: " + e.getMessage());
                }
            }
            writer.dispose();
        }
    }
}

From source file:org.geotools.utils.imageoverviews.OverviewsEmbedder.java

public void run() {
    // did we create a local private tile cache or not?
    boolean localTileCache = false;
    ///*from   w ww  . j a v  a2  s .com*/
    // creating the image to use for the successive
    // subsampling
    //
    TileCache baseTC = JAI.getDefaultInstance().getTileCache();

    if (baseTC == null) {
        localTileCache = true;
        final long tilecacheSize = super.getTileCacheSize();
        baseTC = JAI.createTileCache();
        baseTC.setMemoryCapacity(tilecacheSize);
        baseTC.setMemoryThreshold(0.75f);
    }

    //
    // CHECK INPUT DIRECTORIES/FILES
    //
    if (sourcePath == null) {
        fireEvent("Provided sourcePath is null", overallProgress);
        return;
    }
    // getting an image input stream to the file
    final File file = new File(sourcePath);
    final File[] files;
    int numFiles = 1;
    StringBuilder message;
    if (!file.canRead() || !file.exists()) {
        fireEvent("Provided file " + file.getAbsolutePath() + " cannot be read or does not exist", 100);
        return;
    }
    if (file.isDirectory()) {
        if (wildcardString == null) {
            fireEvent("Provided wildcardString is null", 100);
            return;
        }
        final FileFilter fileFilter = new WildcardFileFilter(wildcardString);
        files = file.listFiles(fileFilter);
        numFiles = files.length;
        if (numFiles <= 0) {
            message = new StringBuilder("No files to process!");
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(message.toString());
            }
            fireEvent(message.toString(), 100);

        }

    } else
        files = new File[] { file };

    if (files == null || files.length == 0) {
        fireEvent("Unable to find input files for the provided wildcard " + wildcardString + " and input path "
                + sourcePath, 100);
        return;
    }
    // setting step
    overallProgressStep = 100 * 1.0 / numFiles;

    //
    // ADDING OVERVIEWS TO ALL FOUND FILES
    //
    for (fileBeingProcessed = 0; fileBeingProcessed < numFiles; fileBeingProcessed++) {

        message = new StringBuilder("Managing file  ").append(fileBeingProcessed).append(" of ")
                .append(files[fileBeingProcessed]).append(" files");
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine(message.toString());
        }

        overallProgress = overallProgressStep * fileBeingProcessed;
        fireEvent(message.toString(), overallProgress);

        if (getStopThread()) {
            message = new StringBuilder("Stopping requested at file  ").append(fileBeingProcessed)
                    .append(" of ").append(numFiles).append(" files");
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(message.toString());
            }
            fireEvent(message.toString(), overallProgress);
            return;
        }

        ImageInputStream stream = null;
        ImageWriter writer = null;
        ImageOutputStream streamOut = null;
        RenderedOp currentImage = null;
        RenderedOp newImage = null;
        try {

            File localFile = files[fileBeingProcessed];

            //
            // get a stream
            //
            stream = ImageIO.createImageInputStream(localFile);
            if (stream == null) {

                message = new StringBuilder("Unable to create an input stream for file")
                        .append(files[fileBeingProcessed]);
                if (LOGGER.isLoggable(Level.SEVERE)) {
                    LOGGER.severe(message.toString());
                }
                fireEvent(message.toString(), overallProgress);
                break;
            }
            stream.mark();

            //
            // get a reader
            //
            final Iterator<ImageReader> it = ImageIO.getImageReaders(stream);
            if (!it.hasNext()) {
                message = new StringBuilder("Unable to find a reader for file")
                        .append(files[fileBeingProcessed]);
                if (LOGGER.isLoggable(Level.SEVERE)) {
                    LOGGER.severe(message.toString());
                }
                fireEvent(message.toString(), overallProgress);
                break;
            }
            final ImageReader reader = (ImageReader) it.next();
            stream.reset();
            stream.mark();
            // is it a geotiff reader or not?
            if (!reader.getFormatName().toLowerCase().startsWith("tif")) {
                if (LOGGER.isLoggable(Level.INFO)) {
                    LOGGER.info("Discarding input file " + files[fileBeingProcessed]
                            + " since it is not a proper tif file.");
                }
                continue;
            }

            //
            // set input
            //
            reader.setInput(stream);
            ImageLayout layout = null;
            // tiling the image if needed
            int actualTileW = reader.getTileWidth(0);
            int actualTileH = reader.getTileHeight(0);
            if (!reader.isImageTiled(0) || (reader.isImageTiled(0) && (actualTileH != tileH && tileH != -1)
                    || (actualTileW != tileW && tileW != -1))) {

                message = new StringBuilder("Retiling image  ").append(fileBeingProcessed);
                if (LOGGER.isLoggable(Level.FINE)) {
                    LOGGER.fine(message.toString());
                }
                fireEvent(message.toString(), overallProgress);
                layout = Utils.createTiledLayout(tileW, tileH, 0, 0);
            }
            stream.reset();
            reader.reset();
            reader.dispose();

            //
            // output image stream
            //
            if (externalOverviews) {
                // create a sibling file
                localFile = new File(localFile.getParent(),
                        FilenameUtils.getBaseName(localFile.getAbsolutePath()) + ".tif.ovr");
            }
            streamOut = ImageIOExt.createImageOutputStream(null, localFile);
            if (streamOut == null) {
                message = new StringBuilder("Unable to acquire an ImageOutputStream for the file ")
                        .append(files[fileBeingProcessed].toString());
                if (LOGGER.isLoggable(Level.SEVERE)) {
                    LOGGER.severe(message.toString());
                }
                fireEvent(message.toString(), 100);
                break;
            }

            //
            // Preparing to write the set of images. First of all I write
            // the first image `
            //
            // getting a writer for this reader
            writer = TIFF_IMAGE_WRITER_SPI.createWriterInstance();
            writer.setOutput(streamOut);
            writer.addIIOWriteProgressListener(writeProgressListener);
            writer.addIIOWriteWarningListener(writeProgressListener);
            ImageWriteParam param = writer.getDefaultWriteParam();

            //
            // setting tiling on the first image using writing parameters
            //
            if (tileH != -1 & tileW != -1) {
                param.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
                param.setTiling(tileW, tileH, 0, 0);

            } else {
                param.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
                param.setTiling(actualTileW, actualTileH, 0, 0);
            }
            if (this.compressionScheme != null && !Double.isNaN(compressionRatio)) {
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionType(compressionScheme);
                param.setCompressionQuality((float) this.compressionRatio);
            }

            final RenderingHints newHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
            newHints.add(new RenderingHints(JAI.KEY_TILE_CACHE, baseTC));

            // read base image
            ParameterBlock pbjRead = new ParameterBlock();
            pbjRead.add(stream);
            pbjRead.add(Integer.valueOf(0));
            pbjRead.add(Boolean.FALSE);
            pbjRead.add(Boolean.FALSE);
            pbjRead.add(Boolean.FALSE);
            pbjRead.add(null);
            pbjRead.add(null);
            pbjRead.add(null);
            pbjRead.add(null);
            currentImage = JAI.create("ImageRead", pbjRead, newHints);
            message = new StringBuilder("Read original image  ").append(fileBeingProcessed);
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(message.toString());
            }
            fireEvent(message.toString(), overallProgress);
            int i = 0;
            //
            // OVERVIEWS CYLE
            //
            for (overviewInProcess = 0; overviewInProcess < numSteps; overviewInProcess++) {

                message = new StringBuilder("Subsampling step ").append(overviewInProcess + 1)
                        .append(" of image  ").append(fileBeingProcessed);
                if (LOGGER.isLoggable(Level.FINE)) {
                    LOGGER.fine(message.toString());
                }
                fireEvent(message.toString(), overallProgress);

                // paranoiac check
                if (currentImage.getWidth() / downsampleStep <= 0
                        || currentImage.getHeight() / downsampleStep <= 0)
                    break;

                // SCALE

                // subsampling the input image using the chosen algorithm
                final SubsampleAlgorithm algorithm = SubsampleAlgorithm.valueOf(scaleAlgorithm);
                switch (algorithm) {
                case Average:
                    newImage = Utils.scaleAverage(currentImage, baseTC, downsampleStep, borderExtender);
                    break;
                case Filtered:
                    newImage = Utils.filteredSubsample(currentImage, baseTC, downsampleStep, lowPassFilter);
                    break;
                case Bilinear:
                    newImage = Utils.subsample(currentImage, baseTC, new InterpolationBilinear(),
                            downsampleStep, borderExtender);
                    break;
                case Bicubic:
                    newImage = Utils.subsample(currentImage, baseTC, new InterpolationBicubic(2),
                            downsampleStep, borderExtender);
                    break;
                case Nearest:
                    newImage = Utils.subsample(currentImage, baseTC, new InterpolationNearest(), downsampleStep,
                            borderExtender);
                    break;
                default:
                    throw new IllegalArgumentException("Invalid scaling algorithm " + scaleAlgorithm);//cannot get here

                }

                //set relevant metadata
                IIOMetadata imageMetadata = null;
                if (writer instanceof TIFFImageWriter) {
                    imageMetadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(newImage), param);
                    if (imageMetadata != null)
                        ((TIFFImageMetadata) imageMetadata).addShortOrLongField(
                                BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE,
                                BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION);
                }
                // write out
                if (!externalOverviews || i > 0)
                    writer.writeInsert(-1, new IIOImage(newImage, null, imageMetadata), param);
                else
                    writer.write(null, new IIOImage(newImage, null, imageMetadata), param);
                message = new StringBuilder("Step ").append(overviewInProcess + 1).append(" of image  ")
                        .append(fileBeingProcessed).append(" done!");
                if (LOGGER.isLoggable(Level.FINE)) {
                    LOGGER.fine(message.toString());
                }
                fireEvent(message.toString(), overallProgress);

                // switching images
                currentImage.dispose(); //dispose old image
                currentImage = newImage;

                i++;

            }

            overallProgress = 100;
            // close message
            message = new StringBuilder("Done with  image  ").append(fileBeingProcessed);
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(message.toString());
            }
            fireEvent(message.toString(), overallProgress);
        } catch (Throwable e) {
            fireException(e);
        } finally {
            // clean up

            // clean caches if they are local
            if (localTileCache && baseTC != null)
                try {
                    baseTC.flush();
                } catch (Exception e) {
                }

            //
            // free everything
            try {
                if (streamOut != null)
                    streamOut.close();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }

            try {
                if (writer != null)
                    writer.dispose();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }

            try {
                if (currentImage != null)
                    currentImage.dispose();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }

            try {
                if (newImage != null)
                    newImage.dispose();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }

            try {
                if (stream != null)
                    stream.close();

            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }
        }
    }

    if (LOGGER.isLoggable(Level.FINE))
        LOGGER.fine("Done!!!");

}

From source file:org.geowebcache.layer.MetaTile.java

/**
 * Outputs one tile from the internal array of tiles to a provided stream
 * //from www .ja v a  2 s . c om
 * @param tileIdx
 *            the index of the tile relative to the internal array
 * @param format
 *            the Java name for the format
 * @param resource
 *            the outputstream
 * @return true if no error was encountered
 * @throws IOException
 */
public boolean writeTileToStream(final int tileIdx, Resource target) throws IOException {
    if (tiles == null) {
        return false;
    }
    String format = responseFormat.getInternalName();

    if (log.isDebugEnabled()) {
        log.debug("Thread: " + Thread.currentThread().getName() + " writing: " + tileIdx);
    }

    // TODO should we recycle the writers ?
    // GR: it'd be only a 2% perf gain according to profile   
    Iterator<ImageWriter> it = javax.imageio.ImageIO.getImageWritersByFormatName(format);
    ImageWriter writer = it.next();
    ImageWriteParam param = writer.getDefaultWriteParam();

    if (this.formatModifier != null) {
        param = formatModifier.adjustImageWriteParam(param);
    }

    Rectangle tileRegion = tiles[tileIdx];
    RenderedImage tile = createTile(tileRegion.x, tileRegion.y, tileRegion.width, tileRegion.height);
    disposeLater(tile);
    OutputStream outputStream = target.getOutputStream();
    ImageOutputStream imgOut = new MemoryCacheImageOutputStream(outputStream);
    writer.setOutput(imgOut);
    IIOImage image = new IIOImage(tile, null, null);
    try {
        writer.write(null, image, param);
    } finally {
        imgOut.close();
        writer.dispose();
    }

    return true;
}

From source file:org.getobjects.appserver.publisher.GoDefaultRenderer.java

/**
 * Renders a java.awt.BufferedImage to the WOResponse of the given context.
 * Remember to configure:<pre>//ww  w. j a  v a2s  .  co m
 *   -Djava.awt.headless=true</pre>
 * (thats the VM arguments of the run panel in Eclipse) 
 * 
 * @param _img   - the BufferedImage object to render
 * @param _ctx - the WOContext to render the image in
 * @return null if everything went fine, an Exception otherwise
 */
public Exception renderBufferedImage(BufferedImage _img, WOContext _ctx) {
    // TBD: this method could be improved a lot, but it works well enough for
    //      simple cases

    if (_img == null)
        return new GoInternalErrorException("got no image to render");

    /* find a proper image writer */

    String usedType = null;
    Iterator<ImageWriter> writers;
    ImageWriter writer = null;
    WORequest rq = _ctx.request();
    if (rq != null) {
        // TBD: just iterate over the accepted (image/) types (considering
        //      the value quality) and check each

        if (rq.acceptsContentType("image/png", false /* direct match */)) {
            if ((writers = ImageIO.getImageWritersByMIMEType("image/png")) != null)
                writer = writers.next();
            if (writer != null)
                usedType = "image/png";
        }
        if (writer == null && rq.acceptsContentType("image/gif", false)) {
            if ((writers = ImageIO.getImageWritersByMIMEType("image/gif")) != null)
                writer = writers.next();
            if (writer != null)
                usedType = "image/gif";
        }
        if (writer == null && rq.acceptsContentType("image/jpeg", false)) {
            if ((writers = ImageIO.getImageWritersByMIMEType("image/jpeg")) != null)
                writer = writers.next();
            if (writer != null)
                usedType = "image/jpeg";
        }
    }
    if (writer == null) {
        if ((writers = ImageIO.getImageWritersByMIMEType("image/png")) != null)
            writer = writers.next();
        if (writer != null)
            usedType = "image/png";
    }
    if (writer == null)
        return new GoInternalErrorException("found no writer for image: " + _img);

    /* prepare WOResponse */

    WOResponse r = _ctx.response();
    r.setStatus(WOMessage.HTTP_STATUS_OK);
    r.setHeaderForKey("inline", "content-disposition");
    if (usedType != null)
        r.setHeaderForKey(usedType, "content-type");
    // TBD: do we know the content-length? If not, should we generate to a
    //      buffer to avoid confusing the browser (IE ...)
    r.enableStreaming();

    /* write */

    ImageOutputStream ios = null;
    try {
        ios = ImageIO.createImageOutputStream(rq.outputStream());
    } catch (IOException e) {
        log.warn("could not create image output stream: " + _img);
        return e;
    }

    writer.setOutput(ios);

    try {
        writer.write(null, new IIOImage(_img, null, null), null);
        ios.flush();
        writer.dispose();
        ios.close();
    } catch (IOException e) {
        log.warn("failed to write image to stream", e);
        return e;
    }

    return null; /* everything is awesome O */
}