/*
* Copyright (c) 2008 Los Alamos National Security, LLC.
*
* Los Alamos National Laboratory
* Research Library
* Digital Library Research & Prototyping Team
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package gov.lanl.adore.djatoka;
import gov.lanl.adore.djatoka.io.FormatFactory;
import gov.lanl.adore.djatoka.io.FormatWriterParams;
import gov.lanl.adore.djatoka.io.IWriter;
import gov.lanl.adore.djatoka.util.IOUtils;
import gov.lanl.adore.djatoka.util.ImageProcessingUtils;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.log4j.Logger;
/**
* Extraction Processor - Intermediate processor between DjatokaExtract
* and IExtract implementation. Works with the format factory to convert
* the extracted region to desired output directory. Handles I/O and post
* extraction transform.
* @author Ryan Chute
*
*/
public class DjatokaExtractProcessor {
static Logger logger = Logger.getLogger(DjatokaExtractProcessor.class);
private static String STDIN = "/dev/stdin";
private static FormatFactory fmtFactory = new FormatFactory();
private IExtract extractImpl;
/**
* Constructor requiring an IExtract implementation
* @param impl an IExtract implementation
*/
public DjatokaExtractProcessor(IExtract impl) {
this.extractImpl = impl;
}
/**
* Sets the format factory used to serialize extracted region
* @param ff the format factory used to serialize extracted region
* @throws DjatokaException
*/
public void setFormatFactory(FormatFactory ff) throws DjatokaException {
fmtFactory = ff;
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input absolute file path for input file.
* @param output absolute file path for output file.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param fmtId mimetype identifier of output file format (e.g. "image/jpeg")
* @throws DjatokaException
*/
public void extractImage(String input, String output,
DjatokaDecodeParam params, String fmtId) throws DjatokaException {
IWriter w = fmtFactory.getWriter(fmtId);
extractImage(input, output, params, w);
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input absolute file path for input file.
* @param output absolute file path for output file.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param outputParams
* @throws DjatokaException
*/
public void extractImage(String input, String output,
DjatokaDecodeParam params, FormatWriterParams outputParams)
throws DjatokaException {
IWriter w = fmtFactory.getWriter(outputParams.getFormatId(),
outputParams.getFormatProps());
extractImage(input, output, params, w);
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input InputStream containing a JPEG 2000 image bitstream.
* @param output absolute file path for output file.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param fmtId mimetype identifier of output file format (e.g. "image/jpeg")
* @throws DjatokaException
*/
public void extractImage(InputStream input, OutputStream output,
DjatokaDecodeParam params, String fmtId) throws DjatokaException {
IWriter w = fmtFactory.getWriter(fmtId);
extractImage(input, output, params, w);
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input absolute file path for input file.
* @param os OutputStream to serialize formatted output image to.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param fmtId mimetype identifier of output file format (e.g. "image/jpeg")
* @throws DjatokaException
*/
public void extractImage(String input, OutputStream os,
DjatokaDecodeParam params, String fmtId) throws DjatokaException {
IWriter w = fmtFactory.getWriter(fmtId);
extractImage(input, os, params, w);
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input absolute file path for input file.
* @param output absolute file path for output file.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param w format writer to be used to serialize extracted region.
* @throws DjatokaException
*/
public void extractImage(String input, String output,
DjatokaDecodeParam params, IWriter w) throws DjatokaException {
File in = null;
String dest = output;
if (input.equals(STDIN)) {
try {
in = File.createTempFile("tmp", ".jp2");
input = in.getAbsolutePath();
in.deleteOnExit();
IOUtils.copyFile(new File(STDIN), in);
} catch (IOException e) {
logger.error("Unable to process image from " + STDIN + ": " + e.getMessage());
throw new DjatokaException(e);
}
}
BufferedImage bi = extractImpl.process(input, params);
if (bi != null) {
if (params.getScalingFactor() != 1.0 || params.getScalingDimensions() != null)
bi = applyScaling(bi, params);
if (params.getTransform() != null)
bi = params.getTransform().run(bi);
try {
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(new File(dest)));
w.write(bi, os);
os.close();
} catch (FileNotFoundException e) {
logger.error("Requested file was not found: " + dest);
throw new DjatokaException(e);
} catch (IOException e) {
logger.error("Error attempting to close: " + dest);
throw new DjatokaException(e);
}
}
if (in != null)
in.delete();
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input input absolute file path for input file.
* @param os OutputStream to serialize formatted output image to.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param w format writer to be used to serialize extracted region.
* @throws DjatokaException
*/
public void extractImage(String input, OutputStream os,
DjatokaDecodeParam params, IWriter w) throws DjatokaException {
File in = null;
// If coming in from stdin, copy to tmp file
if (input.equals(STDIN)) {
try {
in = File.createTempFile("tmp", ".jp2");
input = in.getAbsolutePath();
in.deleteOnExit();
IOUtils.copyFile(new File(STDIN), in);
} catch (IOException e) {
logger.error("Unable to process image from " + STDIN + ": " + e.getMessage());
throw new DjatokaException(e);
}
}
BufferedImage bi = extractImpl.process(input, params);
if (bi != null) {
if (params.getScalingFactor() != 1.0 || params.getScalingDimensions() != null)
bi = applyScaling(bi, params);
if (params.getTransform() != null)
bi = params.getTransform().run(bi);
w.write(bi, os);
}
if (in != null)
in.delete();
}
/**
* Extract region or resolution level from JPEG 2000 image file.
* @param input input absolute file path for input file.
* @param os OutputStream to serialize formatted output image to.
* @param params DjatokaDecodeParam instance containing region and transform settings.
* @param w format writer to be used to serialize extracted region.
* @throws DjatokaException
*/
public void extractImage(InputStream input, OutputStream os,
DjatokaDecodeParam params, IWriter w) throws DjatokaException {
BufferedImage bi = extractImpl.process(input, params);
if (bi != null) {
if (params.getScalingFactor() != 1.0 || params.getScalingDimensions() != null)
bi = applyScaling(bi, params);
if (params.getTransform() != null)
bi = params.getTransform().run(bi);
w.write(bi, os);
}
}
/**
* Apply scaling, if Scaling Factor != to 1.0 then check ScalingDimensions
* for w,h vars. A scaling factor value must be greater than 0 and less than 2.
* Note that ScalingFactor overrides ScalingDimensions.
* @param bi BufferedImage to be scaled.
* @param params DjatokaDecodeParam containing ScalingFactor or ScalingDimensions vars
* @return scaled instance of provided BufferedImage
*/
private static BufferedImage applyScaling(BufferedImage bi, DjatokaDecodeParam params) {
if (params.getScalingFactor() != 1.0
&& params.getScalingFactor() > 0
&& params.getScalingFactor() < 3)
bi = ImageProcessingUtils.scale(bi,params.getScalingFactor());
else if (params.getScalingDimensions() != null
&& params.getScalingDimensions().length == 2) {
int width = params.getScalingDimensions()[0];
if (width >= 3 * bi.getWidth())
return bi;
int height = params.getScalingDimensions()[1];
if (height >= 3 * bi.getHeight())
return bi;
bi = ImageProcessingUtils.scale(bi, width, height);
}
return bi;
}
}