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