/* * 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.openurl; import gov.lanl.adore.djatoka.DjatokaEncodeParam; import gov.lanl.adore.djatoka.DjatokaException; import gov.lanl.adore.djatoka.ICompress; import gov.lanl.adore.djatoka.IExtract; import gov.lanl.adore.djatoka.io.FormatConstants; import gov.lanl.adore.djatoka.kdu.KduCompressExe; import gov.lanl.adore.djatoka.kdu.KduExtractExe; import gov.lanl.adore.djatoka.util.IOUtils; import gov.lanl.adore.djatoka.util.ImageProcessingUtils; import gov.lanl.adore.djatoka.util.ImageRecord; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; /** * Utility class used to harvest URIs and compress files into JP2 * @author Ryan Chute * */ public class DjatokaImageMigrator implements FormatConstants, IReferentMigrator { static Logger logger = Logger.getLogger(DjatokaImageMigrator.class); private List<String> processing = java.util.Collections.synchronizedList(new LinkedList<String>()); private HashMap<String, String> formatMap; /** * Constructor. Initialized formatMap with common ext suffixes */ public DjatokaImageMigrator() { formatMap = new HashMap<String, String>(); formatMap.put(FORMAT_ID_JPEG, FORMAT_MIMEYPE_JPEG); formatMap.put(FORMAT_ID_JP2, FORMAT_MIMEYPE_JP2); formatMap.put(FORMAT_ID_PNG, FORMAT_MIMEYPE_PNG); formatMap.put(FORMAT_ID_BMP, FORMAT_MIMEYPE_BMP); formatMap.put(FORMAT_ID_PNM, FORMAT_MIMEYPE_PNM); formatMap.put(FORMAT_ID_TIFF, FORMAT_MIMEYPE_TIFF); formatMap.put(FORMAT_ID_GIF, FORMAT_MIMEYPE_GIF); // Additional Extensions formatMap.put(FORMAT_ID_JPG, FORMAT_MIMEYPE_JPEG); formatMap.put(FORMAT_ID_TIF, FORMAT_MIMEYPE_TIFF); // Additional JPEG 2000 Extensions formatMap.put(FORMAT_ID_J2C, FORMAT_MIMEYPE_JP2); formatMap.put(FORMAT_ID_JPC, FORMAT_MIMEYPE_JP2); formatMap.put(FORMAT_ID_J2K, FORMAT_MIMEYPE_JP2); formatMap.put(FORMAT_ID_JPF, FORMAT_MIMEYPE_JPX); formatMap.put(FORMAT_ID_JPX, FORMAT_MIMEYPE_JPX); formatMap.put(FORMAT_ID_JPM, FORMAT_MIMEYPE_JPM); } /** * Returns a delete on exit File object for a provide URI * @param uri the URI of an image to be downloaded and compressed as JP2 * @return File object of JP2 compressed image * @throws DjatokaException */ public File convert(URI uri) throws DjatokaException { try { logger.info("processingRemoteURI: " + uri.toURL()); processing.add(uri.toString()); File urlLocal = null; boolean isJp2 = false; // Obtain Resource InputStream src = IOUtils.getInputStream(uri.toURL()); String ext = uri.toURL().toString().substring(uri.toURL().toString().lastIndexOf(".") + 1).toLowerCase(); if (ext.equals(FORMAT_ID_TIF) || ext.equals(FORMAT_ID_TIFF)) { urlLocal = File.createTempFile("convert" + uri.hashCode(), "." + FORMAT_ID_TIF); } else if (formatMap.containsKey(ext) && (formatMap.get(ext).equals(FORMAT_MIMEYPE_JP2) || formatMap.get(ext).equals(FORMAT_MIMEYPE_JPX))) { urlLocal = File.createTempFile("cache" + uri.hashCode(), "." + ext); isJp2 = true; } else { if (src.markSupported()) src.mark(15); if (ImageProcessingUtils.checkIfJp2(src)) urlLocal = File.createTempFile("cache" + uri.hashCode(), "." + FORMAT_ID_JP2); if (src.markSupported()) src.reset(); else { // close and reopen the stream src.close(); src = IOUtils.getInputStream(uri.toURL()); } } if (urlLocal == null) { urlLocal = File.createTempFile("convert" + uri.hashCode(), ".img"); } urlLocal.deleteOnExit(); FileOutputStream dest = new FileOutputStream(urlLocal); IOUtils.copyStream(src, dest); // Process Image if (!isJp2) urlLocal = processImage(urlLocal, uri); // Clean-up src.close(); dest.close(); return urlLocal; } catch (Exception e) { throw new DjatokaException(e); } finally { if (processing.contains(uri.toString())) processing.remove(uri.toString()); } } /** * Returns a delete on exit File object for a provide URI * @param img File object on local image to be compressed * @param uri the URI of an image to be compressed as JP2 * @return File object of JP2 compressed image * @throws DjatokaException */ public File processImage(File img, URI uri) throws DjatokaException { String imgPath = img.getAbsolutePath(); String fmt = formatMap.get(imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase()); try { if (fmt == null || !ImageProcessingUtils.isJp2Type(fmt)) { ICompress jp2 = new KduCompressExe(); File jp2Local = File.createTempFile("cache" + uri.hashCode() + "-", ".jp2"); jp2Local.delete(); jp2.compressImage(img.getAbsolutePath(), jp2Local.getAbsolutePath(), new DjatokaEncodeParam()); img.delete(); img = jp2Local; } else { try { IExtract ex = new KduExtractExe(); ex.getMetadata(new ImageRecord(uri.toString(), img.getAbsolutePath())); } catch (DjatokaException e) { throw new DjatokaException("Unknown JP2/JPX file format"); } } } catch (Exception e) { throw new DjatokaException(e); } return img; } /** * Return a unmodifiable list of images currently being processed. Images are removed once complete. * @return list of images being processed */ public List<String> getProcessingList() { return processing; } /** * Returns map of format extension (e.g. jpg) to mimetype mappings (e.g. image/jpeg) * @return format extension to mimetype mappings */ public HashMap<String, String> getFormatMap() { return formatMap; } /** * Sets map of format extension (e.g. jpg) to mimetype mappings (e.g. image/jpeg) * @param formatMap extension to mimetype mappings */ public void setFormatMap(HashMap<String, String> formatMap) { this.formatMap = formatMap; } public static void main(String[] args) { URI uri; try { long a = System.currentTimeMillis(); uri = new URI(args[0]); IReferentMigrator dim = new DjatokaImageMigrator(); File f = dim.convert(uri); System.out.println((System.currentTimeMillis() - a) + ": " + f.getAbsolutePath()); } catch (URISyntaxException e) { e.printStackTrace(); } catch (DjatokaException e) { e.printStackTrace(); } } }