Fix several memory and resource leaks
[openjpeg.git] / tests / test_tile_decoder.c
1 /*
2  * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 #define USE_OPJ_DEPRECATED
27 /* set this macro to enable profiling for the given test */
28 /* warning : in order to be effective, openjpeg must have been built with profiling enabled !! */
29 /*#define _PROFILE*/
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <math.h>
35
36 #ifdef _WIN32
37 #include <malloc.h>
38 #else
39 #include <stdlib.h>
40 #endif
41
42 #include "opj_config.h"
43 #include <stdlib.h>
44
45 #ifdef _WIN32
46 #include <windows.h>
47 #define strcasecmp _stricmp
48 #define strncasecmp _strnicmp
49 #else
50 #include <strings.h>
51 #endif /* _WIN32 */
52
53 #include "openjpeg.h"
54 #include "format_defs.h"
55
56
57 /* -------------------------------------------------------------------------- */
58 /* Declarations                                                               */ 
59 int get_file_format(const char *filename);
60 static int infile_format(const char *fname);
61
62 /* -------------------------------------------------------------------------- */
63 int get_file_format(const char *filename) {
64         unsigned int i;
65         static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "rawl", "tga", "png", "j2k", "jp2", "jpt", "j2c", "jpc" };
66         static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT, J2K_CFMT };
67         char * ext = strrchr(filename, '.');
68         if (ext == NULL)
69                 return -1;
70         ext++;
71         if(ext) {
72                 for(i = 0; i < sizeof(format)/sizeof(*format); i++) {
73                         if(strcasecmp(ext, extension[i]) == 0) {
74                                 return format[i];
75                         }
76                 }
77         }
78
79         return -1;
80 }
81
82 /* -------------------------------------------------------------------------- */
83 #define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
84 #define JP2_MAGIC "\x0d\x0a\x87\x0a"
85 /* position 45: "\xff\x52" */
86 #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
87
88 static int infile_format(const char *fname)
89 {
90         FILE *reader;
91         const char *s, *magic_s;
92         int ext_format, magic_format;
93         unsigned char buf[12];
94         unsigned int l_nb_read;
95
96         reader = fopen(fname, "rb");
97
98         if (reader == NULL)
99                 return -1;
100
101         memset(buf, 0, 12);
102         l_nb_read = (unsigned int)fread(buf, 1, 12, reader);
103         fclose(reader);
104         if (l_nb_read != 12)
105                 return -1;
106
107         ext_format = get_file_format(fname);
108
109         if (ext_format == JPT_CFMT)
110                 return JPT_CFMT;
111
112         if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
113                 magic_format = JP2_CFMT;
114                 magic_s = ".jp2";
115         }
116         else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
117                 magic_format = J2K_CFMT;
118                 magic_s = ".j2k or .jpc or .j2c";
119         }
120         else
121                 return -1;
122
123         if (magic_format == ext_format)
124                 return ext_format;
125
126         s = fname + strlen(fname) - 4;
127
128         fputs("\n===========================================\n", stderr);
129         fprintf(stderr, "The extension of this file is incorrect.\n"
130                         "FOUND %s. SHOULD BE %s\n", s, magic_s);
131         fputs("===========================================\n", stderr);
132
133         return magic_format;
134 }
135
136
137 /* -------------------------------------------------------------------------- */
138
139 /**
140   sample error debug callback expecting no client object
141  */
142 static void error_callback(const char *msg, void *client_data) {
143         (void)client_data;
144         fprintf(stdout, "[ERROR] %s", msg);
145 }
146 /**
147   sample warning debug callback expecting no client object
148  */
149 static void warning_callback(const char *msg, void *client_data) {
150         (void)client_data;
151         fprintf(stdout, "[WARNING] %s", msg);
152 }
153 /**
154   sample debug callback expecting no client object
155  */
156 static void info_callback(const char *msg, void *client_data) {
157         (void)client_data;
158         fprintf(stdout, "[INFO] %s", msg);
159 }
160
161 /* -------------------------------------------------------------------------- */
162
163 int main (int argc, char *argv[])
164 {
165         opj_dparameters_t l_param;
166         opj_codec_t * l_codec;
167         opj_image_t * l_image;
168         opj_stream_t * l_stream;
169         OPJ_UINT32 l_data_size;
170         OPJ_UINT32 l_max_data_size = 1000;
171         OPJ_UINT32 l_tile_index;
172         OPJ_BYTE * l_data = (OPJ_BYTE *) malloc(1000);
173         OPJ_BOOL l_go_on = OPJ_TRUE;
174         OPJ_UINT32 l_nb_comps=0 ;
175         OPJ_INT32 l_current_tile_x0,l_current_tile_y0,l_current_tile_x1,l_current_tile_y1;
176
177         int da_x0=0;
178         int da_y0=0;
179         int da_x1=1000;
180         int da_y1=1000;
181         const char *input_file;
182
183         /* should be test_tile_decoder 0 0 1000 1000 tte1.j2k */
184         if( argc == 6 )
185         {
186                 da_x0=atoi(argv[1]);
187                 da_y0=atoi(argv[2]);
188                 da_x1=atoi(argv[3]);
189                 da_y1=atoi(argv[4]);
190                 input_file = argv[5];
191
192         }
193         else
194         {
195                 da_x0=0;
196                 da_y0=0;
197                 da_x1=1000;
198                 da_y1=1000;
199                 input_file = "test.j2k";
200         }
201
202         if (! l_data) {
203                 return EXIT_FAILURE;
204         }
205
206         l_stream = opj_stream_create_default_file_stream(input_file,OPJ_TRUE);
207         if (!l_stream){
208                 free(l_data);
209                 fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
210                 return EXIT_FAILURE;
211         }
212
213         /* Set the default decoding parameters */
214         opj_set_default_decoder_parameters(&l_param);
215
216         /* */
217         l_param.decod_format = infile_format(input_file);
218
219         /** you may here add custom decoding parameters */
220         /* do not use layer decoding limitations */
221         l_param.cp_layer = 0;
222
223         /* do not use resolutions reductions */
224         l_param.cp_reduce = 0;
225
226         /* to decode only a part of the image data */
227         /*opj_restrict_decoding(&l_param,0,0,1000,1000);*/
228
229
230         switch(l_param.decod_format) {
231                 case J2K_CFMT:  /* JPEG-2000 codestream */
232                         {
233                                 /* Get a decoder handle */
234                                 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
235                                 break;
236                         }
237                 case JP2_CFMT:  /* JPEG 2000 compressed image data */
238                         {
239                                 /* Get a decoder handle */
240                                 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
241                                 break;
242                         }
243                 default:
244                         {    
245                                 fprintf(stderr, "ERROR -> Not a valid JPEG2000 file!\n");
246                                 free(l_data);
247                                 opj_stream_destroy(l_stream);
248                                 return EXIT_FAILURE;
249                         }
250         }
251
252         /* catch events using our callbacks and give a local context */         
253         opj_set_info_handler(l_codec, info_callback,00);
254         opj_set_warning_handler(l_codec, warning_callback,00);
255         opj_set_error_handler(l_codec, error_callback,00);
256
257         /* Setup the decoder decoding parameters using user parameters */
258         if (! opj_setup_decoder(l_codec, &l_param))
259         {
260                 fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n");
261                 free(l_data);
262                 opj_stream_destroy(l_stream);
263                 opj_destroy_codec(l_codec);
264                 return EXIT_FAILURE;
265         }
266
267         /* Read the main header of the codestream and if necessary the JP2 boxes*/
268         if (! opj_read_header(l_stream, l_codec, &l_image))
269         {
270                 fprintf(stderr, "ERROR -> j2k_to_image: failed to read the header\n");
271                 free(l_data);
272                 opj_stream_destroy(l_stream);
273                 opj_destroy_codec(l_codec);
274                 return EXIT_FAILURE;
275         }
276
277         if (!opj_set_decode_area(l_codec, l_image, da_x0, da_y0,da_x1, da_y1)){
278                 fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n");
279                 free(l_data);
280                 opj_stream_destroy(l_stream);
281                 opj_destroy_codec(l_codec);
282                 opj_image_destroy(l_image);
283                 return EXIT_FAILURE;
284         }
285
286
287         while (l_go_on)
288         {
289                 if (! opj_read_tile_header( l_codec,
290                                         l_stream,
291                                         &l_tile_index,
292                                         &l_data_size,
293                                         &l_current_tile_x0,
294                                         &l_current_tile_y0,
295                                         &l_current_tile_x1,
296                                         &l_current_tile_y1,
297                                         &l_nb_comps,
298                                         &l_go_on))
299                 {
300                         free(l_data);
301                         opj_stream_destroy(l_stream);
302                         opj_destroy_codec(l_codec);
303                         opj_image_destroy(l_image);
304                         return EXIT_FAILURE;
305                 }
306
307                 if (l_go_on)
308                 {
309                         if (l_data_size > l_max_data_size)
310                         {
311                                 OPJ_BYTE *l_new_data = (OPJ_BYTE *) realloc(l_data, l_data_size);
312                                 if (! l_new_data)
313                                 {
314                                         free(l_new_data);
315                                         opj_stream_destroy(l_stream);
316                                         opj_destroy_codec(l_codec);
317                                         opj_image_destroy(l_image);
318                                         return EXIT_FAILURE;
319                                 }
320                                 l_data = l_new_data;
321                                 l_max_data_size = l_data_size;
322                         }
323
324                         if (! opj_decode_tile_data(l_codec,l_tile_index,l_data,l_data_size,l_stream))
325                         {
326                                 free(l_data);
327                                 opj_stream_destroy(l_stream);
328                                 opj_destroy_codec(l_codec);
329                                 opj_image_destroy(l_image);
330                                 return EXIT_FAILURE;
331                         }
332                         /** now should inspect image to know the reduction factor and then how to behave with data */
333                 }
334         }
335
336         if (! opj_end_decompress(l_codec,l_stream))
337         {
338                 free(l_data);
339                 opj_stream_destroy(l_stream);
340                 opj_destroy_codec(l_codec);
341                 opj_image_destroy(l_image);
342                 return EXIT_FAILURE;
343         }
344
345         /* Free memory */
346         free(l_data);
347         opj_stream_destroy(l_stream);
348         opj_destroy_codec(l_codec);
349         opj_image_destroy(l_image);
350
351         /* Print profiling*/
352         /*PROFPRINT();*/
353
354         return EXIT_SUCCESS;
355 }
356