Merge pull request #1518 from dg0yt/static-windows
[openjpeg.git] / wrapping / java / openjp2 / java-sources / org / openJpeg / OpenJPEGJavaDecoder.java
1 /*
2  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
3  * Copyright (c) 2002-2014, Professor Benoit Macq
4  * Copyright (c) 2002-2007, Patrick Piscaglia, Telemis s.a.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */ 
28 package org.openJpeg;
29
30 import java.util.Vector;
31
32 /** This class decodes one J2K codestream into an image (width + height + depth + pixels[], 
33  * using the OpenJPEG.org library.
34  * To be able to log messages, the called must register a IJavaJ2KDecoderLogger object.
35  */
36 public class OpenJPEGJavaDecoder {
37
38         public interface IJavaJ2KDecoderLogger {
39                 public void logDecoderMessage(String message);
40                 public void logDecoderError(String message);
41         }
42         
43     private static boolean isInitialized = false;
44     
45         // ===== decompression parameters =============>
46         // These value may be changed for each image
47     private String[] decoder_arguments = null;
48         /** number of resolutions decompositions */
49         private int nbResolutions = -1;
50         /** the quality layers */
51         private int[] layers = null;
52
53         /** Contains the 8 bpp version of the image. May NOT be filled together with image16 or image24.<P>
54          * We store in Java the 8 or 16 bpp version of the image while the decoder uses a 32 bpp version, because <UL>
55          * <LI> the storage capacity required is smaller
56          * <LI> the transfer Java <-- C will be faster
57          * <LI> the conversion byte/short ==> int will be done faster by the C
58          * </UL>*/
59         private byte[] image8 = null;
60         /** Contains the 16 bpp version of the image. May NOT be filled together with image8 or image24*/
61         private short[] image16 = null;
62         /** Contains the 24 bpp version of the image. May NOT be filled together with image8 or image16 */
63         private int[] image24 = null;
64         /** Holds the J2K compressed bytecode to decode */
65     private byte compressedStream[] = null;
66     /** Holds the compressed version of the index file, to be used by the decoder */
67     private byte compressedIndex[] = null;
68     /** Width and Height of the image */
69     private int width = -1;
70     private int height = -1;
71     private int depth = -1;
72     /** This parameter is never used in Java but is read by the C library to know the number of resolutions to skip when decoding, 
73      * i.e. if there are 5 resolutions and skipped=1 ==> decode until resolution 4.  */
74     private int skippedResolutions = 0;
75     
76     private Vector<IJavaJ2KDecoderLogger> loggers = new Vector();
77
78
79     public OpenJPEGJavaDecoder(String openJPEGlibraryFullPathAndName, IJavaJ2KDecoderLogger messagesAndErrorsLogger) throws ExceptionInInitializerError
80     {
81         this(openJPEGlibraryFullPathAndName);
82         loggers.addElement(messagesAndErrorsLogger);
83     }
84
85     public OpenJPEGJavaDecoder(String openJPEGlibraryFullPathAndName) throws ExceptionInInitializerError
86     {
87         if (!isInitialized) {
88                 try {
89                         System.load(openJPEGlibraryFullPathAndName);
90                         isInitialized = true;
91                 } catch (Throwable t) {
92                         throw new ExceptionInInitializerError("OpenJPEG Java Decoder: probably impossible to find the C library");
93                 }
94         }
95     }
96     
97     public void addLogger(IJavaJ2KDecoderLogger messagesAndErrorsLogger) {
98         loggers.addElement(messagesAndErrorsLogger);
99     }
100     
101     public void removeLogger(IJavaJ2KDecoderLogger messagesAndErrorsLogger) {
102         loggers.removeElement(messagesAndErrorsLogger);
103     }
104     
105     public int  decodeJ2KtoImage() {
106                 if ((image16 == null || (image16 != null && image16.length != width*height)) && (depth==-1 || depth==16)) {
107                         image16 = new short[width*height];
108                         logMessage("OpenJPEGJavaDecoder.decompressImage: image16 length = " + image16.length + " (" + width + " x " + height + ") ");
109                 }
110                 if ((image8 == null || (image8 != null && image8.length != width*height)) && (depth==-1 || depth==8)) {
111                         image8 = new byte[width*height];
112                         logMessage("OpenJPEGJavaDecoder.decompressImage: image8 length = " + image8.length + " (" + width + " x " + height + ") ");
113                 }
114                 if ((image24 == null || (image24 != null && image24.length != width*height)) && (depth==-1 || depth==24)) {
115                         image24 = new int[width*height];
116                         logMessage("OpenJPEGJavaDecoder.decompressImage: image24 length = " + image24.length + " (" + width + " x " + height + ") ");
117                 }
118                 
119                 String[] arguments = new String[0 + (decoder_arguments != null ? decoder_arguments.length : 0)];
120                 int offset = 0;
121                 if (decoder_arguments != null) {
122                         for (int i=0; i<decoder_arguments.length; i++) {
123                                 arguments[i+offset] = decoder_arguments[i];
124                         }
125                 }
126
127                 return internalDecodeJ2KtoImage(arguments);
128     }
129     
130     /** 
131      * Decode the j2k stream given in the codestream byte[] and fills the image8, image16 or image24 array, according to the bit depth.
132      */
133     private native int internalDecodeJ2KtoImage(String[] parameters);
134
135     /** Image depth in bpp */
136         public int getDepth() {
137                 return depth;
138         }
139
140     /** Image depth in bpp */
141         public void setDepth(int depth) {
142                 this.depth = depth;
143         }
144
145         /** Image height in pixels */
146         public int getHeight() {
147                 return height;
148         }
149
150         /** Image height in pixels */
151         public void setHeight(int height) {
152                 this.height = height;
153         }
154
155         /** Number of resolutions contained in the image */
156         public int getNbResolutions() {
157                 return nbResolutions;
158         }
159
160         /** Number of resolutions contained in the image */
161         public void setNbResolutions(int nbResolutions) {
162                 this.nbResolutions = nbResolutions;
163         }
164
165         /** Width of the image in pixels */
166         public int getWidth() {
167                 return width;
168         }
169
170         /** Width of the image in pixels */
171         public void setWidth(int width) {
172                 this.width = width;
173         }
174
175         /** Contains the decompressed version of the image, if the depth in is [9,16] bpp.
176          * Returns NULL otherwise.
177          */
178         public short[] getImage16() {
179                 return image16;
180         }
181
182         /** Contains the decompressed version of the image, if the depth in is [17,24] bpp and the image is in color.
183          * Returns NULL otherwise.
184          */
185         public int[] getImage24() {
186                 return image24;
187         }
188
189         /** Contains the decompressed version of the image, if the depth in is [1,8] bpp.
190          * Returns NULL otherwise.
191          */
192         public byte[] getImage8() {
193                 return image8;
194         }
195
196         /** Sets the compressed version of the index file for this image.
197          * This index file is used by the decompressor
198          */
199         public void setCompressedIndex(byte[] compressedIndex) {
200                 this.compressedIndex = compressedIndex;
201         }
202
203         /** Sets the codestream to be decoded */
204         public void setCompressedStream(byte[] compressedStream) {
205                 this.compressedStream = compressedStream;
206         }
207
208         /** @return the compressed code stream length, or -1 if not defined */
209         public long getCodestreamLength() {
210                 if (compressedStream == null)
211                         return -1;
212                 else return compressedStream.length;
213         }
214         
215         /** This method is called either directly or by the C methods */
216         public void logMessage(String message) {
217                 for (IJavaJ2KDecoderLogger logger:loggers)
218                         logger.logDecoderMessage(message);
219         }
220         
221         /** This method is called either directly or by the C methods */
222         public void logError(String error) {
223                 for (IJavaJ2KDecoderLogger logger:loggers)
224                         logger.logDecoderError(error);
225         }
226
227         public void reset() {
228                 nbResolutions = -1;
229                 layers = null;
230                 image8 = null;
231                 image16 = null;
232                 image24 = null;
233                 compressedStream = null;
234             compressedIndex = null;
235             width = -1;
236             height = -1;
237             depth = -1;
238         }
239
240         public void setSkippedResolutions(int numberOfSkippedResolutions) {
241                 skippedResolutions = numberOfSkippedResolutions;
242         }
243
244         /** Contains all the decoding arguments other than the input/output file */
245         public void setDecoderArguments(String[] argumentsForTheDecoder) {
246                 decoder_arguments = argumentsForTheDecoder;
247         }
248
249
250 }