// // LociUploader.java // /* OME Plugins for ImageJ: a collection of ImageJ plugins including the Download from OME and Upload to OME plugins. Copyright (C) 2005-2010 Melissa Linkert, Philip Huettl and Curtis Rueden. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package loci.plugins.ome; import ij.IJ; import ij.ImagePlus; import ij.ImageStack; import ij.Prefs; import ij.WindowManager; import ij.gui.GenericDialog; import ij.io.FileInfo; import ij.plugin.PlugIn; import ij.process.ColorProcessor; import java.awt.TextField; import java.io.IOException; import java.util.HashSet; import loci.common.DataTools; import loci.common.services.DependencyException; import loci.common.services.ServiceException; import loci.common.services.ServiceFactory; import loci.formats.FormatTools; import loci.formats.MetadataTools; import loci.formats.meta.MetadataRetrieve; import loci.formats.meta.MetadataStore; import loci.formats.services.OMEXMLService; import loci.ome.io.OMEWriter; import loci.plugins.util.LibraryChecker; import ome.xml.model.enums.DimensionOrder; import ome.xml.model.enums.EnumerationException; import ome.xml.model.enums.PixelType; import ome.xml.model.primitives.PositiveInteger; /** * ImageJ plugin for uploading images to an OME server. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/ome-plugins/src/loci/plugins/ome/LociUploader.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/ome-plugins/src/loci/plugins/ome/LociUploader.java;hb=HEAD">Gitweb</a></dd></dl> * * @author Melissa Linkert linket at wisc.edu */ public class LociUploader implements PlugIn { // -- Fields -- private String server; private String user; private String pass; private boolean canceled = false; // -- PlugIn API methods -- public void run(String arg) { // check that we can safely execute the plugin if (!LibraryChecker.checkJava() || !LibraryChecker.checkImageJ()) return; HashSet missing = new HashSet(); LibraryChecker.checkLibrary(LibraryChecker.Library.BIO_FORMATS, missing); LibraryChecker.checkLibrary(LibraryChecker.Library.OME_JAVA_XML, missing); LibraryChecker.checkLibrary(LibraryChecker.Library.OME_JAVA_DS, missing); if (!LibraryChecker.checkMissing(missing)) return; promptForLogin(); if (canceled) { canceled = false; return; } uploadStack(); } // -- Helper methods -- /** Open a dialog box that prompts for a username, password, and server. */ private void promptForLogin() { GenericDialog prompt = new GenericDialog("Login to OME"); prompt.addStringField("Server: ", Prefs.get("uploader.server", ""), 60); prompt.addStringField("Username: ", Prefs.get("uploader.user", ""), 60); prompt.addStringField("Password: ", "", 60); ((TextField) prompt.getStringFields().get(2)).setEchoChar('*'); prompt.showDialog(); if (prompt.wasCanceled()) { canceled = true; return; } server = prompt.getNextString(); user = prompt.getNextString(); pass = prompt.getNextString(); Prefs.set("uploader.server", server); Prefs.set("uploader.user", user); } /** Log in to the OME server and upload the current image stack. */ private void uploadStack() { try { IJ.showStatus("Starting upload..."); OMEWriter ul = new OMEWriter(); String id = server + "?user=" + user + "&password=" + pass; ImagePlus imp = WindowManager.getCurrentImage(); if (imp == null) { IJ.error("No open images!"); IJ.showStatus(""); return; } ImageStack is = imp.getImageStack(); FileInfo fi = imp.getOriginalFileInfo(); MetadataStore store = null; OMEXMLService service = null; try { ServiceFactory factory = new ServiceFactory(); service = (OMEXMLService) factory.getInstance(OMEXMLService.class); } catch (DependencyException e) { IJ.error("OME-XML library not found."); } // if we opened this stack with the Bio-Formats importer, then the // appropriate OME-XML is in fi.description if (fi != null && fi.description != null && fi.description.endsWith("</OME>")) { Exception exc = null; try { store = service.createOMEXMLMetadata(fi.description); } catch (ServiceException e) { exc = e; } if (exc != null) { IJ.error("Could not create OMEXMLMetadataStore"); } } else { Exception exc = null; try { store = service.createOMEXMLMetadata(); } catch (ServiceException e) { exc = e; } if (exc != null) { IJ.error("Could not create OMEXMLMetadataStore"); } int pixelType = FormatTools.UINT8; switch (imp.getBitDepth()) { case 16: pixelType = FormatTools.UINT16; break; case 32: pixelType = FormatTools.FLOAT; break; } store.setPixelsSizeX( new PositiveInteger(new Integer(imp.getWidth())), 0); store.setPixelsSizeY( new PositiveInteger(new Integer(imp.getHeight())), 0); store.setPixelsSizeZ( new PositiveInteger(new Integer(imp.getNSlices())), 0); store.setPixelsSizeC( new PositiveInteger(new Integer(imp.getNChannels())), 0); store.setPixelsSizeT( new PositiveInteger(new Integer(imp.getNFrames())), 0); try { store.setPixelsType( PixelType.fromString(FormatTools.getPixelTypeString(pixelType)), 0); } catch (EnumerationException e) { } store.setPixelsBinDataBigEndian(fi == null ? Boolean.TRUE : new Boolean(!fi.intelByteOrder), 0, 0); // TODO : figure out a way to calculate the dimension order store.setPixelsDimensionOrder(DimensionOrder.XYCZT, 0); String name = fi == null ? imp.getTitle() : fi.fileName; store.setImageName(name, 0); if (fi != null) store.setImageDescription(fi.info, 0); } MetadataRetrieve retrieve = (MetadataRetrieve) store; ul.setMetadataRetrieve(retrieve); ul.setId(id); boolean little = !retrieve.getPixelsBinDataBigEndian(0, 0).booleanValue(); for (int i=0; i<is.getSize(); i++) { IJ.showStatus("Reading plane " + (i+1) + "/" + is.getSize()); Object pix = is.getProcessor(i + 1).getPixels(); byte[] toUpload = null; if (pix instanceof byte[]) { toUpload = (byte[]) pix; } else if (pix instanceof short[]) { short[] s = (short[]) pix; toUpload = new byte[s.length * 2]; for (int j=0; j<s.length; j++) { DataTools.unpackBytes(s[j], toUpload, j * 2, 2, little); } } else if (pix instanceof int[]) { if (is.getProcessor(i+1) instanceof ColorProcessor) { byte[][] rgb = new byte[3][((int[]) pix).length]; ((ColorProcessor) is.getProcessor(i+1)).getRGB(rgb[0], rgb[1], rgb[2]); int channels = ((Integer) retrieve.getPixelsSizeC(0).getValue()).intValue(); if (channels > 3) channels = 3; toUpload = new byte[channels * rgb[0].length]; for (int j=0; j<channels; j++) { System.arraycopy(rgb[j], 0, toUpload, 0, rgb[j].length); } } else { int[] p = (int[]) pix; toUpload = new byte[4 * p.length]; for (int j=0; j<p.length; j++) { DataTools.unpackBytes(p[j], toUpload, j * 4, 4, little); } } } else if (pix instanceof float[]) { float[] f = (float[]) pix; toUpload = new byte[f.length * 4]; for (int j=0; j<f.length; j++) { int k = Float.floatToIntBits(f[j]); DataTools.unpackBytes(k, toUpload, j * 4, 4, little); } } ul.saveBytes(i, toUpload); } IJ.showStatus("Sending data to server..."); ul.close(); IJ.showStatus("Upload finished."); } catch (Exception e) { IJ.error("Upload failed:\n" + e); e.printStackTrace(); } } }