]> Creatis software - gdcm.git/blob - src/gdcmopenjpeg/codec/j2k_to_image.c
ENH: Huge update to openjpeg 1.0 (actually more CVS)...
[gdcm.git] / src / gdcmopenjpeg / codec / j2k_to_image.c
1 /*\r
2  * Copyright (c) 2001-2003, David Janssens\r
3  * Copyright (c) 2002-2003, Yannick Verschueren\r
4  * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
5  * Copyright (c) 2005, HervĂ© Drolon, FreeImage Team\r
6  * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
7  * All rights reserved.\r
8  *\r
9  * Redistribution and use in source and binary forms, with or without\r
10  * modification, are permitted provided that the following conditions\r
11  * are met:\r
12  * 1. Redistributions of source code must retain the above copyright\r
13  *    notice, this list of conditions and the following disclaimer.\r
14  * 2. Redistributions in binary form must reproduce the above copyright\r
15  *    notice, this list of conditions and the following disclaimer in the\r
16  *    documentation and/or other materials provided with the distribution.\r
17  *\r
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
28  * POSSIBILITY OF SUCH DAMAGE.\r
29  */\r
30 #include <stdio.h>\r
31 #include <string.h>\r
32 #include <stdlib.h>\r
33 \r
34 #include "openjpeg.h"\r
35 #include "compat/getopt.h"\r
36 #include "convert.h"\r
37 \r
38 #ifndef WIN32\r
39 #define stricmp strcasecmp\r
40 #define strnicmp strncasecmp\r
41 #endif\r
42 \r
43 /* ----------------------------------------------------------------------- */\r
44 \r
45 #define J2K_CFMT 0\r
46 #define JP2_CFMT 1\r
47 #define JPT_CFMT 2\r
48 #define MJ2_CFMT 3\r
49 #define PXM_DFMT 0\r
50 #define PGX_DFMT 1\r
51 #define BMP_DFMT 2\r
52 #define YUV_DFMT 3\r
53 \r
54 /* ----------------------------------------------------------------------- */\r
55 \r
56 void decode_help_display() {\r
57   fprintf(stdout,"HELP\n----\n\n");\r
58   fprintf(stdout,"- the -h option displays this help information on screen\n\n");\r
59 \r
60   fprintf(stdout,"List of parameters for the JPEG 2000 encoder:\n");\r
61   fprintf(stdout,"\n");\r
62   fprintf(stdout,"  -i <compressed file>\n");\r
63   fprintf(stdout,"    REQUIRED\n");\r
64   fprintf(stdout,"    Currently accepts J2K-files, JP2-files and JPT-files. The file type\n");\r
65   fprintf(stdout,"    is identified based on its suffix.\n");\r
66   fprintf(stdout,"  -o <decompressed file>\n");\r
67   fprintf(stdout,"    REQUIRED\n");\r
68   fprintf(stdout,"    Currently accepts PGM-files, PPM-files, PNM-files, PGX-files and\n");\r
69   fprintf(stdout,"    BMP-files. Binary data is written to the file (not ascii). If a PGX\n");\r
70   fprintf(stdout,"    filename is given, there will be as many output files as there are\n");\r
71   fprintf(stdout,"    components: an indice starting from 0 will then be appended to the\n");\r
72   fprintf(stdout,"    output filename, just before the \"pgx\" extension. If a PGM filename\n");\r
73   fprintf(stdout,"    is given and there are more than one component, only the first component\n");\r
74   fprintf(stdout,"    will be written to the file.\n");\r
75   fprintf(stdout,"  -r <reduce factor>\n");\r
76   fprintf(stdout,"    Set the number of highest resolution levels to be discarded. The\n");\r
77   fprintf(stdout,"    image resolution is effectively divided by 2 to the power of the\n");\r
78   fprintf(stdout,"    number of discarded levels. The reduce factor is limited by the\n");\r
79   fprintf(stdout,"    smallest total number of decomposition levels among tiles.\n");\r
80   fprintf(stdout,"  -l <number of quality layers to decode>\n");\r
81   fprintf(stdout,"    Set the maximum number of quality layers to decode. If there are\n");\r
82   fprintf(stdout,"    less quality layers than the specified number, all the quality layers\n");\r
83   fprintf(stdout,"    are decoded.\n");\r
84   fprintf(stdout,"\n");\r
85 }\r
86 \r
87 /* -------------------------------------------------------------------------- */\r
88 \r
89 int get_file_format(char *filename) {\r
90   unsigned int i;\r
91   static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp", "j2k", "jp2", "jpt" };\r
92   static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT };\r
93   char * ext = strrchr(filename, '.') + 1;\r
94   if(ext) {\r
95     for(i = 0; i < sizeof(format); i++) {\r
96       if(strnicmp(ext, extension[i], 3) == 0) {\r
97         return format[i];\r
98       }\r
99     }\r
100   }\r
101 \r
102   return -1;\r
103 }\r
104 \r
105 /* -------------------------------------------------------------------------- */\r
106 \r
107 int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters) {\r
108   /* parse the command line */\r
109 \r
110   while (1) {\r
111     int c = getopt(argc, argv, "i:o:r:q:f:t:n:c:b:x:p:s:d:h:P:S:E:M:R:T:C:I");\r
112     if (c == -1)\r
113       break;\r
114     switch (c) {\r
115       case 'i':      /* input file */\r
116       {\r
117         char *infile = optarg;\r
118         parameters->decod_format = get_file_format(infile);\r
119         switch(parameters->decod_format) {\r
120           case J2K_CFMT:\r
121           case JP2_CFMT:\r
122           case JPT_CFMT:\r
123             break;\r
124           default:\r
125             fprintf(stderr, \r
126               "!! Unrecognized format for infile : %s [accept only *.j2k, *.jp2, *.jpc or *.jpt] !!\n\n", \r
127               infile);\r
128             return 1;\r
129             break;\r
130         }\r
131         strncpy(parameters->infile, infile, MAX_PATH);\r
132       }\r
133       break;\r
134         \r
135         /* ----------------------------------------------------- */\r
136 \r
137       case 'o':      /* output file */\r
138       {\r
139         char *outfile = optarg;\r
140         parameters->cod_format = get_file_format(outfile);\r
141         switch(parameters->cod_format) {\r
142           case PGX_DFMT:\r
143           case PXM_DFMT:\r
144           case BMP_DFMT:\r
145             break;\r
146           default:\r
147             fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx or *.bmp]!! \n", outfile);\r
148             return 1;\r
149             break;\r
150         }\r
151         strncpy(parameters->outfile, outfile, MAX_PATH);\r
152       }\r
153       break;\r
154       \r
155         /* ----------------------------------------------------- */\r
156       \r
157     \r
158       case 'r':    /* reduce option */\r
159       {\r
160         sscanf(optarg, "%d", &parameters->cp_reduce);\r
161       }\r
162       break;\r
163       \r
164         /* ----------------------------------------------------- */\r
165       \r
166 \r
167       case 'l':    /* layering option */\r
168       {\r
169         sscanf(optarg, "%d", &parameters->cp_layer);\r
170       }\r
171       break;\r
172       \r
173         /* ----------------------------------------------------- */\r
174       \r
175       case 'h':       /* display an help description */\r
176       {\r
177         decode_help_display();\r
178         return 1;\r
179       }\r
180       break;\r
181             \r
182         /* ----------------------------------------------------- */\r
183       \r
184       default:\r
185         fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, optarg);\r
186         break;\r
187     }\r
188   }\r
189 \r
190   /* check for possible errors */\r
191 \r
192   if((parameters->infile[0] == 0) || (parameters->outfile[0] == 0)) {\r
193     fprintf(stderr,"ERROR -> At least one required argument is missing\nCheck j2k_to_image -h for usage information\n");\r
194     return 1;\r
195   }\r
196 \r
197   return 0;\r
198 }\r
199 \r
200 /* -------------------------------------------------------------------------- */\r
201 \r
202 /**\r
203 sample error callback expecting a FILE* client object\r
204 */\r
205 void error_callback(const char *msg, void *client_data) {\r
206   FILE *stream = (FILE*)client_data;\r
207   fprintf(stream, "[ERROR] %s", msg);\r
208 }\r
209 /**\r
210 sample warning callback expecting a FILE* client object\r
211 */\r
212 void warning_callback(const char *msg, void *client_data) {\r
213   FILE *stream = (FILE*)client_data;\r
214   fprintf(stream, "[WARNING] %s", msg);\r
215 }\r
216 /**\r
217 sample debug callback expecting no client object\r
218 */\r
219 void info_callback(const char *msg, void *client_data) {\r
220   (void)client_data;\r
221   fprintf(stdout, "[INFO] %s", msg);\r
222 }\r
223 \r
224 /* -------------------------------------------------------------------------- */\r
225 \r
226 int main(int argc, char **argv) {\r
227   opj_dparameters_t parameters;  /* decompression parameters */\r
228   opj_event_mgr_t event_mgr;    /* event manager */\r
229   opj_image_t *image = NULL;\r
230   FILE *fsrc = NULL;\r
231   unsigned char *src = NULL; \r
232   int file_length;\r
233 \r
234   opj_dinfo_t* dinfo = NULL;  /* handle to a decompressor */\r
235   opj_cio_t *cio = NULL;\r
236 \r
237   /* configure the event callbacks (not required) */\r
238   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
239   event_mgr.error_handler = error_callback;\r
240   event_mgr.warning_handler = warning_callback;\r
241   event_mgr.info_handler = info_callback;\r
242 \r
243   /* set decoding parameters to default values */\r
244   opj_set_default_decoder_parameters(&parameters);\r
245 \r
246   /* parse input and get user decoding parameters */\r
247   if(parse_cmdline_decoder(argc, argv, &parameters) == 1) {\r
248     return 0;\r
249   }\r
250   \r
251   /* read the input file and put it in memory */\r
252   /* ---------------------------------------- */\r
253   fsrc = fopen(parameters.infile, "rb");\r
254   if (!fsrc) {\r
255     fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile);\r
256     return 1;\r
257   }  \r
258   fseek(fsrc, 0, SEEK_END);\r
259   file_length = ftell(fsrc);\r
260   fseek(fsrc, 0, SEEK_SET);\r
261   src = (unsigned char *) malloc(file_length);\r
262   fread(src, 1, file_length, fsrc);\r
263   fclose(fsrc);\r
264   \r
265   /* decode the code-stream */\r
266   /* ---------------------- */\r
267 \r
268     switch(parameters.decod_format) {\r
269     case J2K_CFMT:\r
270     {\r
271       /* JPEG-2000 codestream */\r
272 \r
273       /* get a decoder handle */\r
274       dinfo = opj_create_decompress(CODEC_J2K);\r
275       \r
276       /* catch events using our callbacks and give a local context */\r
277       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);      \r
278 \r
279       /* setup the decoder decoding parameters using user parameters */\r
280       opj_setup_decoder(dinfo, &parameters);\r
281 \r
282       /* open a byte stream */\r
283       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
284 \r
285       /* decode the stream and fill the image structure */\r
286       image = opj_decode(dinfo, cio);\r
287       if(!image) {\r
288         fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");\r
289         opj_destroy_decompress(dinfo);\r
290         opj_cio_close(cio);\r
291         return 1;\r
292       }\r
293       \r
294       /* close the byte stream */\r
295       opj_cio_close(cio);\r
296     }\r
297     break;\r
298 \r
299     case JP2_CFMT:\r
300     {\r
301       /* JPEG 2000 compressed image data */\r
302 \r
303       /* get a decoder handle */\r
304       dinfo = opj_create_decompress(CODEC_JP2);\r
305       \r
306       /* catch events using our callbacks and give a local context */\r
307       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);      \r
308 \r
309       /* setup the decoder decoding parameters using the current image and using user parameters */\r
310       opj_setup_decoder(dinfo, &parameters);\r
311 \r
312       /* open a byte stream */\r
313       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
314 \r
315       /* decode the stream and fill the image structure */\r
316       image = opj_decode(dinfo, cio);\r
317       if(!image) {\r
318         fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");\r
319         opj_destroy_decompress(dinfo);\r
320         opj_cio_close(cio);\r
321         return 1;\r
322       }\r
323 \r
324       /* close the byte stream */\r
325       opj_cio_close(cio);\r
326 \r
327     }\r
328     break;\r
329 \r
330     case JPT_CFMT:\r
331     {\r
332       /* JPEG 2000, JPIP */\r
333 \r
334       /* get a decoder handle */\r
335       dinfo = opj_create_decompress(CODEC_JPT);\r
336       \r
337       /* catch events using our callbacks and give a local context */\r
338       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);      \r
339 \r
340       /* setup the decoder decoding parameters using user parameters */\r
341       opj_setup_decoder(dinfo, &parameters);\r
342 \r
343       /* open a byte stream */\r
344       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
345 \r
346       /* decode the stream and fill the image structure */\r
347       image = opj_decode(dinfo, cio);\r
348       if(!image) {\r
349         fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");        \r
350         opj_destroy_decompress(dinfo);\r
351         opj_cio_close(cio);\r
352         return 1;\r
353       }  \r
354 \r
355       /* close the byte stream */\r
356       opj_cio_close(cio);\r
357     }\r
358     break;\r
359 \r
360     default:\r
361       fprintf(stderr, "ERROR -> j2k_to_image : Unknown input image format\n");\r
362       return 1;\r
363       break;\r
364   }\r
365   \r
366   /* free the memory containing the code-stream */\r
367   free(src);\r
368   src = NULL;\r
369 \r
370   /* create output image */\r
371   /* ------------------- */\r
372 \r
373   switch (parameters.cod_format) {\r
374     case PXM_DFMT:      /* PNM PGM PPM */\r
375       imagetopnm(image, parameters.outfile);\r
376       break;\r
377             \r
378     case PGX_DFMT:      /* PGX */\r
379       imagetopgx(image, parameters.outfile);\r
380       break;\r
381     \r
382     case BMP_DFMT:      /* BMP */\r
383       imagetobmp(image, parameters.outfile);\r
384       break;\r
385   }\r
386 \r
387   /* free remaining structures */\r
388   if(dinfo) {\r
389     opj_destroy_decompress(dinfo);\r
390   }\r
391 \r
392   /* free image data structure */\r
393   opj_image_destroy(image);\r
394    \r
395   return 0;\r
396 }\r
397 \r