package edu.mbl.jif.imagej;
/*
* Image/J Plugins
* Copyright (C) 2002-2004 Jarek Sacha
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Latest release available at http://sourceforge.net/projects/ij-plugins/
*/
import ij.ImagePlus;
import ij.measure.Calibration;
import ij.process.*;
import java.awt.image.*;
/**
* Creates/converts Image/J's image objects from Java2D/JAI representation.
*
* @author Jarek Sacha
* @version $Revision: 1.4 $
*/
public class ImagePlusCreator {
private ImagePlusCreator() {
}
/**
* Force Rendered image to set all the tails that it may have. In multi-tile
* images not all tiles may be updated when a RenderedImage is created.
*
* @param ri image that may need tile update.
* @return WritableRaster with all tiles updated.
*/
public static WritableRaster forceTileUpdate(RenderedImage ri) {
Raster r = ri.getData();
if (!(r instanceof WritableRaster)) {
r = Raster.createWritableRaster(r.getSampleModel(), r.getDataBuffer(), null);
}
WritableRaster wr = (WritableRaster) r;
int xTiles = ri.getNumXTiles();
int yTiles = ri.getNumYTiles();
for (int ty = 0; ty < yTiles; ++ty) {
for (int tx = 0; tx < xTiles; ++tx) {
wr.setRect(ri.getTile(tx, ty));
}
}
return wr;
}
/**
* Create an ImageProcessor object from a DataBuffer.
*
* @param w Image width.
* @param h Image height.
* @param buffer Data buffer.
* @param cm Color model.
* @return Image processor object.
* @throws UnsupportedImageModelException2 If data buffer is in unknown format.
*/
public static ImageProcessor createProcessor(int w, int h, DataBuffer buffer,
ColorModel cm) throws UnsupportedImageModelException2 {
if (buffer.getOffset() != 0) {
throw new UnsupportedImageModelException2("Expecting BufferData with no offset.");
}
switch (buffer.getDataType()) {
case DataBuffer.TYPE_BYTE:
return new ByteProcessor(w, h, ((DataBufferByte) buffer).getData(), cm);
case DataBuffer.TYPE_USHORT:
return new ShortProcessor(w, h, ((DataBufferUShort) buffer).getData(), cm);
case DataBuffer.TYPE_SHORT:
short[] pixels = ((DataBufferShort) buffer).getData();
for (int i = 0; i < pixels.length; ++i) {
pixels[i] = (short) (pixels[i] + 32768);
}
return new ShortProcessor(w, h, pixels, cm);
case DataBuffer.TYPE_INT:
return new FloatProcessor(w, h, ((DataBufferInt) buffer).getData());
case DataBuffer.TYPE_FLOAT:
{
DataBufferFloat dbFloat = (DataBufferFloat) buffer;
return new FloatProcessor(w, h, dbFloat.getData(), cm);
}
case DataBuffer.TYPE_DOUBLE:
return new FloatProcessor(w, h, ((DataBufferDouble) buffer).getData());
case DataBuffer.TYPE_UNDEFINED:
// ENH: Should this be reported as data problem?
throw new UnsupportedImageModelException2("Pixel type is undefined.");
default:
throw new UnsupportedImageModelException2("Unrecognized DataBuffer data type");
}
}
/**
* Create instance of ImagePlus from WritableRaster r and ColorModel cm.
*
* @param r Raster containing pixel data.
* @param cm Image color model (can be null).
* @return ImagePlus object created from WritableRaster r and
* ColorModel cm
* @throws UnsupportedImageModelException2 when enable to create ImagePlus.
*/
public static ImagePlus create(WritableRaster r, ColorModel cm)
throws UnsupportedImageModelException2 {
DataBuffer db = r.getDataBuffer();
int numBanks = db.getNumBanks();
if (numBanks > 1 && cm == null) {
throw new UnsupportedImageModelException2("Don't know what to do with image with no " +
"color model and multiple banks.");
}
SampleModel sm = r.getSampleModel();
int dbType = db.getDataType();
if (numBanks > 1 || sm.getNumBands() > 1
) {
// If image has multiple banks or multiple color components, assume that it
// is a color image and relay on AWT for proper decoding.
BufferedImage bi = new BufferedImage(cm, r, false, null);
return new ImagePlus(null, new ColorProcessor(bi));
} else if (sm.getSampleSize(0) < 8) {
// Temporary fix for less then 8 bit images
BufferedImage bi = new BufferedImage(cm, r, false, null);
return new ImagePlus(null, new ByteProcessor(bi));
} else {
if (!(cm instanceof IndexColorModel)) {
// Image/J (as of version 1.26r) can not properly deal with non color
// images and ColorModel that is not an instance of IndexedColorModel.
cm = null;
}
ImageProcessor ip = createProcessor(r.getWidth(), r.getHeight(),
r.getDataBuffer(), cm);
ImagePlus im = new ImagePlus(null, ip);
// Add calibration function for 'short' pixels
if (db.getDataType() == DataBuffer.TYPE_SHORT) {
Calibration cal = new Calibration(im);
double[] coeff = new double[2];
coeff[0] = -32768.0;
coeff[1] = 1.0;
cal.setFunction(Calibration.STRAIGHT_LINE, coeff, "gray value");
im.setCalibration(cal);
} else if (cm == null) {
Calibration cal = im.getCalibration();
im.setCalibration(null);
ImageStatistics stats = im.getStatistics();
im.setCalibration(cal);
ip.setMinAndMax(stats.min, stats.max);
im.updateImage();
}
return im;
}
}
}