package edu.mbl.jif.imaging.util; import java.awt.*; import java.awt.image.*; import java.io.*; /** @todo Consolidate this with other Imaging utils... * */ /** * (c) Copyright 1998-2001 Ben Fry, fry@media.mit.edu<BR> * If you use this code, you must give credit appropriately. * @version 1.01 * <P> * This is a bushel of utility routines to make is easier to * deal with images and do image processing. The meat of the * routines convert an image into a pixel array, or vice versa, * making it easy to manipulate the data and convert it back * into an image to be shown on-screen or saved. * <P> * I've found the standard JDK ImageFilter classes are almost * completely a dead-end, and not very useful. Especially for * people just getting started with Java, ImageProducers and * ImageConsumers are a little bit much, nevermind the other * landmines and bugs present in JDK 1.1. * <PRE> * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <PRE> * For more information about the license, visit www.gnu.org */ public class ImageUtils_BenFry { /** * Convert an image object into an array of pixel data. * This returns an array of int[] that is width*height large. * One int per pixel, so to get the red, green, blue, and * alpha values for each pixel, use the following: * <PRE> * int myData[] = ImageUtils.imageToArray(myImage); * int pixel = myData[10]; // get the tenth pixel * int alpha = (pixel >> 24) & 0xff; * int red = (pixel >> 16) & 0xff; * int green = (pixel >> 8) & 0xff; * int blue = pixel & 0xff; * </PRE> */ static public int[] imageToArray(Image img) { int w = img.getWidth(null); int h = img.getHeight(null); int pix[] = new int[w * h]; PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pix, 0, w); try { pg.grabPixels(); } catch (InterruptedException e) { } return pix; } /** * Turns things back the other way. If you want to modify * a pixel (ala the example above) you can reassign the pixel * using the following: * <PRE> * // no transparency * int myData[10] = 0xff000000 | (red << 16) | (green < 8) | blue; * // ..or with an alpha channel * int myData[10] = (alpha << 24) | (red << 16) | (green < 8) | blue; * </PRE> */ static public Image arrayToImage(int pix[], int w) { Toolkit tk = Toolkit.getDefaultToolkit(); int h = pix.length / w; return tk.createImage(new MemoryImageSource(w, h, pix, 0, w)); } /** * Turns an image into a standard offscreen image. This * is because an image taken from a URL can't be drawn * into using getGraphics(), so the remedy is to make * an offscreen image, draw the original image into that, * and then continue drawing.. */ static public Image makeOffscreenImage(Image img, Component comp) { int width = img.getWidth(null); int height = img.getHeight(null); Image output = comp.createImage(width, height); Graphics g = output.getGraphics(); g.drawImage(img, 0, 0, null); return output; } /** * Same as above, but destination image can be a different size */ static public Image makeOffscreenImage(Image img, Component comp, int wide, int high) { int width = img.getWidth(null); int height = img.getHeight(null); Image output = comp.createImage(wide, high); Graphics g = output.getGraphics(); g.drawImage(img, (wide-width)/2, (high-height)/2, null); return output; } /** * Create a blank offscreen image without a component. * This is a hack and should be used only at a minimum. * I won't bother explaining what's going on here. */ static public Image createOffscreenImage(int width, int height) { Frame comp = new Frame(); Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); comp.setLocation(size.width + 10, 10); comp.setVisible(true); Image output = comp.createImage(width, height); comp.dispose(); return output; } static public int[] imageToSquareArray(Image inputImage) { // make a square image of the max size // max size is the diameter of the image, which makes a circle int rawData[] = ImageUtils_BenFry.imageToArray(inputImage); int rawWidth = inputImage.getWidth(null); int rawHeight = rawData.length / rawWidth; int diameter = (int)Math.ceil(Math.sqrt(rawWidth * rawWidth + rawHeight * rawHeight)); int imageData[] = new int[diameter * diameter]; int offsetX = (diameter - rawWidth) / 2; int offsetY = (diameter - rawHeight) / 2; for (int y = 0; y < rawHeight; y++) { for (int x = 0; x < rawWidth; x++) { imageData[offsetY * diameter + offsetX] = rawData[y * rawWidth + x]; offsetX++; } offsetX -= rawWidth; offsetY++; } return imageData; } }