251 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
 | |
|  * Copyright (c) 2002-2007, Professor Benoit Macq
 | |
|  * Copyright (c) 2002-2007, Patrick Piscaglia, Telemis s.a.
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
 | |
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 | |
|  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | |
|  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | |
|  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | |
|  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | |
|  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | |
|  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | |
|  * POSSIBILITY OF SUCH DAMAGE.
 | |
|  */ 
 | |
| package org.openJpeg;
 | |
| 
 | |
| import java.util.Vector;
 | |
| 
 | |
| /** This class decodes one J2K codestream into an image (width + height + depth + pixels[], 
 | |
|  * using the OpenJPEG.org library.
 | |
|  * To be able to log messages, the called must register a IJavaJ2KDecoderLogger object.
 | |
|  */
 | |
| public class OpenJPEGJavaDecoder {
 | |
| 
 | |
| 	public interface IJavaJ2KDecoderLogger {
 | |
| 		public void logDecoderMessage(String message);
 | |
| 		public void logDecoderError(String message);
 | |
| 	}
 | |
| 	
 | |
|     private static boolean isInitialized = false;
 | |
|     
 | |
| 	// ===== decompression parameters =============>
 | |
| 	// These value may be changed for each image
 | |
|     private String[] decoder_arguments = null;
 | |
| 	/** number of resolutions decompositions */
 | |
| 	private int nbResolutions = -1;
 | |
| 	/** the quality layers */
 | |
| 	private int[] layers = null;
 | |
| 
 | |
| 	/** Contains the 8 bpp version of the image. May NOT be filled together with image16 or image24.<P>
 | |
| 	 * We store in Java the 8 or 16 bpp version of the image while the decoder uses a 32 bpp version, because <UL>
 | |
| 	 * <LI> the storage capacity required is smaller
 | |
| 	 * <LI> the transfer Java <-- C will be faster
 | |
| 	 * <LI> the conversion byte/short ==> int will be done faster by the C
 | |
| 	 * </UL>*/
 | |
| 	private byte[] image8 = null;
 | |
| 	/** Contains the 16 bpp version of the image. May NOT be filled together with image8 or image24*/
 | |
| 	private short[] image16 = null;
 | |
| 	/** Contains the 24 bpp version of the image. May NOT be filled together with image8 or image16 */
 | |
| 	private int[] image24 = null;
 | |
| 	/** Holds the J2K compressed bytecode to decode */
 | |
|     private byte compressedStream[] = null;
 | |
|     /** Holds the compressed version of the index file, to be used by the decoder */
 | |
|     private byte compressedIndex[] = null;
 | |
|     /** Width and Height of the image */
 | |
|     private int width = -1;
 | |
|     private int height = -1;
 | |
|     private int depth = -1;
 | |
|     /** This parameter is never used in Java but is read by the C library to know the number of resolutions to skip when decoding, 
 | |
|      * i.e. if there are 5 resolutions and skipped=1 ==> decode until resolution 4.  */
 | |
|     private int skippedResolutions = 0;
 | |
|     
 | |
|     private Vector<IJavaJ2KDecoderLogger> loggers = new Vector();
 | |
| 
 | |
| 
 | |
|     public OpenJPEGJavaDecoder(String openJPEGlibraryFullPathAndName, IJavaJ2KDecoderLogger messagesAndErrorsLogger) throws ExceptionInInitializerError
 | |
|     {
 | |
|     	this(openJPEGlibraryFullPathAndName);
 | |
|     	loggers.addElement(messagesAndErrorsLogger);
 | |
|     }
 | |
| 
 | |
|     public OpenJPEGJavaDecoder(String openJPEGlibraryFullPathAndName) throws ExceptionInInitializerError
 | |
|     {
 | |
|     	if (!isInitialized) {
 | |
|     		try {
 | |
|     			System.load(openJPEGlibraryFullPathAndName);
 | |
|     			isInitialized = true;
 | |
|     		} catch (Throwable t) {
 | |
|     			throw new ExceptionInInitializerError("OpenJPEG Java Decoder: probably impossible to find the C library");
 | |
|     		}
 | |
|     	}
 | |
|     }
 | |
|     
 | |
|     public void addLogger(IJavaJ2KDecoderLogger messagesAndErrorsLogger) {
 | |
|     	loggers.addElement(messagesAndErrorsLogger);
 | |
|     }
 | |
|     
 | |
|     public void removeLogger(IJavaJ2KDecoderLogger messagesAndErrorsLogger) {
 | |
|     	loggers.removeElement(messagesAndErrorsLogger);
 | |
|     }
 | |
|     
 | |
|     public int  decodeJ2KtoImage() {
 | |
| 		if ((image16 == null || (image16 != null && image16.length != width*height)) && (depth==-1 || depth==16)) {
 | |
| 			image16 = new short[width*height];
 | |
| 			logMessage("OpenJPEGJavaDecoder.decompressImage: image16 length = " + image16.length + " (" + width + " x " + height + ") ");
 | |
| 		}
 | |
| 		if ((image8 == null || (image8 != null && image8.length != width*height)) && (depth==-1 || depth==8)) {
 | |
| 			image8 = new byte[width*height];
 | |
| 			logMessage("OpenJPEGJavaDecoder.decompressImage: image8 length = " + image8.length + " (" + width + " x " + height + ") ");
 | |
| 		}
 | |
| 		if ((image24 == null || (image24 != null && image24.length != width*height)) && (depth==-1 || depth==24)) {
 | |
| 			image24 = new int[width*height];
 | |
| 			logMessage("OpenJPEGJavaDecoder.decompressImage: image24 length = " + image24.length + " (" + width + " x " + height + ") ");
 | |
| 		}
 | |
| 		
 | |
| 		String[] arguments = new String[0 + (decoder_arguments != null ? decoder_arguments.length : 0)];
 | |
| 		int offset = 0;
 | |
| 		if (decoder_arguments != null) {
 | |
| 			for (int i=0; i<decoder_arguments.length; i++) {
 | |
| 				arguments[i+offset] = decoder_arguments[i];
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return internalDecodeJ2KtoImage(arguments);
 | |
|     }
 | |
|     
 | |
|     /** 
 | |
|      * Decode the j2k stream given in the codestream byte[] and fills the image8, image16 or image24 array, according to the bit depth.
 | |
|      */
 | |
|     private native int internalDecodeJ2KtoImage(String[] parameters);
 | |
| 
 | |
|     /** Image depth in bpp */
 | |
| 	public int getDepth() {
 | |
| 		return depth;
 | |
| 	}
 | |
| 
 | |
|     /** Image depth in bpp */
 | |
| 	public void setDepth(int depth) {
 | |
| 		this.depth = depth;
 | |
| 	}
 | |
| 
 | |
| 	/** Image height in pixels */
 | |
| 	public int getHeight() {
 | |
| 		return height;
 | |
| 	}
 | |
| 
 | |
| 	/** Image height in pixels */
 | |
| 	public void setHeight(int height) {
 | |
| 		this.height = height;
 | |
| 	}
 | |
| 
 | |
| 	/** Number of resolutions contained in the image */
 | |
| 	public int getNbResolutions() {
 | |
| 		return nbResolutions;
 | |
| 	}
 | |
| 
 | |
| 	/** Number of resolutions contained in the image */
 | |
| 	public void setNbResolutions(int nbResolutions) {
 | |
| 		this.nbResolutions = nbResolutions;
 | |
| 	}
 | |
| 
 | |
| 	/** Width of the image in pixels */
 | |
| 	public int getWidth() {
 | |
| 		return width;
 | |
| 	}
 | |
| 
 | |
| 	/** Width of the image in pixels */
 | |
| 	public void setWidth(int width) {
 | |
| 		this.width = width;
 | |
| 	}
 | |
| 
 | |
| 	/** Contains the decompressed version of the image, if the depth in is [9,16] bpp.
 | |
| 	 * Returns NULL otherwise.
 | |
| 	 */
 | |
| 	public short[] getImage16() {
 | |
| 		return image16;
 | |
| 	}
 | |
| 
 | |
| 	/** Contains the decompressed version of the image, if the depth in is [17,24] bpp and the image is in color.
 | |
| 	 * Returns NULL otherwise.
 | |
| 	 */
 | |
| 	public int[] getImage24() {
 | |
| 		return image24;
 | |
| 	}
 | |
| 
 | |
| 	/** Contains the decompressed version of the image, if the depth in is [1,8] bpp.
 | |
| 	 * Returns NULL otherwise.
 | |
| 	 */
 | |
| 	public byte[] getImage8() {
 | |
| 		return image8;
 | |
| 	}
 | |
| 
 | |
| 	/** Sets the compressed version of the index file for this image.
 | |
| 	 * This index file is used by the decompressor
 | |
| 	 */
 | |
| 	public void setCompressedIndex(byte[] compressedIndex) {
 | |
| 		this.compressedIndex = compressedIndex;
 | |
| 	}
 | |
| 
 | |
| 	/** Sets the codestream to be decoded */
 | |
| 	public void setCompressedStream(byte[] compressedStream) {
 | |
| 		this.compressedStream = compressedStream;
 | |
| 	}
 | |
| 
 | |
| 	/** @return the compressed code stream length, or -1 if not defined */
 | |
| 	public long getCodestreamLength() {
 | |
| 		if (compressedStream == null)
 | |
| 			return -1;
 | |
| 		else return compressedStream.length;
 | |
| 	}
 | |
| 	
 | |
| 	/** This method is called either directly or by the C methods */
 | |
| 	public void logMessage(String message) {
 | |
| 		for (IJavaJ2KDecoderLogger logger:loggers)
 | |
| 			logger.logDecoderMessage(message);
 | |
| 	}
 | |
| 	
 | |
| 	/** This method is called either directly or by the C methods */
 | |
| 	public void logError(String error) {
 | |
| 		for (IJavaJ2KDecoderLogger logger:loggers)
 | |
| 			logger.logDecoderError(error);
 | |
| 	}
 | |
| 
 | |
| 	public void reset() {
 | |
| 		nbResolutions = -1;
 | |
| 		layers = null;
 | |
| 		image8 = null;
 | |
| 		image16 = null;
 | |
| 		image24 = null;
 | |
| 		compressedStream = null;
 | |
| 	    compressedIndex = null;
 | |
| 	    width = -1;
 | |
| 	    height = -1;
 | |
| 	    depth = -1;
 | |
| 	}
 | |
| 
 | |
| 	public void setSkippedResolutions(int numberOfSkippedResolutions) {
 | |
| 		skippedResolutions = numberOfSkippedResolutions;
 | |
| 	}
 | |
| 
 | |
| 	/** Contains all the decoding arguments other than the input/output file */
 | |
| 	public void setDecoderArguments(String[] argumentsForTheDecoder) {
 | |
| 		decoder_arguments = argumentsForTheDecoder;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| }
 | 
