/** * */ package fr.unistra.pelican.algorithms.io; import java.io.IOException; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.ByteImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.IntegerImage; import fr.unistra.pelican.util.jFits.Fits; import fr.unistra.pelican.util.jFits.FitsException; import fr.unistra.pelican.util.jFits.FitsFile; import fr.unistra.pelican.util.jFits.FitsHDUnit; import fr.unistra.pelican.util.jFits.FitsHeader; import fr.unistra.pelican.util.jFits.FitsKeyword; import fr.unistra.pelican.util.jFits.FitsMatrix; /** * Save an image in fits file format. * Can handle x,y and b dim. * In case of multiband image, each band is saved in a standard fits image extension. * * If a header is provided, its correctness is NOT verified. * If no header is provided, a suitable header is searched in image properties. * If no header is found at all, a minimal header is generated automatically. * * * @author Benjamin Perret * */ public class FitsImageSave extends Algorithm { /** * File path, destination of saved image */ public String filename; /** * Image to save */ public Image inputImage; /** * Optional header */ public FitsHeader header; /** * Force to use a special bit per pixel as specified in {@link Fits} */ public int bitPix=-1; /** * */ public FitsImageSave() { super.inputs="filename,inputImage"; super.options="bitPix,header"; super.outputs=""; } /* (non-Javadoc) * @see fr.unistra.pelican.Algorithm#launch() */ @Override public void launch() throws AlgorithmException { try{ FitsHDUnit [] hdus=new FitsHDUnit[inputImage.bdim]; for(int b=0;b<inputImage.bdim;b++) { FitsMatrix data=null; switch (bitPix) { case Fits.BYTE: data=getMatrixByte(inputImage,b); break; case Fits.SHORT: data=getMatrixShort(inputImage,b); break; case Fits.INT: data=getMatrixInt(inputImage,b); break; case Fits.FLOAT: data=getMatrixFloat(inputImage,b); break; case Fits.DOUBLE: data=getMatrixDouble(inputImage,b); break; default: if(inputImage instanceof BooleanImage || inputImage instanceof ByteImage) data=getMatrixByte(inputImage,b); else if(inputImage instanceof IntegerImage) data=getMatrixInt(inputImage,b); else data=getMatrixDouble(inputImage,b); } FitsHeader head; if(b==0) { if(header == null) { Object o = inputImage.properties.get(LoadFitsWithExtensions.HEADER_KEYWORD + b); if (o!= null && o instanceof FitsHeader) { head=mergeHeader(data.getHeader(),(FitsHeader)o); //System.out.println("Head found in properties for band " +b); } else { //System.out.println("Headder generated for " +b + " " +o); head=data.getHeader(); } } else { head=header; } if(inputImage.bdim!=1) head.insertKeywordAt(new FitsKeyword("EXTEND", true,"File may contain standard extension"), 5); head.addKeyword(new FitsKeyword("COMMENT","Generated from PELICAN")); } else { if(header == null) { Object o = inputImage.properties.get(LoadFitsWithExtensions.HEADER_KEYWORD + b); if (o!= null && o instanceof FitsHeader) { head=mergeHeader(data.getHeader(),(FitsHeader)o); //System.out.println("Head found in properties for band " +b); } else { //System.out.println("Headder generated for " +b + " " +o); head=data.getHeader(); } } else { head=header; } head.setExtension(Fits.IMAGE); } if(b==0) filterHeader(head); hdus[b]=new FitsHDUnit(head,data); } FitsFile file = new FitsFile(); for(int b=0;b<inputImage.bdim;b++) file.addHDUnit(hdus[b]); file.writeFile(filename); file.closeFile();} catch (FitsException e) { throw new AlgorithmException("Fits Save error: " +e); } catch (IOException e) { throw new AlgorithmException("Fits Save error: " +e); } } private FitsHeader filterHeader(FitsHeader header) { String [] remove={"PCOUNT","GCOUNT"}; for(int i=0;i < header.getNoKeywords(); i++) { FitsKeyword kw= header.getKeyword(i); boolean flag=true; String name=kw.getName(); for(int j=0;j<remove.length;j++) if(name.compareTo(remove[j])==0) { header.removeKeywordAt(i); i--; continue; } } return header; } private FitsHeader mergeHeader(FitsHeader minimalHeader, FitsHeader complete) { String [] forbidden={"NAXIS","BITPIX","SIMPLE","EXTEND","NAXIS1","NAXIS2","NAXIS3"}; for(int i=0;i < complete.getNoKeywords(); i++) { FitsKeyword kw= complete.getKeyword(i); boolean flag=true; String name=kw.getName(); for(int j=0;j<forbidden.length;j++) if(name.compareTo(forbidden[j])==0) flag=false; if(flag){ minimalHeader.addKeyword(kw); //System.out.println("accept " + kw + " name : '"+kw.getName()+"'"); } } return minimalHeader; } private FitsMatrix getMatrixShort(Image im, int b) throws FitsException, IOException { int xdim=im.xdim; int ydim=im.ydim; int nax[]={xdim,ydim}; // dimensions short dat [] =new short[xdim*ydim]; //donnᅵes for(int j=0;j<ydim;j++) // conversion des donnees et mise sous forme lineaire for (int i=0;i<xdim;i++) dat[j*im.xdim + i]=(short)im.getPixelXYBInt(i, ydim-j-1, b); FitsMatrix data=new FitsMatrix(Fits.SHORT,nax); // fits matrix des bonnes dims data.setShortValues(0, dat); // remplissage sans offset return data; } private FitsMatrix getMatrixDouble(Image im, int b) throws FitsException, IOException { int xdim=im.xdim; int ydim=im.ydim; int nax[]={xdim,ydim}; // dimensions double dat [] =new double[xdim*ydim]; //donnᅵes for(int j=0;j<ydim;j++) // conversion des donnees et mise sous forme lineaire for (int i=0;i<xdim;i++) dat[j*im.xdim + i]=im.getPixelXYBDouble(i, ydim-j-1, b); FitsMatrix data=new FitsMatrix(Fits.DOUBLE,nax); // fits matrix des bonnes dims data.setDoubleValues(0, dat); // remplissage sans offset return data; } private FitsMatrix getMatrixFloat(Image im, int b) throws FitsException, IOException { int xdim=im.xdim; int ydim=im.ydim; int nax[]={xdim,ydim}; // dimensions float dat [] =new float[xdim*ydim]; //donnᅵes for(int j=0;j<ydim;j++) // conversion des donnees et mise sous forme lineaire for (int i=0;i<xdim;i++) dat[j*im.xdim + i]=(float)im.getPixelXYBDouble(i, ydim-j-1, b); FitsMatrix data=new FitsMatrix(Fits.FLOAT,nax); // fits matrix des bonnes dims data.setFloatValues(0, dat); // remplissage sans offset return data; } private FitsMatrix getMatrixByte(Image im, int b) throws FitsException, IOException { int xdim=im.xdim; int ydim=im.ydim; int nax[]={xdim,ydim}; // dimensions short dat [] =new short[xdim*ydim]; //donnees for(int j=0;j<ydim;j++) // conversion des donnees et mise sous forme lineaire for (int i=0;i<xdim;i++) dat[ j*im.xdim + i]=(short)im.getPixelXYBByte(i, ydim-j-1, b); FitsMatrix data=new FitsMatrix(Fits.SHORT,nax); // fits matrix des bonnes dims data.setShortValues(0, dat); // remplissage sans offset return data; } private FitsMatrix getMatrixInt(Image im, int b) throws FitsException, IOException { int xdim=im.xdim; int ydim=im.ydim; int nax[]={xdim,ydim}; // dimensions int dat [] =new int[xdim*ydim]; //donnees for(int j=0;j<ydim;j++) // conversion des donnees et mise sous forme lineaire for (int i=0;i<xdim;i++) dat[j*im.xdim + i]=(short)im.getPixelXYBInt(i, ydim-j-1, b); FitsMatrix data=new FitsMatrix(Fits.SHORT,nax); // fits matrix des bonnes dims data.setIntValues(0, dat); // remplissage sans offset return data; } public static void exec(String filename, Image inputImage) { (new FitsImageSave()).process(filename,inputImage); } public static void exec(String filename, Image inputImage, int bitPix) { (new FitsImageSave()).process(filename,inputImage,bitPix); } public static void exec(String filename, Image inputImage, FitsHeader header) { (new FitsImageSave()).process(filename,inputImage,-1,header) ; } public static void exec(String filename, Image inputImage, int bitPix,FitsHeader header) { (new FitsImageSave()).process(filename,inputImage,bitPix,header) ; } }