BUG: Fixing case in which the pointer the data buffers doesn't
[openjpeg.git] / codec / j2k_dump.c
1 /*
2  * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3  * Copyright (c) 2002-2007, Professor Benoit Macq
4  * Copyright (c) 2001-2003, David Janssens
5  * Copyright (c) 2002-2003, Yannick Verschueren
6  * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
7  * Copyright (c) 2005, Herve Drolon, FreeImage Team
8  * Copyright (c) 2006-2007, Parvatha Elangovan
9  * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <math.h>
37 #define USE_OPJ_DEPRECATED
38 #include "openjpeg.h"
39 #include "j2k.h"
40 #include "jp2.h"
41 #include "compat/getopt.h"
42 #include "convert.h"
43 #include "dirent.h"
44 #include "index.h"
45
46 #ifndef WIN32
47 #include <strings.h>
48 #define _stricmp strcasecmp
49 #define _strnicmp strncasecmp
50 #endif
51
52 /* ----------------------------------------------------------------------- */
53
54 #define J2K_CFMT 0
55 #define JP2_CFMT 1
56 #define JPT_CFMT 2
57
58 #define PXM_DFMT 10
59 #define PGX_DFMT 11
60 #define BMP_DFMT 12
61 #define YUV_DFMT 13
62 #define TIF_DFMT 14
63 #define RAW_DFMT 15
64 #define TGA_DFMT 16
65
66 /* ----------------------------------------------------------------------- */
67
68 typedef struct dircnt{
69         /** Buffer for holding images read from Directory*/
70         char *filename_buf;
71         /** Pointer to the buffer*/
72         char **filename;
73 }dircnt_t;
74
75
76 typedef struct img_folder{
77         /** The directory path of the folder containing input images*/
78         char *imgdirpath;
79         /** Output format*/
80         const char *out_format;
81         /** Enable option*/
82         char set_imgdir;
83         /** Enable Cod Format for output*/
84         char set_out_format;
85
86 }img_fol_t;
87
88 void decode_help_display() {
89         fprintf(stdout,"HELP\n----\n\n");
90         fprintf(stdout,"- the -h option displays this help information on screen\n\n");
91
92 /* UniPG>> */
93         fprintf(stdout,"List of parameters for the JPEG 2000 "
94 #ifdef USE_JPWL
95                 "+ JPWL "
96 #endif /* USE_JPWL */
97                 "decoder:\n");
98 /* <<UniPG */
99         fprintf(stdout,"\n");
100         fprintf(stdout,"\n");
101         fprintf(stdout,"  -ImgDir \n");
102         fprintf(stdout,"        Image file Directory path \n");
103         fprintf(stdout,"  -i <compressed file>\n");
104         fprintf(stdout,"    REQUIRED only if an Input image directory not specified\n");
105         fprintf(stdout,"    Currently accepts J2K-files, JP2-files and JPT-files. The file type\n");
106         fprintf(stdout,"    is identified based on its suffix.\n");
107         fprintf(stdout,"\n");
108 }
109
110 /* -------------------------------------------------------------------------- */
111
112 int get_num_images(char *imgdirpath){
113         DIR *dir;
114         struct dirent* content; 
115         int num_images = 0;
116
117         /*Reading the input images from given input directory*/
118
119         dir= opendir(imgdirpath);
120         if(!dir){
121                 fprintf(stderr,"Could not open Folder %s\n",imgdirpath);
122                 return 0;
123         }
124         
125         while((content=readdir(dir))!=NULL){
126                 if(strcmp(".",content->d_name)==0 || strcmp("..",content->d_name)==0 )
127                         continue;
128                 num_images++;
129         }
130         return num_images;
131 }
132
133 int load_images(dircnt_t *dirptr, char *imgdirpath){
134         DIR *dir;
135         struct dirent* content; 
136         int i = 0;
137
138         /*Reading the input images from given input directory*/
139
140         dir= opendir(imgdirpath);
141         if(!dir){
142                 fprintf(stderr,"Could not open Folder %s\n",imgdirpath);
143                 return 1;
144         }else   {
145                 fprintf(stderr,"Folder opened successfully\n");
146         }
147         
148         while((content=readdir(dir))!=NULL){
149                 if(strcmp(".",content->d_name)==0 || strcmp("..",content->d_name)==0 )
150                         continue;
151
152                 strcpy(dirptr->filename[i],content->d_name);
153                 i++;
154         }
155         return 0;       
156 }
157
158 int get_file_format(char *filename) {
159         unsigned int i;
160         static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "tga", "j2k", "jp2", "jpt", "j2c", "jpc" };
161         static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, TGA_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT, J2K_CFMT };
162         char * ext = strrchr(filename, '.');
163         if (ext == NULL)
164                 return -1;
165         ext++;
166         if(ext) {
167                 for(i = 0; i < sizeof(format)/sizeof(*format); i++) {
168                         if(_strnicmp(ext, extension[i], 3) == 0) {
169                                 return format[i];
170                         }
171                 }
172         }
173
174         return -1;
175 }
176
177 char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters){
178         char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],outfilename[OPJ_PATH_LEN],temp_ofname[OPJ_PATH_LEN];
179         char *temp_p, temp1[OPJ_PATH_LEN]="";
180
181         strcpy(image_filename,dirptr->filename[imageno]);
182         fprintf(stderr,"File Number %d \"%s\"\n",imageno,image_filename);
183         parameters->decod_format = get_file_format(image_filename);
184         if (parameters->decod_format == -1)
185                 return 1;
186         sprintf(infilename,"%s/%s",img_fol->imgdirpath,image_filename);
187         strncpy(parameters->infile, infilename, sizeof(infilename));
188
189         //Set output file
190         strcpy(temp_ofname,strtok(image_filename,"."));
191         while((temp_p = strtok(NULL,".")) != NULL){
192                 strcat(temp_ofname,temp1);
193                 sprintf(temp1,".%s",temp_p);
194         }
195         if(img_fol->set_out_format==1){
196                 sprintf(outfilename,"%s/%s.%s",img_fol->imgdirpath,temp_ofname,img_fol->out_format);
197                 strncpy(parameters->outfile, outfilename, sizeof(outfilename));
198         }
199         return 0;
200 }
201
202 /* -------------------------------------------------------------------------- */
203 int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol, char *indexfilename) {
204         /* parse the command line */
205         int totlen;
206         option_t long_option[]={
207                 {"ImgDir",REQ_ARG, NULL ,'y'},
208         };
209
210         const char optlist[] = "i:h";
211         totlen=sizeof(long_option);
212         img_fol->set_out_format = 0;
213         while (1) {
214                 int c = getopt_long(argc, argv,optlist,long_option,totlen);
215                 if (c == -1)
216                         break;
217                 switch (c) {
218                         case 'i':                       /* input file */
219                         {
220                                 char *infile = optarg;
221                                 parameters->decod_format = get_file_format(infile);
222                                 switch(parameters->decod_format) {
223                                         case J2K_CFMT:
224                                         case JP2_CFMT:
225                                         case JPT_CFMT:
226                                                 break;
227                                         default:
228                                                 fprintf(stderr, 
229                                                         "!! Unrecognized format for infile : %s [accept only *.j2k, *.jp2, *.jpc or *.jpt] !!\n\n", 
230                                                         infile);
231                                                 return 1;
232                                 }
233                                 strncpy(parameters->infile, infile, sizeof(parameters->infile)-1);
234                         }
235                         break;
236                                 
237                                 /* ----------------------------------------------------- */
238
239                         case 'h':                       /* display an help description */
240                                 decode_help_display();
241                                 return 1;                               
242
243                                 /* ------------------------------------------------------ */
244
245                         case 'y':                       /* Image Directory path */
246                                 {
247                                         img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1);
248                                         strcpy(img_fol->imgdirpath,optarg);
249                                         img_fol->set_imgdir=1;
250                                 }
251                                 break;
252
253                                 /* ----------------------------------------------------- */
254                         
255                         default:
256                                 fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, optarg);
257                                 break;
258                 }
259         }
260
261         /* check for possible errors */
262         if(img_fol->set_imgdir==1){
263                 if(!(parameters->infile[0]==0)){
264                         fprintf(stderr, "Error: options -ImgDir and -i cannot be used together !!\n");
265                         return 1;
266                 }
267                 if(img_fol->set_out_format == 0){
268                         fprintf(stderr, "Error: When -ImgDir is used, -OutFor <FORMAT> must be used !!\n");
269                         fprintf(stderr, "Only one format allowed! Valid format PGM, PPM, PNM, PGX, BMP, TIF, RAW and TGA!!\n");
270                         return 1;
271                 }
272                 if(!((parameters->outfile[0] == 0))){
273                         fprintf(stderr, "Error: options -ImgDir and -o cannot be used together !!\n");
274                         return 1;
275                 }
276         }else{
277                 if((parameters->infile[0] == 0) ) {
278                         fprintf(stderr, "Error: One of the options -i or -ImgDir must be specified\n");
279                         fprintf(stderr, "usage: image_to_j2k -i *.j2k/jp2/j2c (+ options)\n");
280                         return 1;
281                 }
282         }
283
284         return 0;
285 }
286
287 /* -------------------------------------------------------------------------- */
288
289 /**
290 sample error callback expecting a FILE* client object
291 */
292 void error_callback(const char *msg, void *client_data) {
293         FILE *stream = (FILE*)client_data;
294         fprintf(stream, "[ERROR] %s", msg);
295 }
296 /**
297 sample warning callback expecting a FILE* client object
298 */
299 void warning_callback(const char *msg, void *client_data) {
300         FILE *stream = (FILE*)client_data;
301         fprintf(stream, "[WARNING] %s", msg);
302 }
303 /**
304 sample debug callback expecting no client object
305 */
306 void info_callback(const char *msg, void *client_data) {
307         (void)client_data;
308         fprintf(stdout, "[INFO] %s", msg);
309 }
310
311 /* -------------------------------------------------------------------------- */
312
313 int main(int argc, char *argv[])
314 {
315   int ret;
316         opj_dparameters_t parameters;   /* decompression parameters */
317         img_fol_t img_fol;
318         opj_image_t *image = NULL;
319         FILE *fsrc = NULL;
320         bool bResult;
321         int num_images;
322         int i,imageno;
323         dircnt_t *dirptr;
324         opj_codec_t* dinfo = NULL;      /* handle to a decompressor */
325         opj_stream_t *cio = NULL;
326         opj_codestream_info_t cstr_info;  /* Codestream information structure */
327         char indexfilename[OPJ_PATH_LEN];       /* index file name */
328         OPJ_INT32 l_tile_x0,l_tile_y0;
329         OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y;
330
331         /* configure the event callbacks (not required) */
332
333         /* set decoding parameters to default values */
334         opj_set_default_decoder_parameters(&parameters);
335
336         /* Initialize indexfilename and img_fol */
337         *indexfilename = 0;
338         memset(&img_fol,0,sizeof(img_fol_t));
339
340         /* parse input and get user encoding parameters */
341         if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol, indexfilename) == 1) {
342                 return EXIT_FAILURE;
343         }
344
345         /* Initialize reading of directory */
346         if(img_fol.set_imgdir==1){      
347                 num_images=get_num_images(img_fol.imgdirpath);
348
349                 dirptr=(dircnt_t*)malloc(sizeof(dircnt_t));
350                 if(dirptr){
351                         dirptr->filename_buf = (char*)malloc(num_images*OPJ_PATH_LEN*sizeof(char));     // Stores at max 10 image file names
352                         dirptr->filename = (char**) malloc(num_images*sizeof(char*));
353
354                         if(!dirptr->filename_buf){
355                                 return EXIT_FAILURE;
356                         }
357                         for(i=0;i<num_images;i++){
358                                 dirptr->filename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN;
359                         }
360                 }
361                 if(load_images(dirptr,img_fol.imgdirpath)==1){
362                         return EXIT_FAILURE;
363                 }
364                 if (num_images==0){
365                         fprintf(stdout,"Folder is empty\n");
366                         return EXIT_FAILURE;
367                 }
368         }else{
369                 num_images=1;
370         }
371
372         /*Encoding image one by one*/
373         for(imageno = 0; imageno < num_images ; imageno++)
374         {
375                 image = NULL;
376                 fprintf(stderr,"\n");
377
378                 if(img_fol.set_imgdir==1){
379                         if (get_next_file(imageno, dirptr,&img_fol, &parameters)) {
380                                 fprintf(stderr,"skipping file...\n");
381                                 continue;
382                         }
383                 }
384
385                 /* read the input file and put it in memory */
386                 /* ---------------------------------------- */
387                 fsrc = fopen(parameters.infile, "rb");
388                 if (!fsrc) {
389                         fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile);
390                         return EXIT_FAILURE;
391                 }
392                 cio = opj_stream_create_default_file_stream(fsrc,true);
393                 /* decode the code-stream */
394                 /* ---------------------- */
395
396                 switch (parameters.decod_format) 
397                 {
398                         case J2K_CFMT:
399                         {
400                                 /* JPEG-2000 codestream */
401
402                                 /* get a decoder handle */
403                                 dinfo = opj_create_decompress(CODEC_J2K);
404                                 break;
405                         }
406                         case JP2_CFMT:
407                         {
408                                 /* JPEG 2000 compressed image data */
409                                 /* get a decoder handle */
410                                 dinfo = opj_create_decompress(CODEC_JP2);
411                                 break;
412                         }
413                         case JPT_CFMT:
414                         {
415                                 /* JPEG 2000, JPIP */
416                                 /* get a decoder handle */
417                                 dinfo = opj_create_decompress(CODEC_JPT);
418                                 break;
419                         }
420                         default:
421                                 fprintf(stderr, "skipping file..\n");
422                                 opj_stream_destroy(cio);
423                                 continue;
424                 }
425                 /* catch events using our callbacks and give a local context */
426                         
427                 /* setup the decoder decoding parameters using user parameters */
428                 opj_setup_decoder(dinfo, &parameters);
429
430                 /* decode the stream and fill the image structure */
431                 /*              if (*indexfilename)                             // If need to extract codestream information
432                                 image = opj_decode_with_info(dinfo, cio, &cstr_info);
433                         else
434                         */
435                 bResult = opj_read_header(
436                         dinfo,
437                         &image,
438                         &l_tile_x0,
439                         &l_tile_y0,
440                         &l_tile_width,
441                         &l_tile_height,
442                         &l_nb_tiles_x,
443                         &l_nb_tiles_y,
444                         cio);
445                 //image = opj_decode(dinfo, cio);
446                 //bResult = bResult && (image != 00);
447                 //bResult = bResult && opj_end_decompress(dinfo,cio);
448                 //if
449                 //      (!image) 
450                 //{
451                 //      fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
452                 //      opj_destroy_codec(dinfo);
453                 //      opj_stream_destroy(cio);
454                 //      fclose(fsrc);
455                 //      return EXIT_FAILURE;
456                 //}
457                 /* dump image */
458     if(!image)
459       {
460                         fprintf(stderr, "ERROR -> j2k_to_image: failed to read header\n");
461                         return EXIT_FAILURE;
462       }
463     j2k_dump_image(stdout, image);
464
465                 /* dump cp */
466     //j2k_dump_cp(stdout, image, dinfo->m_codec);
467
468                 /* close the byte stream */
469                 opj_stream_destroy(cio);
470                 fclose(fsrc);
471                 /* Write the index to disk */
472                 if (*indexfilename) {
473                         char bSuccess;
474                         bSuccess = write_index_file(&cstr_info, indexfilename);
475                         if (bSuccess) {
476                                 fprintf(stderr, "Failed to output index file\n");
477         ret = EXIT_FAILURE;
478                         }
479                 }
480
481                 /* free remaining structures */
482                 if (dinfo) {
483                         opj_destroy_codec(dinfo);
484                 }
485                 /* free codestream information structure */
486                 if (*indexfilename)     
487                         opj_destroy_cstr_info(&cstr_info);
488                 /* free image data structure */
489                 opj_image_destroy(image);
490
491         }
492
493         return ret;
494 }
495 //end main