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