Java Tutorial/2D Graphics/ImageIO — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
м (1 версия)
 
м (1 версия)
 
(нет различий)

Текущая версия на 15:24, 31 мая 2010

Add Image IO Read Progress Listener to ImageReader

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
public class Main{
  static public void main(String args[]) throws Exception {
    FileInputStream fin = new FileInputStream("a.gif");
    Iterator readers = ImageIO.getImageReadersBySuffix("GIF");
    ImageReader imageReader = (ImageReader) readers.next();
    ImageInputStream iis = ImageIO.createImageInputStream(fin);
    imageReader.setInput(iis, false);
    imageReader.addIIOReadProgressListener(new IIOReadProgressListener() {
      public void imageComplete(ImageReader source) {
        System.out.println("image complete " + source);
      }
      public void imageProgress(ImageReader source, float percentageDone) {
        System.out.println("image progress " + source + ": " + percentageDone + "%");
      }
      public void imageStarted(ImageReader source, int imageIndex) {
        System.out.println("image #" + imageIndex + " started " + source);
      }
      public void readAborted(ImageReader source) {
        System.out.println("read aborted " + source);
      }
      public void sequenceComplete(ImageReader source) {
        System.out.println("sequence complete " + source);
      }
      public void sequenceStarted(ImageReader source, int minIndex) {
        System.out.println("sequence started " + source + ": " + minIndex);
      }
      public void thumbnailComplete(ImageReader source) {
        System.out.println("thumbnail complete " + source);
      }
      public void thumbnailProgress(ImageReader source, float percentageDone) {
        System.out.println("thumbnail started " + source + ": " + percentageDone + "%");
      }
      public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
        System.out.println("thumbnail progress " + source + ", " + thumbnailIndex + " of "
            + imageIndex);
      }
    });
    BufferedImage image = imageReader.read(0);
    Iterator imageWriters = ImageIO.getImageWritersBySuffix("JPG");
    ImageWriter imageWriter = (ImageWriter) imageWriters.next();
    File file = new File("b.JPG");
    ImageOutputStream ios = ImageIO.createImageOutputStream(file);
    imageWriter.setOutput(ios);
    imageWriter.write(image);
  }
}





Compress and save an image to the disk

/*
 * Copyright (c) JForum Team
 * All rights reserved.
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 1) Redistributions of source code must retain the above 
 * copyright notice, this list of conditions and the 
 * following  disclaimer.
 * 2)  Redistributions in binary form must reproduce the 
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 * 
 * This file creation date: 21/04/2004 - 19:54:16
 * The JForum Project
 * http://www.jforum.net
 */
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

/**
 * Utilities methods for image manipulation. It does not support writting of GIF images, but it can
 * read from. GIF images will be saved as PNG.
 * 
 * @author Rafael Steil
 * @version $Id: ImageUtils.java,v 1.23 2007/09/09 01:05:22 rafaelsteil Exp $
 */
public class ImageUtils
{
  public static final int IMAGE_UNKNOWN = -1;
  public static final int IMAGE_JPEG = 0;
  public static final int IMAGE_PNG = 1;
  public static final int IMAGE_GIF = 2;
  /**
   * Resizes an image
   * 
   * @param imgName The image name to resize. Must be the complet path to the file
   * @param type int
   * @param maxWidth The image"s max width
   * @param maxHeight The image"s max height
   * @return A resized <code>BufferedImage</code>
   */
  public static BufferedImage resizeImage(String imgName, int type, int maxWidth, int maxHeight)
  {
    try {
      return resizeImage(ImageIO.read(new File(imgName)), type, maxWidth, maxHeight);
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Resizes an image.
   * 
   * @param image
   *            The image to resize
   * @param maxWidth
   *            The image"s max width
   * @param maxHeight
   *            The image"s max height
   * @return A resized <code>BufferedImage</code>
   * @param type
   *            int
   */
  public static BufferedImage resizeImage(BufferedImage image, int type, int maxWidth, int maxHeight)
  {
    Dimension largestDimension = new Dimension(maxWidth, maxHeight);
    // Original size
    int imageWidth = image.getWidth(null);
    int imageHeight = image.getHeight(null);
    float aspectRatio = (float) imageWidth / imageHeight;
    if (imageWidth > maxWidth || imageHeight > maxHeight) {
      if ((float) largestDimension.width / largestDimension.height > aspectRatio) {
        largestDimension.width = (int) Math.ceil(largestDimension.height * aspectRatio);
      }
      else {
        largestDimension.height = (int) Math.ceil(largestDimension.width / aspectRatio);
      }
      imageWidth = largestDimension.width;
      imageHeight = largestDimension.height;
    }
    return createHeadlessSmoothBufferedImage(image, type, imageWidth, imageHeight);
  }
  /**
   * Saves an image to the disk.
   * 
   * @param image  The image to save
   * @param toFileName The filename to use
   * @param type The image type. Use <code>ImageUtils.IMAGE_JPEG</code> to save as JPEG images,
   *  or <code>ImageUtils.IMAGE_PNG</code> to save as PNG.
   * @return <code>false</code> if no appropriate writer is found
   */
  public static boolean saveImage(BufferedImage image, String toFileName, int type)
  {
    try {
      return ImageIO.write(image, type == IMAGE_JPEG ? "jpg" : "png", new File(toFileName));
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Compress and save an image to the disk. Currently this method only supports JPEG images.
   * 
   * @param image The image to save
   * @param toFileName The filename to use
   * @param type The image type. Use <code>ImageUtils.IMAGE_JPEG</code> to save as JPEG images,
   * or <code>ImageUtils.IMAGE_PNG</code> to save as PNG.
   */
  public static void saveCompressedImage(BufferedImage image, String toFileName, int type)
  {
    try {
      if (type == IMAGE_PNG) {
        throw new UnsupportedOperationException("PNG compression not implemented");
      }
      Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
      ImageWriter writer;
      writer = (ImageWriter) iter.next();
      ImageOutputStream ios = ImageIO.createImageOutputStream(new File(toFileName));
      writer.setOutput(ios);
      ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
      iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
      iwparam.setCompressionQuality(0.7F);
      writer.write(null, new IIOImage(image, null, null), iwparam);
      ios.flush();
      writer.dispose();
      ios.close();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Creates a <code>BufferedImage</code> from an <code>Image</code>. This method can
   * function on a completely headless system. This especially includes Linux and Unix systems
   * that do not have the X11 libraries installed, which are required for the AWT subsystem to
   * operate. This method uses nearest neighbor approximation, so it"s quite fast. Unfortunately,
   * the result is nowhere near as nice looking as the createHeadlessSmoothBufferedImage method.
   * 
   * @param image  The image to convert
   * @param w The desired image width
   * @param h The desired image height
   * @return The converted image
   * @param type int
   */
  public static BufferedImage createHeadlessBufferedImage(BufferedImage image, int type, int width, int height)
  {
    if (type == ImageUtils.IMAGE_PNG && hasAlpha(image)) {
      type = BufferedImage.TYPE_INT_ARGB;
    }
    else {
      type = BufferedImage.TYPE_INT_RGB;
    }
    BufferedImage bi = new BufferedImage(width, height, type);
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        bi.setRGB(x, y, image.getRGB(x * image.getWidth() / width, y * image.getHeight() / height));
      }
    }
    return bi;
  }
  /**
   * Creates a <code>BufferedImage</code> from an <code>Image</code>. This method can
   * function on a completely headless system. This especially includes Linux and Unix systems
   * that do not have the X11 libraries installed, which are required for the AWT subsystem to
   * operate. The resulting image will be smoothly scaled using bilinear filtering.
   * 
   * @param source The image to convert
   * @param w The desired image width
   * @param h The desired image height
   * @return The converted image
   * @param type  int
   */
  public static BufferedImage createHeadlessSmoothBufferedImage(BufferedImage source, int type, int width, int height)
  {
    if (type == ImageUtils.IMAGE_PNG && hasAlpha(source)) {
      type = BufferedImage.TYPE_INT_ARGB;
    }
    else {
      type = BufferedImage.TYPE_INT_RGB;
    }
    BufferedImage dest = new BufferedImage(width, height, type);
    int sourcex;
    int sourcey;
    double scalex = (double) width / source.getWidth();
    double scaley = (double) height / source.getHeight();
    int x1;
    int y1;
    double xdiff;
    double ydiff;
    int rgb;
    int rgb1;
    int rgb2;
    for (int y = 0; y < height; y++) {
      sourcey = y * source.getHeight() / dest.getHeight();
      ydiff = scale(y, scaley) - sourcey;
      for (int x = 0; x < width; x++) {
        sourcex = x * source.getWidth() / dest.getWidth();
        xdiff = scale(x, scalex) - sourcex;
        x1 = Math.min(source.getWidth() - 1, sourcex + 1);
        y1 = Math.min(source.getHeight() - 1, sourcey + 1);
        rgb1 = getRGBInterpolation(source.getRGB(sourcex, sourcey), source.getRGB(x1, sourcey), xdiff);
        rgb2 = getRGBInterpolation(source.getRGB(sourcex, y1), source.getRGB(x1, y1), xdiff);
        rgb = getRGBInterpolation(rgb1, rgb2, ydiff);
        dest.setRGB(x, y, rgb);
      }
    }
    return dest;
  }
  private static double scale(int point, double scale)
  {
    return point / scale;
  }
  private static int getRGBInterpolation(int value1, int value2, double distance)
  {
    int alpha1 = (value1 & 0xFF000000) >>> 24;
    int red1 = (value1 & 0x00FF0000) >> 16;
    int green1 = (value1 & 0x0000FF00) >> 8;
    int blue1 = (value1 & 0x000000FF);
    int alpha2 = (value2 & 0xFF000000) >>> 24;
    int red2 = (value2 & 0x00FF0000) >> 16;
    int green2 = (value2 & 0x0000FF00) >> 8;
    int blue2 = (value2 & 0x000000FF);
    int rgb = ((int) (alpha1 * (1.0 - distance) + alpha2 * distance) << 24)
      | ((int) (red1 * (1.0 - distance) + red2 * distance) << 16)
      | ((int) (green1 * (1.0 - distance) + green2 * distance) << 8)
      | (int) (blue1 * (1.0 - distance) + blue2 * distance);
    return rgb;
  }
  /**
   * Determines if the image has transparent pixels.
   * 
   * @param image The image to check for transparent pixel.s
   * @return <code>true</code> of <code>false</code>, according to the result
   */
  public static boolean hasAlpha(Image image)
  {
    try {
      PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
      pg.grabPixels();
      return pg.getColorModel().hasAlpha();
    }
    catch (InterruptedException e) {
      return false;
    }
  }
}





Creates an image compatible with the current display

/*
 *
 * Created on March 16, 2007, 4:34 PM
 *
 * Copyright 2006-2007 Nigel Hughes
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at http://www.apache.org/
 * licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
/**
 * @author nigel
 */
public class Utils {
  /**
   * Creates an image compatible with the current display
   * 
   * @return A BufferedImage with the appropriate color model
   */
  public static BufferedImage createCompatibleImage(int width, int height) {
    GraphicsConfiguration configuration = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getDefaultScreenDevice().getDefaultConfiguration();
    return configuration.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
  }
}





Detect image type

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
public class Main {
  public static void main(String[] args) throws IOException {
    URL[] urls = { new URL("http://yourserver/small.png") };
    for (URL url : urls) {
      ImageInputStream iis = ImageIO.createImageInputStream(url.openStream());
      Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
      System.out.println("url= " + url.getPath());
      while (readers.hasNext()) {
        ImageReader read = readers.next();
        System.out.println("format name = " + read.getFormatName());
      }
      System.out.println();
    }
  }
}





Detect the file type of the input stream prior to reading the image

import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
public class Main {
  public static void main(String[] argv) throws Exception {
    ImageInputStream imageStream = ImageIO.createImageInputStream(new URL("").openStream());
    Iterator<ImageReader> readers = ImageIO.getImageReaders(imageStream);
    ImageReader reader = null;
    if (!readers.hasNext()) {
      imageStream.close();
      return;
    } else {
      reader = readers.next();
    }
    String formatName = reader.getFormatName();
    if (!formatName.equalsIgnoreCase("jpeg") && !formatName.equalsIgnoreCase("png")
        && !formatName.equalsIgnoreCase("gif")) {
      imageStream.close();
      return;
    }
    reader.setInput(imageStream, true, true);
    BufferedImage theImage = reader.read(0);
    reader.dispose();
    imageStream.close();
  }
}





Determining the Format of an Image in a File

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
public class Main {
  public static void main(String[] argv) throws Exception {
    File file = new File("image.gif");
    System.out.println(getFormatName(file));
    InputStream is = new FileInputStream(file);
    is.close();
    System.out.println(getFormatName(is));
  }
  private static String getFormatName(Object o) {
    try {
      ImageInputStream iis = ImageIO.createImageInputStream(o);
      Iterator iter = ImageIO.getImageReaders(iis);
      if (!iter.hasNext()) {
        return null;
      }
      ImageReader reader = (ImageReader) iter.next();
      iis.close();
      return reader.getFormatName();
    } catch (IOException e) {
    }
    return null;
  }
}





Get list of unique MIME types that can be read

import java.util.Arrays;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    String[] formatNames = ImageIO.getReaderMIMETypes();
    System.out.println(Arrays.toString(formatNames));
  }
}





Get list of unique MIME types that can be written

import java.util.Arrays;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    String[] formatNames = ImageIO.getWriterMIMETypes();
    System.out.println(Arrays.toString(formatNames));
  }
}





Get list of unique supported read formats

import java.util.Arrays;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    String[] formatNames = ImageIO.getReaderFormatNames();
    System.out.println(Arrays.toString(formatNames));
    // e.g. png jpeg gif jpg
  }
}





Get list of unique supported write formats

import java.util.Arrays;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    String[] formatNames = ImageIO.getWriterFormatNames();
    System.out.println(Arrays.toString(formatNames));
  }
}





Load an Image from a JAR file

import java.awt.Image;
import java.awt.Toolkit;
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    String imgName = "image.jpg";
    URL imgURL = Main.class.getResource(imgName);
    Toolkit tk = Toolkit.getDefaultToolkit();
    Image img = tk.getImage(imgURL);
  }
}





Load the image file from a folder or a jar file: use javax.imageio.ImageIO class to read the image file

import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] args) throws Exception {
    BufferedImage image = ImageIO.read(Main.class.getResource("S.jpg"));
  }
}





Read an Image from a file

import java.awt.BorderLayout;
import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
  public static void main(String[] argv) throws Exception {
    File sourceimage = new File("source.gif");
    Image image = ImageIO.read(sourceimage);
    JFrame frame = new JFrame();
    JLabel label = new JLabel(new ImageIcon(image));
    frame.getContentPane().add(label, BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }
}





Read an Image from inputStream

import java.awt.BorderLayout;
import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
  public static void main(String[] argv) throws Exception {
    //Read from an input stream
    InputStream is = new BufferedInputStream(new FileInputStream("source.gif"));
    Image image = ImageIO.read(is);
    JFrame frame = new JFrame();
    JLabel label = new JLabel(new ImageIcon(image));
    frame.getContentPane().add(label, BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }
}





Read an Image from URL

import java.awt.BorderLayout;
import java.awt.Image;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Read from a URL
    URL url = new URL("http://java.org/source.gif");
    Image image = ImageIO.read(url);
    JFrame frame = new JFrame();
    JLabel label = new JLabel(new ImageIcon(image));
    frame.getContentPane().add(label, BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }
}





Resizes an image

/*
 * Copyright (c) JForum Team
 * All rights reserved.
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 1) Redistributions of source code must retain the above 
 * copyright notice, this list of conditions and the 
 * following  disclaimer.
 * 2)  Redistributions in binary form must reproduce the 
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 * 
 * This file creation date: 21/04/2004 - 19:54:16
 * The JForum Project
 * http://www.jforum.net
 */
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

/**
 * Utilities methods for image manipulation. It does not support writting of GIF images, but it can
 * read from. GIF images will be saved as PNG.
 * 
 * @author Rafael Steil
 * @version $Id: ImageUtils.java,v 1.23 2007/09/09 01:05:22 rafaelsteil Exp $
 */
public class ImageUtils
{
  public static final int IMAGE_UNKNOWN = -1;
  public static final int IMAGE_JPEG = 0;
  public static final int IMAGE_PNG = 1;
  public static final int IMAGE_GIF = 2;
  /**
   * Resizes an image
   * 
   * @param imgName The image name to resize. Must be the complet path to the file
   * @param type int
   * @param maxWidth The image"s max width
   * @param maxHeight The image"s max height
   * @return A resized <code>BufferedImage</code>
   */
  public static BufferedImage resizeImage(String imgName, int type, int maxWidth, int maxHeight)
  {
    try {
      return resizeImage(ImageIO.read(new File(imgName)), type, maxWidth, maxHeight);
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Resizes an image.
   * 
   * @param image
   *            The image to resize
   * @param maxWidth
   *            The image"s max width
   * @param maxHeight
   *            The image"s max height
   * @return A resized <code>BufferedImage</code>
   * @param type
   *            int
   */
  public static BufferedImage resizeImage(BufferedImage image, int type, int maxWidth, int maxHeight)
  {
    Dimension largestDimension = new Dimension(maxWidth, maxHeight);
    // Original size
    int imageWidth = image.getWidth(null);
    int imageHeight = image.getHeight(null);
    float aspectRatio = (float) imageWidth / imageHeight;
    if (imageWidth > maxWidth || imageHeight > maxHeight) {
      if ((float) largestDimension.width / largestDimension.height > aspectRatio) {
        largestDimension.width = (int) Math.ceil(largestDimension.height * aspectRatio);
      }
      else {
        largestDimension.height = (int) Math.ceil(largestDimension.width / aspectRatio);
      }
      imageWidth = largestDimension.width;
      imageHeight = largestDimension.height;
    }
    return createHeadlessSmoothBufferedImage(image, type, imageWidth, imageHeight);
  }
  /**
   * Saves an image to the disk.
   * 
   * @param image  The image to save
   * @param toFileName The filename to use
   * @param type The image type. Use <code>ImageUtils.IMAGE_JPEG</code> to save as JPEG images,
   *  or <code>ImageUtils.IMAGE_PNG</code> to save as PNG.
   * @return <code>false</code> if no appropriate writer is found
   */
  public static boolean saveImage(BufferedImage image, String toFileName, int type)
  {
    try {
      return ImageIO.write(image, type == IMAGE_JPEG ? "jpg" : "png", new File(toFileName));
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Compress and save an image to the disk. Currently this method only supports JPEG images.
   * 
   * @param image The image to save
   * @param toFileName The filename to use
   * @param type The image type. Use <code>ImageUtils.IMAGE_JPEG</code> to save as JPEG images,
   * or <code>ImageUtils.IMAGE_PNG</code> to save as PNG.
   */
  public static void saveCompressedImage(BufferedImage image, String toFileName, int type)
  {
    try {
      if (type == IMAGE_PNG) {
        throw new UnsupportedOperationException("PNG compression not implemented");
      }
      Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
      ImageWriter writer;
      writer = (ImageWriter) iter.next();
      ImageOutputStream ios = ImageIO.createImageOutputStream(new File(toFileName));
      writer.setOutput(ios);
      ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
      iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
      iwparam.setCompressionQuality(0.7F);
      writer.write(null, new IIOImage(image, null, null), iwparam);
      ios.flush();
      writer.dispose();
      ios.close();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * Creates a <code>BufferedImage</code> from an <code>Image</code>. This method can
   * function on a completely headless system. This especially includes Linux and Unix systems
   * that do not have the X11 libraries installed, which are required for the AWT subsystem to
   * operate. This method uses nearest neighbor approximation, so it"s quite fast. Unfortunately,
   * the result is nowhere near as nice looking as the createHeadlessSmoothBufferedImage method.
   * 
   * @param image  The image to convert
   * @param w The desired image width
   * @param h The desired image height
   * @return The converted image
   * @param type int
   */
  public static BufferedImage createHeadlessBufferedImage(BufferedImage image, int type, int width, int height)
  {
    if (type == ImageUtils.IMAGE_PNG && hasAlpha(image)) {
      type = BufferedImage.TYPE_INT_ARGB;
    }
    else {
      type = BufferedImage.TYPE_INT_RGB;
    }
    BufferedImage bi = new BufferedImage(width, height, type);
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        bi.setRGB(x, y, image.getRGB(x * image.getWidth() / width, y * image.getHeight() / height));
      }
    }
    return bi;
  }
  /**
   * Creates a <code>BufferedImage</code> from an <code>Image</code>. This method can
   * function on a completely headless system. This especially includes Linux and Unix systems
   * that do not have the X11 libraries installed, which are required for the AWT subsystem to
   * operate. The resulting image will be smoothly scaled using bilinear filtering.
   * 
   * @param source The image to convert
   * @param w The desired image width
   * @param h The desired image height
   * @return The converted image
   * @param type  int
   */
  public static BufferedImage createHeadlessSmoothBufferedImage(BufferedImage source, int type, int width, int height)
  {
    if (type == ImageUtils.IMAGE_PNG && hasAlpha(source)) {
      type = BufferedImage.TYPE_INT_ARGB;
    }
    else {
      type = BufferedImage.TYPE_INT_RGB;
    }
    BufferedImage dest = new BufferedImage(width, height, type);
    int sourcex;
    int sourcey;
    double scalex = (double) width / source.getWidth();
    double scaley = (double) height / source.getHeight();
    int x1;
    int y1;
    double xdiff;
    double ydiff;
    int rgb;
    int rgb1;
    int rgb2;
    for (int y = 0; y < height; y++) {
      sourcey = y * source.getHeight() / dest.getHeight();
      ydiff = scale(y, scaley) - sourcey;
      for (int x = 0; x < width; x++) {
        sourcex = x * source.getWidth() / dest.getWidth();
        xdiff = scale(x, scalex) - sourcex;
        x1 = Math.min(source.getWidth() - 1, sourcex + 1);
        y1 = Math.min(source.getHeight() - 1, sourcey + 1);
        rgb1 = getRGBInterpolation(source.getRGB(sourcex, sourcey), source.getRGB(x1, sourcey), xdiff);
        rgb2 = getRGBInterpolation(source.getRGB(sourcex, y1), source.getRGB(x1, y1), xdiff);
        rgb = getRGBInterpolation(rgb1, rgb2, ydiff);
        dest.setRGB(x, y, rgb);
      }
    }
    return dest;
  }
  private static double scale(int point, double scale)
  {
    return point / scale;
  }
  private static int getRGBInterpolation(int value1, int value2, double distance)
  {
    int alpha1 = (value1 & 0xFF000000) >>> 24;
    int red1 = (value1 & 0x00FF0000) >> 16;
    int green1 = (value1 & 0x0000FF00) >> 8;
    int blue1 = (value1 & 0x000000FF);
    int alpha2 = (value2 & 0xFF000000) >>> 24;
    int red2 = (value2 & 0x00FF0000) >> 16;
    int green2 = (value2 & 0x0000FF00) >> 8;
    int blue2 = (value2 & 0x000000FF);
    int rgb = ((int) (alpha1 * (1.0 - distance) + alpha2 * distance) << 24)
      | ((int) (red1 * (1.0 - distance) + red2 * distance) << 16)
      | ((int) (green1 * (1.0 - distance) + green2 * distance) << 8)
      | (int) (blue1 * (1.0 - distance) + blue2 * distance);
    return rgb;
  }
  /**
   * Determines if the image has transparent pixels.
   * 
   * @param image The image to check for transparent pixel.s
   * @return <code>true</code> of <code>false</code>, according to the result
   */
  public static boolean hasAlpha(Image image)
  {
    try {
      PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
      pg.grabPixels();
      return pg.getColorModel().hasAlpha();
    }
    catch (InterruptedException e) {
      return false;
    }
  }
}





Returns true if the specified file extension can be read

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    // Check availability using a format name
    b = canReadExtension("foo"); // false
    b = canReadExtension("gif"); // true
    b = canReadExtension("giF"); // true
  }
  // Returns true if the specified file extension can be read
  public static boolean canReadExtension(String fileExt) {
    Iterator iter = ImageIO.getImageReadersBySuffix(fileExt);
    return iter.hasNext();
  }
}





Returns true if the specified file extension can be written

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    // Check availability using a format name
    b = canWriteExtension("foo"); // false
    b = canWriteExtension("gif"); // true
    b = canWriteExtension("giF"); // true
  }
  // Returns true if the specified file extension can be written
  public static boolean canWriteExtension(String fileExt) {
    Iterator iter = ImageIO.getImageWritersBySuffix(fileExt);
    return iter.hasNext();
  }
}





Returns true if the specified format name can be read

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    // Check availability using a format name
    b = canReadFormat("foo"); // false
    b = canReadFormat("gif"); // true
    b = canReadFormat("giF"); // true
    }
  // Returns true if the specified format name can be read
  public static boolean canReadFormat(String formatName) {
    Iterator iter = ImageIO.getImageReadersByFormatName(formatName);
    return iter.hasNext();
  }  
}





Returns true if the specified format name can be written

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    // Check availability using a format name
    b = canWriteFormat("foo"); // false
    b = canWriteFormat("gif"); // true
    b = canWriteFormat("giF"); // true
  }
 
  public static boolean canWriteFormat(String formatName) {
    Iterator iter = ImageIO.getImageWritersByFormatName(formatName);
    return iter.hasNext();
  }
}





Returns true if the specified mime type can be read

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    b = canReadMimeType("image/jpg"); // false
    b = canReadMimeType("image/jpeg"); // true
  }
  // Returns true if the specified mime type can be read
  public static boolean canReadMimeType(String mimeType) {
    Iterator iter = ImageIO.getImageReadersByMIMEType(mimeType);
    return iter.hasNext();
  }
}





Returns true if the specified mime type can be written

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
public class Main {
  public static void main(String[] argv) throws Exception {
    boolean b;
    b = canWriteMimeType("image/jpg"); // false
    b = canWriteMimeType("image/jpeg"); // true
  }
  // Returns true if the specified mime type can be written
  public static boolean canWriteMimeType(String mimeType) {
    Iterator iter = ImageIO.getImageWritersByMIMEType(mimeType);
    return iter.hasNext();
  }
}





Show ImageIO Info

import javax.imageio.ImageIO;
public class Main {
  static public void main(String args[]) throws Exception {
    String names[] = ImageIO.getReaderFormatNames();
    for (int i = 0; i < names.length; ++i) {
      System.out.println("reader " + names[i]);
    }
    names = ImageIO.getWriterFormatNames();
    for (int i = 0; i < names.length; ++i) {
      System.out.println("writer " + names[i]);
    }
  }
}





Use Image.IO to read an image file and display it

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class MainClass extends JFrame {
  private BufferedImage bi;
  public static void main(String[] args) {
      new MainClass().setVisible(true);
  }
  public MainClass() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    try {
      bi = ImageIO.read(new File("your.jpg"));
    } catch (Exception e) {
      e.printStackTrace();
    }
    setSize(bi.getWidth(), bi.getHeight());
  }
  public void paint(Graphics g) {
    g.drawImage(bi, 0, 0, getWidth(), getHeight(), this);
  }
}





Use the getResourceAsStream method

import java.awt.Image;
import java.awt.Toolkit;
import java.io.BufferedInputStream;
import java.io.InputStream;
public class Main {
  public static void main(String[] argv) throws Exception {
    InputStream is = Main.class.getResourceAsStream("image.gif");
    BufferedInputStream bis = new BufferedInputStream(is);
    byte[] byBuf = new byte[10000];
    int byteRead = bis.read(byBuf, 0, 10000);
    Image img = Toolkit.getDefaultToolkit().createImage(byBuf);
  }
}





Write Image with different types

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class Main {
  static public void main(String args[]) throws Exception {
    int width = 200, height = 200;
    BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D ig2 = bi.createGraphics();
    ig2.fillRect(0, 0, width - 1, height - 1);
    BasicStroke stroke = new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    ig2.setPaint(Color.lightGray);
    ig2.setStroke(stroke);
    ig2.draw(new Ellipse2D.Double(0, 0, 100, 100));
    ImageIO.write(bi, "GIF", new File("a.gif"));
  }
}