All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ij.io.FileSaver Maven / Gradle / Ivy

Go to download

ImageJ is an open source Java image processing program inspired by NIH Image for the Macintosh.

There is a newer version: 1.54m
Show newest version
package ij.io;
import java.awt.*;
import java.io.*;
import java.util.zip.*;
import ij.*;
import ij.process.*;
import ij.measure.Calibration;
import ij.plugin.filter.Analyzer;
import ij.plugin.frame.Recorder;
import ij.plugin.JpegWriter;
import ij.plugin.Orthogonal_Views;
import ij.gui.*;
import ij.measure.Measurements;
import ij.util.Tools;
import javax.imageio.*;

/** Saves images in tiff, gif, jpeg, raw, zip and text format. */
public class FileSaver {

	public static final int DEFAULT_JPEG_QUALITY = 85;
	private static int jpegQuality;
	private static int bsize = 32768; // 32K default buffer size
	
    static {setJpegQuality(ij.Prefs.getInt(ij.Prefs.JPEG, DEFAULT_JPEG_QUALITY));}

	private static String defaultDirectory = null;
	private ImagePlus imp;
	private FileInfo fi;
	private String name;
	private String directory;
	private boolean saveName;

	/** Constructs a FileSaver from an ImagePlus. */
	public FileSaver(ImagePlus imp) {
		this.imp = imp;
		fi = imp.getFileInfo();
	}

	/** Resaves the image. Calls saveAsTiff() if this is a new image, not a TIFF,
		or if the image was loaded using a URL. Returns false if saveAsTiff() is
		called and the user selects cancel in the file save dialog box. */
	public boolean save() {
		FileInfo ofi = null;
		if (imp!=null) ofi = imp.getOriginalFileInfo();
		boolean validName = ofi!=null && imp.getTitle().equals(ofi.fileName);
		if (validName && ofi.fileFormat==FileInfo.TIFF && ofi.directory!=null && !ofi.directory.equals("") && (ofi.url==null||ofi.url.equals(""))) {
            name = imp.getTitle();
            directory = ofi.directory;
			String path = directory+name;
			File f = new File(path);
			if (f==null || !f.exists())
				return saveAsTiff();
			if (!IJ.isMacro()) {
				GenericDialog gd = new GenericDialog("Save as TIFF");
				gd.addMessage("\""+ofi.fileName+"\" already exists.\nDo you want to replace it?");
				gd.setOKLabel("Replace");
				gd.showDialog();
				if (gd.wasCanceled())
					return false;
			}
			IJ.showStatus("Saving "+path);
			if (imp.getStackSize()>1) {
				IJ.saveAs(imp, "tif", path);
				return true;
			} else
		    	return saveAsTiff(path);
		} else
			return saveAsTiff();
	}
	
	String getPath(String type, String extension) {
		name = imp.getTitle();
		SaveDialog sd = new SaveDialog("Save as "+type, name, extension);
		name = sd.getFileName();
		if (name==null)
			return null;
		directory = sd.getDirectory();
		imp.startTiming();
		String path = directory+name;
		return path;
	}
	
	/** Saves the image or stack in TIFF format using a save file
		dialog. Returns false if the user selects cancel. Equivalent to 
		IJ.saveAsTiff(imp,""), which is more convenient. */
	public boolean saveAsTiff() {
		String path = getPath("TIFF", ".tif");
		if (path==null)
			return false;
		if (fi.nImages>1)
			return saveAsTiffStack(path);
		else
			return saveAsTiff(path);
	}
	
	/** Saves the image in TIFF format using the specified path. Equivalent to
		 IJ.saveAsTiff(imp,path), which is more convenient. */
	public boolean saveAsTiff(String path) {
		if (fi.nImages>1)
			return saveAsTiffStack(path);
		if (imp.getProperty("FHT")!=null && path.contains("FFT of "))
			setupFFTSave();
		fi.info = imp.getInfoProperty();
		Object label = imp.getProperty("Label");
		if (label!=null && (label instanceof String)) {
			fi.sliceLabels = new String[1];
			fi.sliceLabels[0] = (String)label;
		}
		fi.description = getDescriptionString();
		if (imp.getProperty(Plot.PROPERTY_KEY) != null) {
			Plot plot = (Plot)(imp.getProperty(Plot.PROPERTY_KEY));
			fi.plot = plot.toByteArray();
		}
		fi.roi = RoiEncoder.saveAsByteArray(imp.getRoi());
		fi.overlay = getOverlay(imp);
		fi.properties = imp.getPropertiesAsArray();
		DataOutputStream out = null;
		try {
			TiffEncoder file = new TiffEncoder(fi);
			out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path),bsize));
			file.write(out);
			out.close();
		} catch (IOException e) {
			showErrorMessage("saveAsTiff", path, e);
			return false;
		} finally {
			if (out!=null)
				try {out.close();} catch (IOException e) {}
		}
		updateImp(fi, FileInfo.TIFF);
		return true;
	}
	
	private void setupFFTSave() {
		Object obj = imp.getProperty("FHT");
		if (obj==null) return;
		FHT fht = (obj instanceof FHT)?(FHT)obj:null;
		if (fht==null) return;
		if (fht.originalColorModel!=null && fht.originalBitDepth!=24)
			fht.setColorModel(fht.originalColorModel);
		ImagePlus imp2 = new ImagePlus(imp.getTitle(), fht);
		imp2.setProperty("Info", imp.getProperty("Info"));
		imp2.setProperties(imp.getPropertiesAsArray());
		imp2.setCalibration(imp.getCalibration());
		imp = imp2;
		fi = imp.getFileInfo();
	}
	
	public static byte[][] getOverlay(ImagePlus imp) {
		if (imp.getHideOverlay())
			return null;
		Overlay overlay = imp.getOverlay();
		if (overlay==null) {
			ImageCanvas ic = imp.getCanvas();
			if (ic==null) return null;
			overlay = ic.getShowAllList(); // ROI Manager "Show All" list
			if (overlay==null) return null;
		}
		int n = overlay.size();
		if (n==0)
			return null;
		if (Orthogonal_Views.isOrthoViewsImage(imp))
			return null;
		byte[][] array = new byte[n][];
		for (int i=0; i1 && imp.getStack().isVirtual())
			fi.virtualStack = (VirtualStack)imp.getStack();
		DataOutputStream out = null;
		try {
			ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(path));
			out = new DataOutputStream(new BufferedOutputStream(zos,bsize));
        	zos.putNextEntry(new ZipEntry(name));
			TiffEncoder te = new TiffEncoder(fi);
			te.write(out);
			out.close();
		}
		catch (IOException e) {
			showErrorMessage("saveAsZip", path, e);
			return false;
		} finally {
			if (out!=null)
				try {out.close();} catch (IOException e) {}
		}
		updateImp(fi, FileInfo.TIFF);
		return true;
	}

	public static boolean okForGif(ImagePlus imp) {
		if (imp.getType()==ImagePlus.COLOR_RGB)
			return false;
		else
			return true;
	}

	/** Save the image in GIF format using a save file
		dialog. Returns false if the user selects cancel
		or the image is not 8-bits. */
	public boolean saveAsGif() {
		String path = getPath("GIF", ".gif");
		if (path==null)
			return false;
		else
			return saveAsGif(path);
	}
	
	/** Save the image in Gif format using the specified path. Returns
		false if the image is not 8-bits or there is an I/O error. */
	public boolean saveAsGif(String path) {
		IJ.runPlugIn(imp, "ij.plugin.GifWriter", path);
		updateImp(fi, FileInfo.GIF_OR_JPG);
		return true;
	}

	/** Always returns true. */
	public static boolean okForJpeg(ImagePlus imp) {
		return true;
	}

	/** Save the image in JPEG format using a save file
		dialog. Returns false if the user selects cancel.
		@see #setJpegQuality
		@see #getJpegQuality
	*/
	public boolean saveAsJpeg() {
		String type = "JPEG ("+getJpegQuality()+")";
		String path = getPath(type, ".jpg");
		if (path==null)
			return false;
		else
			return saveAsJpeg(path);
	}

	/** Save the image in JPEG format using the specified path.
		@see #setJpegQuality
		@see #getJpegQuality
	*/
	public boolean saveAsJpeg(String path) {
		String err = JpegWriter.save(imp, path, jpegQuality);
		if (err==null && !(imp.getType()==ImagePlus.GRAY16 || imp.getType()==ImagePlus.GRAY32))
			updateImp(fi, FileInfo.GIF_OR_JPG);
		return true;
	}

	/** Save the image in BMP format using a save file dialog. 
		Returns false if the user selects cancel. */
	public boolean saveAsBmp() {
		String path = getPath("BMP", ".bmp");
		if (path==null)
			return false;
		else
			return saveAsBmp(path);
	}

	/** Save the image in BMP format using the specified path. */
	public boolean saveAsBmp(String path) {
		IJ.runPlugIn(imp, "ij.plugin.BMP_Writer", path);
		updateImp(fi, FileInfo.BMP);
		return true;
	}

	/** Saves grayscale images in PGM (portable graymap) format 
		and RGB images in PPM (portable pixmap) format,
		using a save file dialog.
		Returns false if the user selects cancel.
	*/
	public boolean saveAsPgm() {
		String extension = imp.getBitDepth()==24?".pnm":".pgm";
		String path = getPath("PGM", extension);
		if (path==null)
			return false;
		else
			return saveAsPgm(path);
	}

	/** Saves grayscale images in PGM (portable graymap) format 
		and RGB images in PPM (portable pixmap) format,
		using the specified path. */
	public boolean saveAsPgm(String path) {
		IJ.runPlugIn(imp, "ij.plugin.PNM_Writer", path);
		updateImp(fi, FileInfo.PGM);
		return true;
	}

	/** Save the image in PNG format using a save file dialog. 
		Returns false if the user selects cancel. */
	public boolean saveAsPng() {
		String path = getPath("PNG", ".png");
		if (path==null)
			return false;
		else
			return saveAsPng(path);
	}

	/** Save the image in PNG format using the specified path. */
	public boolean saveAsPng(String path) {
		IJ.runPlugIn(imp, "ij.plugin.PNG_Writer", path);
		updateImp(fi, FileInfo.IMAGEIO);
		return true;
	}

	/** Save the image in FITS format using a save file dialog. 
		Returns false if the user selects cancel. */
	public boolean saveAsFits() {
		if (!okForFits(imp)) return false;
		String path = getPath("FITS", ".fits");
		if (path==null)
			return false;
		else
			return saveAsFits(path);
	}

	/** Save the image in FITS format using the specified path. */
	public boolean saveAsFits(String path) {
		if (!okForFits(imp)) return false;
		IJ.runPlugIn(imp, "ij.plugin.FITS_Writer", path);
		updateImp(fi, FileInfo.FITS);
		return true;
	}

	public static boolean okForFits(ImagePlus imp) {
		if (imp.getBitDepth()==24) {
			IJ.error("FITS Writer", "Grayscale image required");
			return false;
		} else
			return true;
	}

	/** Save the image or stack as raw data using a save file
		dialog. Returns false if the user selects cancel. */
	public boolean saveAsRaw() {
		String path = getPath("Raw", ".raw");
		if (path==null)
			return false;
		if (imp.getStackSize()==1)
			return saveAsRaw(path);
		else
			return saveAsRawStack(path);
	}
	
	/** Save the image as raw data using the specified path. */
	public boolean saveAsRaw(String path) {
		fi.nImages = 1;
		fi.intelByteOrder = Prefs.intelByteOrder;
		boolean signed16Bit = false;
		short[] pixels = null;
		int n = 0;
		OutputStream out = null;
		try {
			signed16Bit = imp.getCalibration().isSigned16Bit();
			if (signed16Bit) {
				pixels = (short[])imp.getProcessor().getPixels();
				n = imp.getWidth()*imp.getHeight();
				for (int i=0; i1 && imp.getStack().isVirtual();
		if (virtualStack) {
			fi.virtualStack = (VirtualStack)imp.getStack();
			if (imp.getProperty("AnalyzeFormat")!=null) fi.fileName="FlipTheseImages";
		}
		OutputStream out = null;
		try {
			signed16Bit = imp.getCalibration().isSigned16Bit();
			if (signed16Bit && !virtualStack) {
				stack = (Object[])fi.pixels;
				n = imp.getWidth()*imp.getHeight();
				for (int slice=0; slice100)
			msg = msg.substring(0, 100);
		msg = "File saving error (IOException):\n   \"" + msg + "\"";
		IJ.error("FileSaver."+title, msg+" \n   "+path);
		IJ.showProgress(1.0);
	}
	
	private void error(String msg) {
		IJ.error("FileSaver", msg);
	}

	/** Returns a string containing information about the specified  image. */
	public String getDescriptionString() {
		Calibration cal = imp.getCalibration();
		StringBuffer sb = new StringBuffer(100);
		sb.append("ImageJ="+ImageJ.VERSION+"\n");
		if (fi.nImages>1 && fi.fileType!=FileInfo.RGB48)
			sb.append("images="+fi.nImages+"\n");
		int channels = imp.getNChannels();
		if (channels>1)
			sb.append("channels="+channels+"\n");
		int slices = imp.getNSlices();
		if (slices>1)
			sb.append("slices="+slices+"\n");
		int frames = imp.getNFrames();
		if (frames>1)
			sb.append("frames="+frames+"\n");
		if (imp.isHyperStack()) sb.append("hyperstack=true\n");
		if (imp.isComposite()) {
			String mode = ((CompositeImage)imp).getModeAsString();
			sb.append("mode="+mode+"\n");
		}
		if (fi.unit!=null)
			appendEscapedLine(sb, "unit="+fi.unit);
		int bitDepth = imp.getBitDepth();
		if (fi.valueUnit!=null && (fi.calibrationFunction!=Calibration.CUSTOM||bitDepth==32)) {
			if (bitDepth!=32) {
				sb.append("cf="+fi.calibrationFunction+"\n");
				if (fi.coefficients!=null) {
					for (int i=0; i=0x20 && c<0x7f && c!='\\')
				sb.append(c);
			else if (c<=0xffff) {   //(supplementary unicode characters >0xffff unsupported)
				sb.append("\\u");
				sb.append(Tools.int2hex(c, 4));
			}
		}
		sb.append('\n');
	}

	/** Specifies the image quality (0-100). 0 is poorest image quality,
		highest compression, and 100 is best image quality, lowest compression. */
    public static void setJpegQuality(int quality) {
        jpegQuality = quality;
    	if (jpegQuality<0) jpegQuality = 0;
    	if (jpegQuality>100) jpegQuality = 100;
    }

    /** Returns the current JPEG quality setting (0-100). */
    public static int getJpegQuality() {
        return jpegQuality;
    }
    
    /** Sets the BufferedOutputStream buffer size in bytes (default is 32K). */
    public static void setBufferSize(int bufferSize) {
        bsize = bufferSize;
        if (bsize<2048) bsize = 2048;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy