package edu.mbl.jif.imagej; /* * Image/J Plugins * Copyright (C) 2002,2003 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.io.FileInfo; import ij.io.TiffDecoder; import ij.measure.Calibration; import java.io.*; import java.util.Properties; /** * Decodes and encodes description strings used by ImageJ to store extra image * info in TIFF description field. * * @author Jarek Sacha * @created March 23, 2002 * @version $Revision: 1.3 $ */ public class DescriptionStringCoder { private DescriptionStringCoder() { } /** * Creates an optional image description string for saving calibration data. * For stacks, also saves the stack size so ImageJ can open the stack without * decoding an IFD for each slice. * * @param imp Image for which the decription string should be created. * @return Description string. */ public static String encode(ImagePlus imp) { FileInfo fi = imp.getFileInfo(); StringBuffer sb = new StringBuffer(100); sb.append("ImageJ=" + ij.ImageJ.VERSION + "\n"); if (fi.nImages > 1) { sb.append("images=" + fi.nImages + "\n"); } if (fi.unit != null) { sb.append("unit=" + fi.unit + "\n"); } if (fi.valueUnit != null) { sb.append("cf=" + fi.calibrationFunction + "\n"); if (fi.coefficients != null) { for (int i = 0; i < fi.coefficients.length; i++) { sb.append("c" + i + "=" + fi.coefficients[i] + "\n"); } } sb.append("vunit=" + fi.valueUnit + "\n"); } if (fi.nImages > 1) { if (fi.pixelDepth != 0.0 && fi.pixelDepth != 1.0) { sb.append("spacing=" + fi.pixelDepth + "\n"); } if (fi.frameInterval != 0.0) { double fps = 1.0 / fi.frameInterval; if ((int) fps == fps) { sb.append("fps=" + (int) fps + "\n"); } else { sb.append("fps=" + fps + "\n"); } } } sb.append(""); return sb.toString(); } /** * Decode the ImageDescription tag. ImageJ saves spatial and density * calibration data in this string. For stacks, it also saves the number of * images to avoid having to decode an IFD for each image. * * @param description Description string. * @param imp Image that will be adjusted using information stored * in the decription string. * @exception Exception If information stored in the decription string is * inconsistent with image size. */ public static void decode(String description, ImagePlus imp) throws Exception { if (description == null || !description.startsWith("ImageJ")) { return; } Properties props = new Properties(); InputStream is = new ByteArrayInputStream(description.getBytes()); try { props.load(is); is.close(); } catch (IOException e) { return; } FileInfo fi = new FileInfo(); fi.unit = props.getProperty("unit", ""); Integer n_cf = getInteger(props, "cf"); if (n_cf != null) { fi.calibrationFunction = n_cf.intValue(); } double c[] = new double[5]; int coefficientsCount = 0; for (int i = 0; i < 5; i++) { Double n_ci = getDouble(props, "c" + i); if (n_ci == null) { break; } c[i] = n_ci.doubleValue(); coefficientsCount++; } if (coefficientsCount >= 2) { fi.coefficients = new double[coefficientsCount]; for (int i = 0; i < coefficientsCount; i++) { fi.coefficients[i] = c[i]; } } fi.valueUnit = props.getProperty("vunit"); Integer n_images = getInteger(props, "images"); if (n_images != null && n_images.intValue() > 1) { fi.nImages = n_images.intValue(); if (fi.nImages != imp.getStackSize()) { throw new Exception("Number of images in description string (" + fi.nImages + ") does not match number if slices in the image (" + imp.getStackSize() + ")."); } } Calibration calib = imp.getCalibration(); if (calib == null) { calib = new Calibration(imp); } calib.setFunction(fi.calibrationFunction, fi.coefficients, fi.valueUnit); calib.setUnit(fi.unit); if (fi.nImages > 1) { Double n_spacing = getDouble(props, "spacing"); if (n_spacing != null && n_spacing.doubleValue() != 0.0) { calib.pixelDepth = n_spacing.doubleValue(); } Double n_fps = getDouble(props, "fps"); if (n_fps != null && n_fps.doubleValue() != 0.0) { calib.frameInterval = 1.0 / n_fps.doubleValue(); } } imp.setCalibration(calib); } /* * */ private static Double getDouble(Properties props, String key) { String s = props.getProperty(key); if (s != null) { try { return Double.valueOf(s); } catch (NumberFormatException e) { } } return null; } /* * */ private static Integer getInteger(Properties props, String key) { String s = props.getProperty(key); if (s != null) { try { return Integer.valueOf(s); } catch (NumberFormatException e) { } } return null; } }