Package gov.lanl.adore.djatoka.kdu

Source Code of gov.lanl.adore.djatoka.kdu.KduCompressExe

/*
* 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.kdu;

import gov.lanl.adore.djatoka.DjatokaEncodeParam;
import gov.lanl.adore.djatoka.DjatokaException;
import gov.lanl.adore.djatoka.ICompress;
import gov.lanl.adore.djatoka.util.IOUtils;
import gov.lanl.adore.djatoka.util.ImageProcessingUtils;
import gov.lanl.adore.djatoka.util.ImageRecord;
import gov.lanl.adore.djatoka.util.ImageRecordUtils;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import com.martiansoftware.jsap.CommandLineTokenizer;

/**
* Java bridge for kdu_compress application
*
* @author Ryan Chute
* @author <a href="mailto:ksclarke@gmail.com">Kevin S. Clarke</a>
*/
public class KduCompressExe implements ICompress {

    private static Logger LOGGER = LoggerFactory.getLogger(KduCompressExe.class);

    private static boolean isWindows = false;

    private static String env;

    private static String exe;

    private static String[] envParams;

    /** The name of the compressing executable */
    public static final String KDU_COMPRESS_EXE = "kdu_compress";

    public static final String STDOUT = "/dev/stdout";

    static {
        env = System.getProperty("kakadu.home") + System.getProperty("file.separator");
        exe =
                env +
                        ((System.getProperty("os.name").startsWith("Win")) ? KDU_COMPRESS_EXE + ".exe"
                                : KDU_COMPRESS_EXE);

        if (System.getProperty("os.name").startsWith("Mac")) {
            envParams = new String[] { "DYLD_LIBRARY_PATH=" + System.getProperty("DYLD_LIBRARY_PATH") };
        } else if (System.getProperty("os.name").startsWith("Win")) {
            isWindows = true;
        } else if (System.getProperty("os.name").startsWith("Linux")) {
            envParams = new String[] { "LD_LIBRARY_PATH=" + System.getProperty("LD_LIBRARY_PATH") };
        } else if (System.getProperty("os.name").startsWith("Solaris")) {
            envParams = new String[] { "LD_LIBRARY_PATH=" + System.getProperty("LD_LIBRARY_PATH") };
        }

        LOGGER.debug("envParams: " + ((envParams != null) ? envParams[0] + " | " : "") + exe);
    }

    /**
     * Constructor which expects the following system properties to be defined and exported.
     * <p/>
     * (Win/Linux/UNIX) LD_LIBRARY_PATH=$DJATOKA_HOME/lib/$DJATOKA_OS
     * <p/>
     * (Mac OS-X) DYLD_LIBRARY_PATH=$DJATOKA_HOME/lib/$DJATOKA_OS
     *
     * @throws Exception
     */
    public KduCompressExe() {
        env = System.getProperty("kakadu.home");

        if (env == null) {
            LOGGER.error("kakadu.home is not defined");
            throw new RuntimeException("kakadu.home is not defined");
        }
    }

    /**
     * Compress input BufferedImage using provided DjatokaEncodeParam parameters.
     *
     * @param bi in-memory image to be compressed
     * @param output absolute file path for output file.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @throws DjatokaException
     */
    public void compressImage(BufferedImage bi, String output, DjatokaEncodeParam params) throws DjatokaException {
        if (params == null) {
            params = new DjatokaEncodeParam();
        }
        if (params.getLevels() == 0) {
            params.setLevels(ImageProcessingUtils.getLevelCount(bi.getWidth(), bi.getHeight()));
        }
        File in = null;
        try {
            in = IOUtils.createTempTiff(bi);
            compressImage(in.getAbsolutePath(), output, params);
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } finally {
            if (in != null) {
                if (!in.delete() && LOGGER.isWarnEnabled()) {
                    LOGGER.warn("File not deleted: {}", in);
                }
            }
        }
    }

    /**
     * Compress input BufferedImage using provided DjatokaEncodeParam parameters.
     *
     * @param bi in-memory image to be compressed
     * @param output OutputStream to serialize compressed image.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @throws DjatokaException
     */
    public void compressImage(BufferedImage bi, OutputStream output, DjatokaEncodeParam params)
            throws DjatokaException {
        if (params == null) {
            params = new DjatokaEncodeParam();
        }
        if (params.getLevels() == 0) {
            params.setLevels(ImageProcessingUtils.getLevelCount(bi.getWidth(), bi.getHeight()));
        }
        File in = null;
        File out = null;
        try {
            in = IOUtils.createTempTiff(bi);
            out = File.createTempFile("tmp", ".jp2");
            compressImage(in.getAbsolutePath(), out.getAbsolutePath(), params);
            IOUtils.copyStream(new FileInputStream(out), output);
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        }

        if (in != null) {
            if (!in.delete() && LOGGER.isWarnEnabled()) {
                LOGGER.warn("File not deleted: {}", in);
            }
        }
        if (out != null) {
            if (!out.delete() && LOGGER.isWarnEnabled()) {
                LOGGER.warn("File not deleted: {}", out);
            }
        }
    }

    /**
     * Compress input using provided DjatokaEncodeParam parameters.
     *
     * @param input InputStream containing TIFF image bitstream
     * @param output absolute file path for output file.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @throws DjatokaException
     */
    public void compressImage(InputStream input, String output, DjatokaEncodeParam params) throws DjatokaException {
        if (params == null) {
            params = new DjatokaEncodeParam();
        }
        File inputFile;
        try {
            inputFile = File.createTempFile("tmp", ".tif");
            inputFile.deleteOnExit();
            IOUtils.copyStream(input, new FileOutputStream(inputFile));
            if (params.getLevels() == 0) {
                ImageRecord dim = ImageRecordUtils.getImageDimensions(inputFile.getAbsolutePath());
                params.setLevels(ImageProcessingUtils.getLevelCount(dim.getWidth(), dim.getHeight()));
                dim = null;
            }
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        }

        compressImage(inputFile.getAbsolutePath(), output, params);

        if (inputFile != null) {
            inputFile.delete();
        }
    }

    /**
     * Compress input using provided DjatokaEncodeParam parameters.
     *
     * @param input InputStream containing TIFF image bitstream
     * @param output OutputStream to serialize compressed image.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @throws DjatokaException
     */
    public void compressImage(InputStream input, OutputStream output, DjatokaEncodeParam params)
            throws DjatokaException {
        if (params == null) {
            params = new DjatokaEncodeParam();
        }
        File inputFile = null;
        try {
            inputFile = File.createTempFile("tmp", ".tif");
            IOUtils.copyStream(input, new FileOutputStream(inputFile));
            if (params.getLevels() == 0) {
                ImageRecord dim = ImageRecordUtils.getImageDimensions(inputFile.getAbsolutePath());
                params.setLevels(ImageProcessingUtils.getLevelCount(dim.getWidth(), dim.getHeight()));
                dim = null;
            }
        } catch (IOException e1) {
            LOGGER.error("Unexpected file format; expecting uncompressed TIFF", e1);
            throw new DjatokaException("Unexpected file format; expecting uncompressed TIFF");
        }

        String out = STDOUT;
        File winOut = null;
        if (isWindows) {
            try {
                winOut = File.createTempFile("pipe_", ".jp2");
            } catch (IOException e) {
                LOGGER.error(e.getMessage(), e);
                throw new DjatokaException(e.getMessage(), e);
            }
            out = winOut.getAbsolutePath();
        }

        String command = getKduCompressCommand(inputFile.getAbsolutePath(), out, params);
        String[] cmdParts = CommandLineTokenizer.tokenize(command);
        Runtime rt = Runtime.getRuntime();
        try {
            final Process process = rt.exec(cmdParts, envParams, new File(env));
            if (out.equals(STDOUT)) {
                IOUtils.copyStream(process.getInputStream(), output);
            } else if (isWindows) {
                FileInputStream fis = new FileInputStream(out);
                IOUtils.copyStream(fis, output);
                fis.close();
            }
            process.waitFor();
            if (process != null) {
                String errorCheck = null;
                try {
                    errorCheck = new String(IOUtils.getByteArray(process.getErrorStream()));
                } catch (Exception e1) {
                    LOGGER.error(e1.getMessage(), e1);
                }
                process.getInputStream().close();
                process.getOutputStream().close();
                process.getErrorStream().close();
                process.destroy();
                if (errorCheck != null) {
                    throw new DjatokaException(errorCheck);
                }
            }
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        }

        if (inputFile != null) {
            if (!inputFile.delete() && LOGGER.isWarnEnabled()) {
                LOGGER.warn("File not deleted: {}", inputFile);
            }
        }
        if (winOut != null) {
            if (!winOut.delete() && LOGGER.isWarnEnabled()) {
                LOGGER.warn("File not deleted: {}", winOut);
            }
        }
    }

    /**
     * Compress input using provided DjatokaEncodeParam parameters.
     *
     * @param input absolute file path for input file.
     * @param output absolute file path for output file.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @throws DjatokaException
     */
    public void compressImage(String input, String output, DjatokaEncodeParam params) throws DjatokaException {
        if (params == null) {
            params = new DjatokaEncodeParam();
        }
        boolean tmp = false;
        File inputFile = null;
        if ((input.toLowerCase().endsWith(".tif") || input.toLowerCase().endsWith(".tiff") || ImageProcessingUtils
                .checkIfTiff(input)) &&
                ImageProcessingUtils.isUncompressedTiff(input)) {
            LOGGER.debug("Processing TIFF: " + input);
            inputFile = new File(input);
        } else {
            if (LOGGER.isDebugEnabled() &&
                    (input.toLowerCase().endsWith(".tif") || input.toLowerCase().endsWith(".tiff"))) {
                LOGGER.debug(input + " : Is tiff? {} | Is uncompressed? {}", ImageProcessingUtils.checkIfTiff(input),
                        ImageProcessingUtils.isUncompressedTiff(input));
            }

            try {
                inputFile = IOUtils.createTempTiff(input);
                tmp = true;
                input = inputFile.getAbsolutePath();
            } catch (Exception e) {
                throw new DjatokaException("Unrecognized file format: " + e.getMessage());
            }
        }

        if (params.getLevels() == 0) {
            ImageRecord dim = ImageRecordUtils.getImageDimensions(inputFile.getAbsolutePath());
            params.setLevels(ImageProcessingUtils.getLevelCount(dim.getWidth(), dim.getHeight()));
            dim = null;
        }

        File outFile = new File(output);
        String command = getKduCompressCommand(new File(input).getAbsolutePath(), outFile.getAbsolutePath(), params);
        String[] cmdParts = CommandLineTokenizer.tokenize(command);
        Runtime rt = Runtime.getRuntime();

        try {
            final Process process = rt.exec(cmdParts, envParams, new File(env));
            process.waitFor();
            if (process != null) {
                String errorCheck = null;

                try {
                    InputStream inStream = process.getErrorStream();
                    errorCheck = new String(IOUtils.getByteArray(inStream));
                } catch (Exception e1) {
                }

                process.getInputStream().close();
                process.getOutputStream().close();
                process.getErrorStream().close();
                process.destroy();

                if (errorCheck != null && !errorCheck.equals("")) {
                    throw new DjatokaException(errorCheck);
                }
            }
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
            throw new DjatokaException(e.getMessage(), e);
        } finally {
            if (tmp) {
                if (!inputFile.delete() && LOGGER.isWarnEnabled()) {
                    LOGGER.warn("File not deleted: {}", inputFile);
                }
            }
        }

        if (!outFile.getAbsolutePath().equals(STDOUT) && !outFile.exists()) {
            throw new DjatokaException("Unknown error occurred during processing.");
        }
    }

    /**
     * Get kdu_compress command line for specified input, output, params.
     *
     * @param input absolute file path for input file.
     * @param output absolute file path for output file.
     * @param params DjatokaEncodeParam containing compression parameters.
     * @return kdu_compress command line for specified input, output, params
     */
    public static final String getKduCompressCommand(String input, String output, DjatokaEncodeParam params) {
        StringBuffer command = new StringBuffer(exe);
        command.append(" -quiet -i ").append(escape(new File(input).getAbsolutePath()));
        command.append(" -o ").append(escape(new File(output).getAbsolutePath()));
        command.append(" ").append(toKduCompressArgs(params));

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Compress command: {}", command.toString());
        }

        return command.toString();
    }

    private static final String escape(String path) {
        if (path.contains(" ")) {
            return "\"" + path + "\"";
        }

        return path;
    }

    private static String toKduCompressArgs(DjatokaEncodeParam params) {
        StringBuffer sb = new StringBuffer();
        if (params.getRate() != null) {
            sb.append("-rate ").append(params.getRate()).append(" ");
        } else {
            sb.append("-slope ").append(params.getSlope()).append(" ");
        }
        if (params.getLevels() > 0) {
            sb.append("Clevels=").append(params.getLevels()).append(" ");
        }
        if (params.getPrecincts() != null) {
            sb.append("Cprecincts=").append(escape(params.getPrecincts()));
            sb.append(" ");
        }
        if (params.getLayers() > 0) {
            sb.append("Clayers=").append(params.getLayers()).append(" ");
        }
        if (params.getProgressionOrder() != null) {
            sb.append("Corder=").append(params.getProgressionOrder()).append(" ");
        }
        if (params.getPacketDivision() != null) {
            sb.append("ORGtparts=").append(params.getPacketDivision()).append(" ");
        }
        if (params.getCodeBlockSize() != null) {
            sb.append("Cblk=").append(escape(params.getCodeBlockSize())).append(" ");
        }
        sb.append("ORGgen_plt=").append((params.getInsertPLT()) ? "yes" : "no").append(" ");
        sb.append("Creversible=").append((params.getUseReversible()) ? "yes" : "no").append(" ");
        if (params.getJP2ColorSpace() != null && !params.getJP2ColorSpace().isEmpty()) {
            sb.append("-jp2_space ").append(params.getJP2ColorSpace());
            sb.append(' ');
        }

        return sb.toString();
    }
}
TOP

Related Classes of gov.lanl.adore.djatoka.kdu.KduCompressExe

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.