/*
* #%L
* OME Bio-Formats package for reading and converting biological file formats.
* %%
* Copyright (C) 2005 - 2015 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* 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, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package loci.formats.in;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import loci.common.Constants;
import loci.common.IniList;
import loci.common.IniParser;
import loci.common.IniTable;
import loci.common.Location;
import loci.common.RandomAccessInputStream;
import loci.common.services.ServiceException;
import loci.formats.CoreMetadata;
import loci.formats.FormatException;
import loci.formats.FormatReader;
import loci.formats.FormatTools;
import loci.formats.MetadataTools;
import loci.formats.codec.JPEGTileDecoder;
import loci.formats.meta.MetadataStore;
import loci.formats.services.JPEGTurboService;
import loci.formats.services.JPEGTurboServiceImpl;
import ome.xml.model.primitives.PositiveFloat;
import ome.units.quantity.Length;
/**
* HamamatsuVMSReader is the file format reader for Hamamatsu VMS datasets.
*
* @author Melissa Linkert melissa at glencoesoftware.com
*/
public class HamamatsuVMSReader extends FormatReader {
// -- Constants --
private static final int MAX_SIZE = 2048;
// -- Fields --
private int initializedSeries = -1;
private int initializedPlane = -1;
private ArrayList<String> files = new ArrayList<String>();
private String[][][] tileFiles;
private String[] jpeg;
private JPEGTurboService service;
private HashMap<String, long[]> restartMarkers =
new HashMap<String, long[]>();
// -- Constructor --
/** Constructs a new Hamamatsu VMS reader. */
public HamamatsuVMSReader() {
super("Hamamatsu VMS", "vms");
domains = new String[] {FormatTools.HISTOLOGY_DOMAIN};
datasetDescription = "One .vms file plus several .jpg files";
}
// -- IFormatReader API methods --
/* @see loci.formats.IFormatReader#getOptimalTileWidth() */
@Override
public int getOptimalTileWidth() {
FormatTools.assertId(currentId, true, 1);
return 1024;
}
/* @see loci.formats.IFormatReader#getOptimalTileHeight() */
@Override
public int getOptimalTileHeight() {
FormatTools.assertId(currentId, true, 1);
return 1024;
}
/* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */
@Override
public String[] getSeriesUsedFiles(boolean noPixels) {
FormatTools.assertId(currentId, true, 1);
if (noPixels) {
return new String[] {currentId};
}
ArrayList<String> f = new ArrayList<String>();
f.add(currentId);
f.add(jpeg[getSeries()]);
f.addAll(files);
return f.toArray(new String[f.size()]);
}
/**
* @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int)
*/
@Override
public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
throws FormatException, IOException
{
FormatTools.checkPlaneParameters(this, no, buf.length, x, y, w, h);
String file = jpeg[getCoreIndex()];
if (getSizeX() <= MAX_SIZE || getSizeY() <= MAX_SIZE) {
JPEGReader reader = new JPEGReader();
reader.setId(file);
reader.openBytes(0, buf, x, y, w, h);
reader.close();
return buf;
}
if (service == null) {
service = new JPEGTurboServiceImpl();
}
try {
if (initializedSeries != getCoreIndex() || initializedPlane != no) {
service.close();
if (restartMarkers.containsKey(file)) {
service.setRestartMarkers(restartMarkers.get(file));
}
else {
service.setRestartMarkers(null);
}
// closing the service will close this file
RandomAccessInputStream s = new RandomAccessInputStream(file);
service.initialize(s, getSizeX(), getSizeY());
restartMarkers.put(file, service.getRestartMarkers());
initializedSeries = getCoreIndex();
initializedPlane = no;
}
service.getTile(buf, x, y, w, h);
}
catch (ServiceException e) {
throw new FormatException(e);
}
return buf;
}
/* @see loci.formats.IFormatReader#close(boolean) */
@Override
public void close(boolean fileOnly) throws IOException {
super.close(fileOnly);
if (!fileOnly) {
tileFiles = null;
files.clear();
if (service != null) {
service.close();
service = null;
}
jpeg = null;
restartMarkers.clear();
initializedSeries = -1;
initializedPlane = -1;
}
}
// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
super.initFile(id);
in = new RandomAccessInputStream(id);
IniParser parser = new IniParser();
IniList layout = parser.parseINI(new BufferedReader(
new InputStreamReader(in, Constants.ENCODING)));
IniTable slideInfo = layout.getTable("Virtual Microscope Specimen");
int nLayers = Integer.parseInt(slideInfo.get("NoLayers"));
int nRows = Integer.parseInt(slideInfo.get("NoJpegRows"));
int nCols = Integer.parseInt(slideInfo.get("NoJpegColumns"));
String imageFile = slideInfo.get("ImageFile");
String mapFile = slideInfo.get("MapFile");
String optimisationFile = slideInfo.get("OptimisationFile");
String macroFile = slideInfo.get("MacroImage");
Double physicalWidth = new Double(slideInfo.get("PhysicalWidth"));
Double physicalHeight = new Double(slideInfo.get("PhysicalHeight"));
Double magnification = new Double(slideInfo.get("SourceLens"));
Double macroWidth = new Double(slideInfo.get("PhysicalMacroWidth"));
Double macroHeight = new Double(slideInfo.get("PhysicalMacroHeight"));
for (String key : slideInfo.keySet()) {
addGlobalMeta(key, slideInfo.get(key));
}
Location dir = new Location(id).getParentFile();
tileFiles = new String[nLayers][nRows][nCols];
for (int layer=0; layer<nLayers; layer++) {
for (int row=0; row<nRows; row++) {
for (int col=0; col<nCols; col++) {
tileFiles[layer][row][col] =
slideInfo.get("ImageFile(" + col + "," + row + ")");
if (tileFiles[layer][row][col] != null) {
files.add(
new Location(dir, tileFiles[layer][row][col]).getAbsolutePath());
}
}
}
}
if (imageFile != null) {
imageFile = new Location(dir, imageFile).getAbsolutePath();
}
if (mapFile != null) {
mapFile = new Location(dir, mapFile).getAbsolutePath();
}
if (optimisationFile != null) {
optimisationFile = new Location(dir, optimisationFile).getAbsolutePath();
files.add(optimisationFile);
}
if (macroFile != null) {
macroFile = new Location(dir, macroFile).getAbsolutePath();
}
jpeg = new String[3];
int seriesCount = 3;
core.clear();
for (int i=0; i<seriesCount; i++) {
String file = null;
switch (i) {
case 0:
file = imageFile;
break;
case 1:
file = macroFile;
break;
case 2:
file = mapFile;
break;
}
jpeg[i] = file;
JPEGTileDecoder decoder = new JPEGTileDecoder();
RandomAccessInputStream s = new RandomAccessInputStream(file);
int[] dims = decoder.preprocess(s);
s.close();
CoreMetadata m = new CoreMetadata();
m.sizeX = dims[0];
m.sizeY = dims[1];
m.sizeZ = 1;
m.sizeC = 3;
m.sizeT = 1;
m.rgb = true;
m.imageCount = 1;
m.dimensionOrder = "XYCZT";
m.pixelType = FormatTools.UINT8;
m.interleaved = m.sizeX > MAX_SIZE && m.sizeY > MAX_SIZE;
m.thumbnail = i > 0;
core.add(m);
}
CoreMetadata ms0 = core.get(0);
MetadataStore store = makeFilterMetadata();
MetadataTools.populatePixels(store, this);
String path = new Location(currentId).getAbsoluteFile().getName();
store.setImageName(path + " full resolution", 0);
store.setImageName(path + " macro", 1);
store.setImageName(path + " map", 2);
if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
Length sizeX =
FormatTools.getPhysicalSizeX(physicalWidth / ms0.sizeX);
Length sizeY =
FormatTools.getPhysicalSizeY(physicalHeight / ms0.sizeY);
Length macroSizeX =
FormatTools.getPhysicalSizeX(macroWidth / core.get(1).sizeX);
Length macroSizeY =
FormatTools.getPhysicalSizeY(macroHeight / core.get(1).sizeY);
if (sizeX != null) {
store.setPixelsPhysicalSizeX(sizeX, 0);
}
if (sizeY != null) {
store.setPixelsPhysicalSizeY(sizeY, 0);
}
if (macroSizeX != null) {
store.setPixelsPhysicalSizeX(macroSizeX, 1);
}
if (macroSizeY != null) {
store.setPixelsPhysicalSizeY(macroSizeY, 1);
}
String instrumentID = MetadataTools.createLSID("Instrument", 0);
store.setInstrumentID(instrumentID, 0);
store.setImageInstrumentRef(instrumentID, 0);
String objectiveID = MetadataTools.createLSID("Objective", 0, 0);
store.setObjectiveID(objectiveID, 0, 0);
store.setObjectiveNominalMagnification(magnification, 0, 0);
store.setObjectiveSettingsID(objectiveID, 0);
}
}
}