/** * Save the specified sequence in the specified file.<br> * When the sequence contains severals image the multipleFile flag is used to indicate<br> * if images are saved as separate files (file then specify a directory) or not.<br> * zMin - zMax and tMin - tMax define the Z and T images range to save.<br> * * @param formatWriter writer used to save sequence (define the image format) * @param sequence sequence to save * @param filePath file name where we want to save sequence * @param zMin start Z position to save * @param zMax end Z position to save * @param tMin start T position to save * @param tMax end T position to save * @param fps frame rate for AVI sequence save * @param saveFrame progress frame for save operation (can be null) * @throws ServiceException * @throws IOException * @throws FormatException */ private static void save( IFormatWriter formatWriter, Sequence sequence, String filePath, int zMin, int zMax, int tMin, int tMax, int fps, FileFrame saveFrame) throws ServiceException, FormatException, IOException { final File file = new File(filePath); final IFormatWriter writer; if (formatWriter == null) writer = getWriter(file, ImageFileFormat.TIFF); else writer = formatWriter; // TODO: temporary fix for the "incorrect close operation" bug in Bio-Formats // with OME TIF writer, remove it when fixed. // { // try // { // writer = formatWriter.getClass().newInstance(); // } // catch (Exception e) // { // throw new ServiceException("Can't create new writer instance: " + e); // } // } if (writer == null) throw new UnknownFormatException( "Can't find a valid image writer for the specified file: " + filePath); // first delete the file else LOCI won't save it correctly if (file.exists()) file.delete(); // ensure parent directory exist FileUtil.ensureParentDirExist(file); final int sizeC = sequence.getSizeC(); final boolean separateChannel = getSeparateChannelFlag(writer, sequence.getColorModel()); // set settings writer.setFramesPerSecond(fps); // generate metadata writer.setMetadataRetrieve( MetaDataUtil.generateMetaData( sequence, (zMax - zMin) + 1, (tMax - tMin) + 1, separateChannel)); // no interleave (XP default viewer want interleaved channel to correctly read image) writer.setInterleaved(false); // set id writer.setId(filePath); // init writer.setSeries(0); // usually give better save performance writer.setWriteSequentially(true); // get endianess final boolean littleEndian = !writer.getMetadataRetrieve().getPixelsBinDataBigEndian(0, 0).booleanValue(); byte[] data = null; try { int imageIndex = 0; // XYCZT order is important here (see metadata) for (int t = tMin; t <= tMax; t++) { for (int z = zMin; z <= zMax; z++) { if ((saveFrame != null) && saveFrame.isCancelRequested()) return; final IcyBufferedImage image = sequence.getImage(t, z); // separated channel data if (separateChannel) { for (int c = 0; c < sizeC; c++) { if (image != null) { // avoid multiple allocation data = image.getRawData(c, data, 0, littleEndian); writer.saveBytes(imageIndex, data); } imageIndex++; } } else { if (image != null) { // avoid multiple allocation data = image.getRawData(data, 0, littleEndian); writer.saveBytes(imageIndex, data); } imageIndex++; } if (saveFrame != null) saveFrame.incPosition(); } } } finally { // always close writer after a file has been saved writer.close(); } }
/** Save a single image from bytes buffer to the specified file. */ private static void saveImage( IFormatWriter formatWriter, byte[] data, int width, int height, int numChannel, boolean separateChannel, DataType dataType, File file, boolean force) throws FormatException, IOException { final String filePath = FileUtil.cleanPath(FileUtil.getGenericPath(file.getAbsolutePath())); if (FileUtil.exists(filePath)) { // forced ? first delete the file else LOCI won't save it if (force) FileUtil.delete(filePath, true); else throw new IOException("File already exists"); } // ensure parent directory exist FileUtil.ensureParentDirExist(filePath); final IFormatWriter writer; final boolean separateCh; if (formatWriter == null) { // get the writer writer = getWriter(FileUtil.getFileExtension(filePath, false), ImageFileFormat.TIFF); // prepare the metadata try { separateCh = getSeparateChannelFlag(writer, numChannel, dataType); writer.setMetadataRetrieve( MetaDataUtil.generateMetaData(width, height, numChannel, dataType, separateCh)); } catch (ServiceException e) { System.err.println("Saver.saveImage(...) error :"); IcyExceptionHandler.showErrorMessage(e, true); } } else { // ready to use writer (metadata already prepared) writer = formatWriter; separateCh = separateChannel; } // we never interleaved data even if some image viewer need it to correctly read image (win XP // viewer) writer.setInterleaved(false); writer.setId(filePath); writer.setSeries(0); // usually give better save performance writer.setWriteSequentially(true); try { // separated channel data if (separateChannel) { final int pitch = width * height * dataType.getSize(); final byte[] dataChannel = new byte[pitch]; int offset = 0; for (int c = 0; c < numChannel; c++) { System.arraycopy(data, offset, dataChannel, 0, pitch); writer.saveBytes(c, dataChannel); offset += pitch; } } else // save all data at once writer.saveBytes(0, data); } catch (Exception e) { System.err.println("Saver.saveImage(...) error :"); IcyExceptionHandler.showErrorMessage(e, true); } writer.close(); }