package fr.unistra.pelican.algorithms.io;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferInt;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.imageio.ImageIO;
import javax.media.jai.RasterFactory;
import com.sun.media.imageioimpl.common.BogusColorSpace;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.DoubleImage;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.IntegerImage;
import fr.unistra.pelican.InvalidParameterException;
import fr.unistra.pelican.PelicanException;
import fr.unistra.pelican.util.jFits.FitsHeader;
/**
* This class saves the given image into the desired format. All JAI supported
* formats may be used. Including bmp,jpeg, png and tiff. <br>
* In case of an unsupported format the input is saved as a tiff file (the
* default format of JAI). <br>
* The input can be either a monochannel grayscale image, a tristumulus color
* image, or even a multispectral image (TIFF is then the only possible output
* format). In case of depth and time dimensions, the produced file is a
* multipage TIFF file.
*
*
* @author Lefevre
*/
public class ImageSave extends Algorithm {
/**
* First input parameter
*/
public String filename;
/**
* Second input parameter
*/
public Image input;
/**
* Some other data you want to save (algorithm dependent)
*/
public Object [] auxData;
/**
* Constructor
*
*/
public ImageSave() {
super.inputs = "input,filename";
super.options="auxData";
super.outputs = "";
}
/*
* (non-Javadoc)
*
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
BufferedImage img = null;
String extension = null;
int bdim = input.getBDim();
int tdim = input.getTDim();
int zdim = input.getZDim();
int xdim = input.getXDim();
int ydim = input.getYDim();
int indice = filename.lastIndexOf('.');
if (indice != -1)
extension = filename.substring(indice + 1).toLowerCase();
else
extension = "tiff";
// 3D or 2D+t image, switch to multiple-page tiff
if (zdim != 1 || tdim != 1) {
System.err.println("Non-standard file: switching to multiple-page tiff");
TiffMultiplePageImageSave.exec(input, filename);
}
// Grayscale, Colour, and Multispectral (only TIFF) images
else {
if(extension.compareTo("fits")==0 || extension.compareTo("fit")==0)
{
FitsHeader h=null;
int bitPix=-1;
if(auxData != null && auxData.length>0 && auxData[0] instanceof Number) {
bitPix = ((Number) auxData[0]).intValue();
}
if(auxData != null && auxData.length>1 && auxData[1] instanceof FitsHeader) {
h = (FitsHeader) auxData[1];
}
FitsImageSave.exec(filename, input,bitPix,h);
return;
} else if(extension.compareTo("txt")==0 || extension.compareTo("pix")==0)
{
if(auxData!=null && auxData.length>0 && auxData[0] instanceof Character)
IRAFTextImageSave.exec(filename, input,(Character)auxData[0]);
else IRAFTextImageSave.exec(filename, input);
return;
}else if ( extension.compareTo("pelican")==0 || extension.compareTo("pel")==0
|| extension.compareTo("plc")==0) {
PelicanImageSave.exec(input, filename);
return;
}else if ( extension.compareTo("osf")==0) {
if(input instanceof IntegerImage)
{
OdessaSegmentationSave.exec((IntegerImage)input, filename);
return;
}
}
// Graylevel image
if (bdim == 1 && !(input instanceof IntegerImage)
&& !(input instanceof DoubleImage)) {
SampleModel s = RasterFactory.createBandedSampleModel(
DataBuffer.TYPE_BYTE, xdim, ydim, 1);
img = imageToBufferedImage(input, s, BufferedImage.TYPE_BYTE_GRAY);
}
// Color 8-bit image in RGB
else if (bdim == 3 && !(input instanceof IntegerImage)) {
int[] bandOffsets = { 0, 1, 2 };
SampleModel s = RasterFactory.createPixelInterleavedSampleModel(
DataBuffer.TYPE_BYTE, xdim, ydim, bdim, bdim * xdim, bandOffsets);
img = imageToBufferedImage(input, s, BufferedImage.TYPE_3BYTE_BGR);
}
// Multispectral image
else {
// 32 bits
if (input instanceof DoubleImage) {
WritableRaster r = RasterFactory.createBandedRaster(
DataBuffer.TYPE_DOUBLE, xdim, ydim, bdim, null);
for (int b = 0; b < bdim; b++)
for (int y = 0; y < ydim; y++)
for (int x = 0; x < xdim; x++)
r.setSample(x, y, b, input.getPixelXYBDouble(x, y, b));
BogusColorSpace cs = new BogusColorSpace(bdim);
ComponentColorModel cm = new ComponentColorModel(cs, false, false, 1,
DataBuffer.TYPE_DOUBLE);
img = new BufferedImage(cm, r, false, null);
} // 16 bits
else if (input instanceof IntegerImage) {
WritableRaster r = RasterFactory.createBandedRaster(
DataBuffer.TYPE_SHORT, xdim, ydim, bdim, null);
for (int b = 0; b < bdim; b++)
for (int y = 0; y < ydim; y++)
for (int x = 0; x < xdim; x++)
r.setSample(x, y, b, input.getPixelXYBInt(x, y, b));
BogusColorSpace cs = new BogusColorSpace(bdim);
ComponentColorModel cm = new ComponentColorModel(cs, false, false, 1,
DataBuffer.TYPE_SHORT);
img = new BufferedImage(cm, r, false, null);
}
// 8 bits
else {
WritableRaster r = RasterFactory.createBandedRaster(
DataBuffer.TYPE_BYTE, xdim, ydim, bdim, null);
for (int b = 0; b < bdim; b++)
for (int y = 0; y < ydim; y++)
for (int x = 0; x < xdim; x++)
r.setSample(x, y, b, input.getPixelXYBByte(x, y, b));
BogusColorSpace cs = new BogusColorSpace(bdim);
ComponentColorModel cm = new ComponentColorModel(cs, false, false, 1,
DataBuffer.TYPE_BYTE);
img = new BufferedImage(cm, r, false, null);
}
}
File f = new File(filename);
try {
if(extension.compareTo("pdf")==0)
{
PDFImageSave.exec(img,f.getAbsolutePath());
}
else if (!ImageIO.write((RenderedImage) img, extension, f)) {
System.err
.println("Error encountered with the desired file format: \'" + extension + "\', switching to \'tiff\'");
ImageIO.write((RenderedImage) img, "tiff", f);
}
} catch (Exception e1) {
throw new InvalidParameterException("PELICAN cannot write :" + filename +"\nError was " +e1,e1);
}
}
}
static DataBufferDouble imageToDataBufferDouble(Image image) {
int size = image.size();
double[] pixels = new double[size];
for (int i = 0; i < size; i++)
pixels[i] = image.getPixelDouble(i);
return new DataBufferDouble(pixels, size);
}
static DataBufferInt imageToDataBufferInt(Image image) {
int size = image.size();
int[] pixels = new int[size];
for (int i = 0; i < size; i++)
pixels[i] = image.getPixelInt(i);
return new DataBufferInt(pixels, size);
}
static DataBufferByte imageToDataBufferByte(Image image) {
int size = image.size();
byte[] pixels = new byte[size];
for (int i = 0; i < size; i++)
pixels[i] = (byte) image.getPixelByte(i);
return new DataBufferByte(pixels, size);
}
static BufferedImage imageToBufferedImage(Image image, SampleModel s, int type) {
DataBuffer db = null;
if (image instanceof IntegerImage)
db = imageToDataBufferInt(image);
// // FIXME: 32bits saving doesn't work
// else if (image instanceof DoubleImage)
// db = imageToDataBufferDouble(image);
else
db = imageToDataBufferByte(image);
Raster r = RasterFactory.createWritableRaster(s, db, new Point(0, 0));
BufferedImage img = new BufferedImage(image.getXDim(), image.getYDim(),
type);
img.setData(r);
return img;
}
/**
* Saves the given images into the desired format.
*
* @param image
* Image to be saved.
* @param filename
* Path where the image will be saved.
*/
public static void exec(Image input, String filename) {
new ImageSave().process(input, filename);
}
/**
* Saves the given images into the desired format.
*
* @param image
* Image to be saved.
* @param filename
* Path where the image will be saved.
* @param auxData
* auxilary datum ... if needed
*/
public static void exec(Image input, String filename, Object ... auxData ) {
new ImageSave().process(input, filename, auxData);
}
/**
* Print supported format for standard IO Java Interface, Other Pelican types are not listed
*/
public static void exec() {
String readerNames[] = ImageIO.getReaderFormatNames();
printlist(readerNames, "Reader names:");
String readerMimes[] = ImageIO.getReaderMIMETypes();
printlist(readerMimes, "Reader MIME types:");
String writerNames[] = ImageIO.getWriterFormatNames();
printlist(writerNames, "Writer names:");
String writerMimes[] = ImageIO.getWriterMIMETypes();
printlist(writerMimes, "Writer MIME types:");
}
private static void printlist(String names[], String title) {
System.out.println(title);
for (int i = 0, n = names.length; i < n; i++) {
System.out.println("\t" + names[i]);
}
}
}