package ij.process;
import java.awt.*;
import java.awt.image.*;
import ij.*;
import ij.gui.*;
import ij.measure.*;
/** This class converts an ImageProcessor to another data type. */
public class TypeConverter {
private static final int BYTE=0, SHORT=1, FLOAT=2, RGB=3;
private ImageProcessor ip;
private int type;
boolean doScaling = true;
int width, height;
public TypeConverter(ImageProcessor ip, boolean doScaling) {
this.ip = ip;
this.doScaling = doScaling;
if (ip instanceof ByteProcessor)
type = BYTE;
else if (ip instanceof ShortProcessor)
type = SHORT;
else if (ip instanceof FloatProcessor)
type = FLOAT;
else
type = RGB;
width = ip.getWidth();
height = ip.getHeight();
}
/** Converts processor to a ByteProcessor. */
public ImageProcessor convertToByte() {
switch (type) {
case BYTE:
return ip;
case SHORT:
return convertShortToByte();
case FLOAT:
return convertFloatToByte();
case RGB:
return convertRGBToByte();
default:
return null;
}
}
/** Converts a ShortProcessor to a ByteProcessor. */
ByteProcessor convertShortToByte() {
int size = width*height;
short[] pixels16 = (short[])ip.getPixels();
byte[] pixels8 = new byte[size];
if (doScaling) {
int value, min=(int)ip.getMin(), max=(int)ip.getMax();
double scale = 256.0/(max-min+1);
for (int i=0; i<size; i++) {
value = (pixels16[i]&0xffff)-min;
if (value<0) value = 0;
value = (int)(value*scale+0.5);
if (value>255) value = 255;
pixels8[i] = (byte)value;
}
return new ByteProcessor(width, height, pixels8, ip.getCurrentColorModel());
} else {
int value;
for (int i=0; i<size; i++) {
value = pixels16[i]&0xffff;
if (value>255) value = 255;
pixels8[i] = (byte)value;
}
return new ByteProcessor(width, height, pixels8, ip.getColorModel());
}
}
/** Converts a FloatProcessor to a ByteProcessor. */
ByteProcessor convertFloatToByte() {
if (doScaling) {
Image img = ip.createImage();
return new ByteProcessor(img);
} else {
ByteProcessor bp = new ByteProcessor(width, height);
bp.setPixels(0, (FloatProcessor)ip);
bp.setColorModel(ip.getColorModel());
bp.resetMinAndMax(); //don't take min&max from ip
return bp;
}
}
/** Converts a ColorProcessor to a ByteProcessor.
The pixels are converted to grayscale using the formula
g=r/3+g/3+b/3. Call ColorProcessor.setWeightingFactors()
to do weighted conversions. */
ByteProcessor convertRGBToByte() {
int c, r, g, b;
int[] pixels32;
byte[] pixels8;
Image img8;
//get RGB pixels
pixels32 = (int[])ip.getPixels();
//convert to grayscale
double[] w = ColorProcessor.getWeightingFactors();
double rw=w[0], gw=w[1], bw=w[2];
pixels8 = new byte[width*height];
for (int i=0; i < width*height; i++) {
c = pixels32[i];
r = (c&0xff0000)>>16;
g = (c&0xff00)>>8;
b = c&0xff;
pixels8[i] = (byte)(r*rw + g*gw + b*bw + 0.5);
}
return new ByteProcessor(width, height, pixels8, null);
}
/** Converts processor to a ShortProcessor. */
public ImageProcessor convertToShort() {
switch (type) {
case BYTE:
return convertByteToShort();
case SHORT:
return ip;
case FLOAT:
return convertFloatToShort();
case RGB:
ip = convertRGBToByte();
return convertByteToShort();
default:
return null;
}
}
/** Converts a ByteProcessor to a ShortProcessor. */
ShortProcessor convertByteToShort() {
if (!ip.isDefaultLut() && !ip.isColorLut() && !ip.isInvertedLut()) {
// apply custom LUT
ip = convertToRGB();
ip = convertRGBToByte();
return (ShortProcessor)convertByteToShort();
}
byte[] pixels8 = (byte[])ip.getPixels();
short[] pixels16 = new short[width * height];
for (int i=0,j=0; i<width*height; i++)
pixels16[i] = (short)(pixels8[i]&0xff);
return new ShortProcessor(width, height, pixels16, ip.getColorModel());
}
/** Converts a FloatProcessor to a ShortProcessor. */
ShortProcessor convertFloatToShort() {
float[] pixels32 = (float[])ip.getPixels();
short[] pixels16 = new short[width*height];
double min = ip.getMin();
double max = ip.getMax();
double scale;
if ((max-min)==0.0)
scale = 1.0;
else
scale = 65535.0/(max-min);
double value;
for (int i=0,j=0; i<width*height; i++) {
if (doScaling)
value = (pixels32[i]-min)*scale;
else
value = pixels32[i];
if (value<0.0) value = 0.0;
if (value>65535.0) value = 65535.0;
pixels16[i] = (short)(value+0.5);
}
return new ShortProcessor(width, height, pixels16, ip.getColorModel());
}
/** Converts processor to a FloatProcessor. */
public ImageProcessor convertToFloat(float[] ctable) {
switch (type) {
case BYTE:
return convertByteToFloat(ctable);
case SHORT:
return convertShortToFloat(ctable);
case FLOAT:
return ip;
case RGB:
ip = convertRGBToByte();
return convertByteToFloat(null);
default:
return null;
}
}
/** Converts a ByteProcessor to a FloatProcessor. Applies a
calibration function if the calibration table is not null.
@see ImageProcessor.setCalibrationTable
*/
FloatProcessor convertByteToFloat(float[] cTable) {
if (!ip.isDefaultLut() && !ip.isColorLut() && !ip.isInvertedLut()) {
// apply custom LUT
ip = convertToRGB();
ip = convertRGBToByte();
return (FloatProcessor)convertByteToFloat(null);
}
byte[] pixels8 = (byte[])ip.getPixels();
float[] pixels32 = new float[width*height];
int value;
if (cTable!=null && cTable.length==256) {
for (int i=0; i<width*height; i++)
pixels32[i] = cTable[pixels8[i]&255];
} else {
for (int i=0; i<width*height; i++)
pixels32[i] = pixels8[i]&255;
}
ColorModel cm = ip.getColorModel();
return new FloatProcessor(width, height, pixels32, cm);
}
/** Converts a ShortProcessor to a FloatProcessor. Applies a
calibration function if the calibration table is not null.
@see ImageProcessor.setCalibrationTable
*/
FloatProcessor convertShortToFloat(float[] cTable) {
short[] pixels16 = (short[])ip.getPixels();
float[] pixels32 = new float[width*height];
int value;
if (cTable!=null && cTable.length==65536)
for (int i=0; i<width*height; i++)
pixels32[i] = cTable[pixels16[i]&0xffff];
else
for (int i=0; i<width*height; i++)
pixels32[i] = pixels16[i]&0xffff;
ColorModel cm = ip.getColorModel();
return new FloatProcessor(width, height, pixels32, cm);
}
/** Converts processor to a ColorProcessor. */
public ImageProcessor convertToRGB() {
if (type==RGB)
return ip;
else {
ImageProcessor ip2 = ip.convertToByte(doScaling);
return new ColorProcessor(ip2.createImage());
}
}
}