[trunk] Handle multi components files with PGM outputs
[openjpeg.git] / tests / compare_images.c
1 /*
2  * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France 
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
27 /*
28  * compare_images.c
29  *
30  *  Created on: 8 juil. 2011
31  *      Author: mickael
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <math.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <assert.h>
40
41 #include "opj_apps_config.h"
42 #include "opj_getopt.h"
43
44 #include "openjpeg.h"
45 #include "format_defs.h"
46 #include "convert.h"
47
48 #ifdef OPJ_HAVE_LIBTIFF
49 #include <tiffio.h> /* TIFFSetWarningHandler */
50 #endif /* OPJ_HAVE_LIBTIFF */
51
52 /*******************************************************************************
53  * Parse MSE and PEAK input values (
54  * separator = ":"
55  *******************************************************************************/
56 static double* parseToleranceValues( char* inArg, const int nbcomp)
57 {
58   double* outArgs= malloc((size_t)nbcomp * sizeof(double));
59   int it_comp = 0;
60   const char delims[] = ":";
61   char *result = strtok( inArg, delims );
62
63   while( (result != NULL) && (it_comp < nbcomp ))
64     {
65     outArgs[it_comp] = atof(result);
66     result = strtok( NULL, delims );
67     it_comp++;
68     }
69
70   if (it_comp != nbcomp)
71     {
72     free(outArgs);
73     return NULL;
74     }
75   /* else */
76   return outArgs;
77 }
78
79 /*******************************************************************************
80  * Command line help function
81  *******************************************************************************/
82 static void compare_images_help_display(void)
83 {
84   fprintf(stdout,"\nList of parameters for the compare_images function  \n");
85   fprintf(stdout,"\n");
86   fprintf(stdout,"  -b \t REQUIRED \t filename to the reference/baseline PGX/TIF/PNM image \n");
87   fprintf(stdout,"  -t \t REQUIRED \t filename to the test PGX/TIF/PNM image\n");
88   fprintf(stdout,"  -n \t REQUIRED \t number of component of the image (used to generate correct filename)\n");
89   fprintf(stdout,"  -m \t OPTIONAL \t list of MSE tolerances, separated by : (size must correspond to the number of component) of \n");
90   fprintf(stdout,"  -p \t OPTIONAL \t list of PEAK tolerances, separated by : (size must correspond to the number of component) \n");
91   fprintf(stdout,"  -s \t OPTIONAL \t 1 or 2 filename separator to take into account PGX/PNM image with different components, "
92                                       "please indicate b or t before separator to indicate respectively the separator "
93                                       "for ref/base file and for test file.  \n");
94   fprintf(stdout,"  -d \t OPTIONAL \t indicate if you want to run this function as conformance test or as non regression test\n");
95   fprintf(stdout,"\n");
96 }
97
98 static int get_decod_format_from_string(const char *filename)
99 {
100   const int dot = '.';
101   char * ext = strrchr(filename, dot);
102   if( strcmp(ext,".pgx") == 0 ) return PGX_DFMT;
103   if( strcmp(ext,".tif") == 0 ) return TIF_DFMT;
104   if( strcmp(ext,".ppm") == 0 ) return PXM_DFMT;
105   return -1;
106 }
107
108
109 /*******************************************************************************
110  * Create filenames from a filename using separator and nb components
111  * (begin from 0)
112  *******************************************************************************/
113 static char* createMultiComponentsFilename(const char* inFilename, const int indexF, const char* separator)
114 {
115   char s[255];
116   char *outFilename, *ptr;
117   const char token = '.';
118   int posToken = 0;
119   int decod_format;
120
121   /*printf("inFilename = %s\n", inFilename);*/
122   if ((ptr = strrchr(inFilename, token)) != NULL)
123     {
124     posToken = (int) (strlen(inFilename) - strlen(ptr));
125     /*printf("Position of %c character inside inFilename = %d\n", token, posToken);*/
126     }
127   else
128     {
129     /*printf("Token %c not found\n", token);*/
130     outFilename = (char*)malloc(1);
131     outFilename[0] = '\0';
132     return outFilename;
133     }
134
135   outFilename = (char*)malloc((size_t)(posToken + 7) * sizeof(char)); /*6*/
136
137   strncpy(outFilename, inFilename, (size_t)posToken);
138
139   outFilename[posToken] = '\0';
140
141   strcat(outFilename, separator);
142
143   sprintf(s, "%i", indexF);
144   strcat(outFilename, s);
145
146   decod_format = get_decod_format_from_string(inFilename);
147   if( decod_format == PGX_DFMT )
148     {
149     strcat(outFilename, ".pgx");
150     }
151   else if( decod_format == PXM_DFMT )
152     {
153     strcat(outFilename, ".pgm");
154     }
155
156   /*printf("outfilename: %s\n", outFilename);*/
157   return outFilename;
158 }
159
160 /*******************************************************************************
161  *
162  *******************************************************************************/
163 static opj_image_t* readImageFromFilePPM(const char* filename, int nbFilenamePGX, const char *separator)
164 {
165   int it_file;
166   opj_image_t* image_read = NULL;
167   opj_image_t* image = NULL;
168   opj_cparameters_t parameters;
169   opj_image_cmptparm_t* param_image_read;
170   int** data;
171
172   /* If separator is empty => nb file to read is equal to one*/
173   if ( strlen(separator) == 0 )
174     nbFilenamePGX = 1;
175
176   /* set encoding parameters to default values */
177   opj_set_default_encoder_parameters(&parameters);
178   parameters.decod_format = PXM_DFMT;
179   strcpy(parameters.infile, filename);
180
181   /* Allocate memory*/
182   param_image_read = malloc((size_t)nbFilenamePGX * sizeof(opj_image_cmptparm_t));
183   data = malloc((size_t)nbFilenamePGX * sizeof(*data));
184
185   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
186     {
187     /* Create the right filename*/
188     char *filenameComponentPGX;
189     if (strlen(separator) == 0)
190       {
191       filenameComponentPGX = malloc((strlen(filename) + 1) * sizeof(*filenameComponentPGX));
192       strcpy(filenameComponentPGX, filename);
193       }
194     else
195       filenameComponentPGX = createMultiComponentsFilename(filename, it_file, separator);
196
197     /* Read the tif file corresponding to the component */
198     image_read = pnmtoimage(filenameComponentPGX, &parameters);
199     if (!image_read)
200       {
201       int it_free_data;
202       fprintf(stderr, "Unable to load pgx file\n");
203
204       free(param_image_read);
205
206       for (it_free_data = 0; it_free_data < it_file; it_free_data++) {
207         free(data[it_free_data]);
208       }
209       free(data);
210
211       free(filenameComponentPGX);
212
213       return NULL;
214       }
215
216     /* Set the image_read parameters*/
217     param_image_read[it_file].x0 = 0;
218     param_image_read[it_file].y0 = 0;
219     param_image_read[it_file].dx = 0;
220     param_image_read[it_file].dy = 0;
221     param_image_read[it_file].h = image_read->comps->h;
222     param_image_read[it_file].w = image_read->comps->w;
223     param_image_read[it_file].bpp = image_read->comps->bpp;
224     param_image_read[it_file].prec = image_read->comps->prec;
225     param_image_read[it_file].sgnd = image_read->comps->sgnd;
226
227     /* Copy data*/
228     data[it_file] = malloc(param_image_read[it_file].h * param_image_read[it_file].w * sizeof(int));
229     memcpy(data[it_file], image_read->comps->data, image_read->comps->h * image_read->comps->w * sizeof(int));
230
231     /* Free memory*/
232     opj_image_destroy(image_read);
233     free(filenameComponentPGX);
234     }
235
236   image = opj_image_create((OPJ_UINT32)nbFilenamePGX, param_image_read, OPJ_CLRSPC_UNSPECIFIED);
237   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
238     {
239     /* Copy data into output image and free memory*/
240     memcpy(image->comps[it_file].data, data[it_file], image->comps[it_file].h * image->comps[it_file].w * sizeof(int));
241     free(data[it_file]);
242     }
243
244   /* Free memory*/
245   free(param_image_read);
246   free(data);
247
248   return image;
249 }
250
251 static opj_image_t* readImageFromFileTIF(const char* filename, int nbFilenamePGX, const char *separator)
252 {
253   int it_file;
254   opj_image_t* image_read = NULL;
255   opj_image_t* image = NULL;
256   opj_cparameters_t parameters;
257   opj_image_cmptparm_t* param_image_read;
258   int** data;
259
260   /* conformance test suite produce annoying warning/error:
261    * TIFFReadDirectory: Warning, /.../data/baseline/conformance/jp2_1.tif: unknown field with tag 37724 (0x935c) encountered.
262    * TIFFOpen: /.../data/baseline/nonregression/opj_jp2_1.tif: Cannot open.
263    * On Win32 this open a message box by default, so remove it from the test suite:
264    */
265 #ifdef OPJ_HAVE_LIBTIFF
266   TIFFSetWarningHandler(NULL);
267   TIFFSetErrorHandler(NULL);
268 #endif
269
270   /* If separator is empty => nb file to read is equal to one*/
271   if ( strlen(separator) == 0 )
272     nbFilenamePGX = 1;
273
274   /* set encoding parameters to default values */
275   opj_set_default_encoder_parameters(&parameters);
276   parameters.decod_format = TIF_DFMT;
277   strcpy(parameters.infile, filename);
278
279   /* Allocate memory*/
280   param_image_read = malloc((size_t)nbFilenamePGX * sizeof(opj_image_cmptparm_t));
281   data = malloc((size_t)nbFilenamePGX * sizeof(*data));
282
283   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
284     {
285     /* Create the right filename*/
286     char *filenameComponentPGX;
287     if (strlen(separator) == 0)
288       {
289       filenameComponentPGX = malloc((strlen(filename) + 1) * sizeof(*filenameComponentPGX));
290       strcpy(filenameComponentPGX, filename);
291       }
292     else
293       filenameComponentPGX = createMultiComponentsFilename(filename, it_file, separator);
294
295     /* Read the tif file corresponding to the component */
296 #ifdef OPJ_HAVE_LIBTIFF
297     image_read = tiftoimage(filenameComponentPGX, &parameters);
298 #endif
299     if (!image_read)
300       {
301       int it_free_data;
302       fprintf(stderr, "Unable to load TIF file\n");
303
304       free(param_image_read);
305
306       for (it_free_data = 0; it_free_data < it_file; it_free_data++) {
307         free(data[it_free_data]);
308       }
309       free(data);
310
311       free(filenameComponentPGX);
312
313       return NULL;
314       }
315
316     /* Set the image_read parameters*/
317     param_image_read[it_file].x0 = 0;
318     param_image_read[it_file].y0 = 0;
319     param_image_read[it_file].dx = 0;
320     param_image_read[it_file].dy = 0;
321     param_image_read[it_file].h = image_read->comps->h;
322     param_image_read[it_file].w = image_read->comps->w;
323     param_image_read[it_file].bpp = image_read->comps->bpp;
324     param_image_read[it_file].prec = image_read->comps->prec;
325     param_image_read[it_file].sgnd = image_read->comps->sgnd;
326
327     /* Copy data*/
328     data[it_file] = malloc(param_image_read[it_file].h * param_image_read[it_file].w * sizeof(int));
329     memcpy(data[it_file], image_read->comps->data, image_read->comps->h * image_read->comps->w * sizeof(int));
330
331     /* Free memory*/
332     opj_image_destroy(image_read);
333     free(filenameComponentPGX);
334     }
335
336   image = opj_image_create((OPJ_UINT32)nbFilenamePGX, param_image_read, OPJ_CLRSPC_UNSPECIFIED);
337   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
338     {
339     /* Copy data into output image and free memory*/
340     memcpy(image->comps[it_file].data, data[it_file], image->comps[it_file].h * image->comps[it_file].w * sizeof(int));
341     free(data[it_file]);
342     }
343
344   /* Free memory*/
345   free(param_image_read);
346   free(data);
347
348   return image;
349 }
350
351 static opj_image_t* readImageFromFilePGX(const char* filename, int nbFilenamePGX, const char *separator)
352 {
353   int it_file;
354   opj_image_t* image_read = NULL;
355   opj_image_t* image = NULL;
356   opj_cparameters_t parameters;
357   opj_image_cmptparm_t* param_image_read;
358   int** data;
359
360   /* If separator is empty => nb file to read is equal to one*/
361   if ( strlen(separator) == 0 )
362     nbFilenamePGX = 1;
363
364   /* set encoding parameters to default values */
365   opj_set_default_encoder_parameters(&parameters);
366   parameters.decod_format = PGX_DFMT;
367   strcpy(parameters.infile, filename);
368
369   /* Allocate memory*/
370   param_image_read = malloc((size_t)nbFilenamePGX * sizeof(opj_image_cmptparm_t));
371   data = malloc((size_t)nbFilenamePGX * sizeof(*data));
372
373   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
374     {
375     /* Create the right filename*/
376     char *filenameComponentPGX;
377     if (strlen(separator) == 0)
378       {
379       filenameComponentPGX = malloc((strlen(filename) + 1) * sizeof(*filenameComponentPGX));
380       strcpy(filenameComponentPGX, filename);
381       }
382     else
383       filenameComponentPGX = createMultiComponentsFilename(filename, it_file, separator);
384
385     /* Read the pgx file corresponding to the component */
386     image_read = pgxtoimage(filenameComponentPGX, &parameters);
387     if (!image_read)
388       {
389       int it_free_data;
390       fprintf(stderr, "Unable to load pgx file\n");
391
392       free(param_image_read);
393
394       for (it_free_data = 0; it_free_data < it_file; it_free_data++) {
395         free(data[it_free_data]);
396       }
397       free(data);
398
399       free(filenameComponentPGX);
400
401       return NULL;
402       }
403
404     /* Set the image_read parameters*/
405     param_image_read[it_file].x0 = 0;
406     param_image_read[it_file].y0 = 0;
407     param_image_read[it_file].dx = 0;
408     param_image_read[it_file].dy = 0;
409     param_image_read[it_file].h = image_read->comps->h;
410     param_image_read[it_file].w = image_read->comps->w;
411     param_image_read[it_file].bpp = image_read->comps->bpp;
412     param_image_read[it_file].prec = image_read->comps->prec;
413     param_image_read[it_file].sgnd = image_read->comps->sgnd;
414
415     /* Copy data*/
416     data[it_file] = malloc(param_image_read[it_file].h * param_image_read[it_file].w * sizeof(int));
417     memcpy(data[it_file], image_read->comps->data, image_read->comps->h * image_read->comps->w * sizeof(int));
418
419     /* Free memory*/
420     opj_image_destroy(image_read);
421     free(filenameComponentPGX);
422     }
423
424   image = opj_image_create((OPJ_UINT32)nbFilenamePGX, param_image_read, OPJ_CLRSPC_UNSPECIFIED);
425   for (it_file = 0; it_file < nbFilenamePGX; it_file++)
426     {
427     /* Copy data into output image and free memory*/
428     memcpy(image->comps[it_file].data, data[it_file], image->comps[it_file].h * image->comps[it_file].w * sizeof(int));
429     free(data[it_file]);
430     }
431
432   /* Free memory*/
433   free(param_image_read);
434   free(data);
435
436   return image;
437 }
438
439 #if defined(OPJ_HAVE_LIBPNG) && 0 /* remove for now */
440 /*******************************************************************************
441  *
442  *******************************************************************************/
443 static int imageToPNG(const opj_image_t* image, const char* filename, int num_comp_select)
444 {
445   opj_image_cmptparm_t param_image_write;
446   opj_image_t* image_write = NULL;
447
448   param_image_write.x0 = 0;
449   param_image_write.y0 = 0;
450   param_image_write.dx = 0;
451   param_image_write.dy = 0;
452   param_image_write.h = image->comps[num_comp_select].h;
453   param_image_write.w = image->comps[num_comp_select].w;
454   param_image_write.bpp = image->comps[num_comp_select].bpp;
455   param_image_write.prec = image->comps[num_comp_select].prec;
456   param_image_write.sgnd = image->comps[num_comp_select].sgnd;
457
458   image_write = opj_image_create(1u, &param_image_write, OPJ_CLRSPC_GRAY);
459   memcpy(image_write->comps->data, image->comps[num_comp_select].data, param_image_write.h * param_image_write.w * sizeof(int));
460
461   imagetopng(image_write, filename);
462
463   opj_image_destroy(image_write);
464
465   return EXIT_SUCCESS;
466 }
467 #endif
468
469 typedef struct test_cmp_parameters
470 {
471   /**  */
472   char* base_filename;
473   /**  */
474   char* test_filename;
475   /** Number of components */
476   int nbcomp;
477   /**  */
478   double* tabMSEvalues;
479   /**  */
480   double* tabPEAKvalues;
481   /**  */
482   int nr_flag;
483   /**  */
484   char separator_base[2];
485   /**  */
486   char separator_test[2];
487
488 } test_cmp_parameters;
489
490 /* return decode format PGX / TIF / PPM , return -1 on error */
491 static int get_decod_format(test_cmp_parameters* param)
492 {
493   int base_format = get_decod_format_from_string( param->base_filename );
494   int test_format = get_decod_format_from_string( param->test_filename );
495   if( base_format != test_format ) return -1;
496   /* handle case -1: */
497   return base_format;
498 }
499
500 /*******************************************************************************
501  * Parse command line
502  *******************************************************************************/
503 static int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
504 {
505   char *MSElistvalues = NULL;  char *PEAKlistvalues= NULL;
506   char *separatorList = NULL;
507   int sizemembasefile, sizememtestfile;
508   int index, flagM=0, flagP=0;
509   const char optlist[] = "b:t:n:m:p:s:d";
510   int c;
511
512   /* Init parameters*/
513   param->base_filename = NULL;
514   param->test_filename = NULL;
515   param->nbcomp = 0;
516   param->tabMSEvalues = NULL;
517   param->tabPEAKvalues = NULL;
518   param->nr_flag = 0;
519   param->separator_base[0] = 0;
520   param->separator_test[0] = 0;
521
522   opj_opterr = 0;
523
524   while ((c = opj_getopt(argc, argv, optlist)) != -1)
525     switch (c)
526       {
527       case 'b':
528         sizemembasefile = (int)strlen(opj_optarg)+1;
529         param->base_filename = (char*) malloc((size_t)sizemembasefile);
530         param->base_filename[0] = '\0';
531         strncpy(param->base_filename, opj_optarg, strlen(opj_optarg));
532         param->base_filename[strlen(opj_optarg)] = '\0';
533         /*printf("param->base_filename = %s [%d / %d]\n", param->base_filename, strlen(param->base_filename), sizemembasefile );*/
534         break;
535       case 't':
536         sizememtestfile = (int) strlen(opj_optarg) + 1;
537         param->test_filename = (char*) malloc((size_t)sizememtestfile);
538         param->test_filename[0] = '\0';
539         strncpy(param->test_filename, opj_optarg, strlen(opj_optarg));
540         param->test_filename[strlen(opj_optarg)] = '\0';
541         /*printf("param->test_filename = %s [%d / %d]\n", param->test_filename, strlen(param->test_filename), sizememtestfile);*/
542        break;
543       case 'n':
544         param->nbcomp = atoi(opj_optarg);
545         break;
546       case 'm':
547         MSElistvalues = opj_optarg;
548         flagM = 1;
549         break;
550       case 'p':
551         PEAKlistvalues = opj_optarg;
552         flagP = 1;
553         break;
554       case 'd':
555         param->nr_flag = 1;
556         break;
557       case 's':
558         separatorList = opj_optarg;
559         break;
560       case '?':
561         if ((opj_optopt == 'b') || (opj_optopt == 't') || (opj_optopt == 'n') || (opj_optopt == 'p') || (opj_optopt == 'm') || (opj_optopt
562             == 's'))
563           fprintf(stderr, "Option -%c requires an argument.\n", opj_optopt);
564         else
565           if (isprint(opj_optopt)) fprintf(stderr, "Unknown option `-%c'.\n", opj_optopt);
566           else fprintf(stderr, "Unknown option character `\\x%x'.\n", opj_optopt);
567         return 1;
568       default:
569         fprintf(stderr, "WARNING -> this option is not valid \"-%c %s\"\n", c, opj_optarg);
570         break;
571       }
572
573   if (opj_optind != argc)
574     {
575     for (index = opj_optind; index < argc; index++)
576       fprintf(stderr,"Non-option argument %s\n", argv[index]);
577     return 1;
578     }
579
580   if (param->nbcomp == 0)
581     {
582     fprintf(stderr,"Need to indicate the number of components !\n");
583     return 1;
584     }
585   /* else */
586   if ( flagM && flagP )
587     {
588     param->tabMSEvalues = parseToleranceValues( MSElistvalues, param->nbcomp);
589     param->tabPEAKvalues = parseToleranceValues( PEAKlistvalues, param->nbcomp);
590     if ( (param->tabMSEvalues == NULL) || (param->tabPEAKvalues == NULL))
591       {
592       fprintf(stderr,"MSE and PEAK values are not correct (respectively need %d values)\n",param->nbcomp);
593       return 1;
594       }
595     }
596
597   /* Get separators after corresponding letter (b or t)*/
598   if (separatorList != NULL)
599     {
600     if( (strlen(separatorList) ==2) || (strlen(separatorList) ==4) )
601       {
602       /* keep original string*/
603       int sizeseplist = (int)strlen(separatorList)+1;
604       char* separatorList2 = (char*)malloc( (size_t)sizeseplist );
605       separatorList2[0] = '\0';
606       strncpy(separatorList2, separatorList, strlen(separatorList));
607       separatorList2[strlen(separatorList)] = '\0';
608       /*printf("separatorList2 = %s [%d / %d]\n", separatorList2, strlen(separatorList2), sizeseplist);*/
609
610       if (strlen(separatorList) == 2) /* one separator behind b or t*/
611         {
612         char *resultT = NULL;
613         resultT = strtok(separatorList2, "t");
614         if (strlen(resultT) == strlen(separatorList)) /* didn't find t character, try to find b*/
615           {
616           char *resultB = NULL;
617           resultB = strtok(resultT, "b");
618           if (strlen(resultB) == 1)
619             {
620             param->separator_base[0] = separatorList[1];
621             param->separator_base[1] = 0;
622             param->separator_test[0] = 0;
623             }
624           else /* not found b*/
625             {
626             free(separatorList2);
627             return 1;
628             }
629           }
630         else /* found t*/
631           {
632           param->separator_base[0] = 0;
633           param->separator_test[0] = separatorList[1];
634           param->separator_test[1] = 0;
635           }
636         /*printf("sep b = %s [%d] and sep t = %s [%d]\n",param->separator_base, strlen(param->separator_base), param->separator_test, strlen(param->separator_test) );*/
637         }
638       else /* == 4 characters we must found t and b*/
639         {
640         char *resultT = NULL;
641         resultT = strtok(separatorList2, "t");
642         if (strlen(resultT) == 3) /* found t in first place*/
643           {
644           char *resultB = NULL;
645           resultB = strtok(resultT, "b");
646           if (strlen(resultB) == 1) /* found b after t*/
647             {
648             param->separator_test[0] = separatorList[1];
649             param->separator_test[1] = 0;
650             param->separator_base[0] = separatorList[3];
651             param->separator_base[1] = 0;
652             }
653           else /* didn't find b after t*/
654             {
655             free(separatorList2);
656             return 1;
657             }
658           }
659         else /* == 2, didn't find t in first place*/
660           {
661           char *resultB = NULL;
662           resultB = strtok(resultT, "b");
663           if (strlen(resultB) == 1) /* found b in first place*/
664             {
665             param->separator_base[0] = separatorList[1];
666             param->separator_base[1] = 0;
667             param->separator_test[0] = separatorList[3];
668             param->separator_test[1] = 0;
669             }
670           else /* didn't found b in first place => problem*/
671             {
672             free(separatorList2);
673             return 1;
674             }
675           }
676         }
677       free(separatorList2);
678       }
679     else /* wrong number of argument after -s*/
680       {
681       return 1;
682       }
683     }
684   else
685     {
686     if (param->nbcomp == 1)
687       {
688       assert( param->separator_base[0] == 0 );
689       assert( param->separator_test[0] == 0 );
690       }
691     else
692       {
693       fprintf(stderr,"If number of component is > 1, we need separator\n");
694       return 1;
695       }
696     }
697
698
699   if ( (param->nr_flag) && (flagP || flagM) )
700     {
701     fprintf(stderr,"Wrong input parameters list: it is non-regression test or tolerance comparison\n");
702     return 1;
703     }
704   if ( (!param->nr_flag) && (!flagP || !flagM) )
705     {
706     fprintf(stderr,"Wrong input parameters list: it is non-regression test or tolerance comparison\n");
707     return 1;
708     }
709
710   return 0;
711 }
712
713 /*******************************************************************************
714  * MAIN
715  *******************************************************************************/
716 int main(int argc, char **argv)
717 {
718   test_cmp_parameters inParam;
719   OPJ_UINT32 it_comp, itpxl;
720   int failed = 1;
721   int nbFilenamePGXbase = 0, nbFilenamePGXtest = 0;
722   char *filenamePNGtest= NULL, *filenamePNGbase = NULL, *filenamePNGdiff = NULL;
723   int memsizebasefilename, memsizetestfilename;
724   size_t memsizedifffilename;
725   int valueDiff = 0, nbPixelDiff = 0;
726   double sumDiff = 0.0;
727   /* Structures to store image parameters and data*/
728   opj_image_t *imageBase = NULL, *imageTest = NULL, *imageDiff = NULL;
729   opj_image_cmptparm_t* param_image_diff = NULL;
730   int decod_format;
731
732   /* Get parameters from command line*/
733   if( parse_cmdline_cmp(argc, argv, &inParam) )
734     {
735     compare_images_help_display();
736     goto cleanup;
737     }
738
739   /* Display Parameters*/
740   printf("******Parameters********* \n");
741   printf(" base_filename = %s\n"
742          " test_filename = %s\n"
743          " nb of Components = %d\n"
744          " Non regression test = %d\n"
745          " separator Base = %s\n"
746          " separator Test = %s\n",
747          inParam.base_filename, inParam.test_filename, inParam.nbcomp,
748          inParam.nr_flag, inParam.separator_base, inParam.separator_test);
749
750   if ( (inParam.tabMSEvalues != NULL) && (inParam.tabPEAKvalues != NULL))
751     {
752     int it_comp2;
753     printf(" MSE values = [");
754     for (it_comp2 = 0; it_comp2 < inParam.nbcomp; it_comp2++)
755       printf(" %f ", inParam.tabMSEvalues[it_comp2]);
756     printf("]\n");
757     printf(" PEAK values = [");
758     for (it_comp2 = 0; it_comp2 < inParam.nbcomp; it_comp2++)
759       printf(" %f ", inParam.tabPEAKvalues[it_comp2]);
760     printf("]\n");
761     printf(" Non-regression test = %d\n", inParam.nr_flag);
762     }
763
764   if (strlen(inParam.separator_base) != 0)
765     nbFilenamePGXbase = inParam.nbcomp;
766
767   if (strlen(inParam.separator_test) != 0)
768     nbFilenamePGXtest = inParam.nbcomp;
769
770   printf(" NbFilename to generate from base filename = %d\n", nbFilenamePGXbase);
771   printf(" NbFilename to generate from test filename = %d\n", nbFilenamePGXtest);
772   printf("************************* \n");
773
774   /*----------BASELINE IMAGE--------*/
775   memsizebasefilename = (int)strlen(inParam.test_filename) + 1 + 5 + 2 + 4;
776   memsizetestfilename = (int)strlen(inParam.test_filename) + 1 + 5 + 2 + 4;
777
778   decod_format = get_decod_format(&inParam);
779   if( decod_format == -1 )
780     {
781     fprintf( stderr, "Unhandled file format\n" );
782     goto cleanup;
783     }
784   assert( decod_format == PGX_DFMT || decod_format == TIF_DFMT || decod_format == PXM_DFMT );
785
786   if( decod_format == PGX_DFMT )
787     {
788     imageBase = readImageFromFilePGX( inParam.base_filename, nbFilenamePGXbase, inParam.separator_base);
789     if ( imageBase == NULL )
790       goto cleanup;
791     }
792   else if( decod_format == TIF_DFMT )
793     {
794     imageBase = readImageFromFileTIF( inParam.base_filename, nbFilenamePGXbase, "");
795     if ( imageBase == NULL )
796       goto cleanup;
797     }
798   else if( decod_format == PXM_DFMT )
799     {
800     imageBase = readImageFromFilePPM( inParam.base_filename, nbFilenamePGXbase, inParam.separator_base);
801     if ( imageBase == NULL )
802       goto cleanup;
803     }
804
805   filenamePNGbase = (char*) malloc((size_t)memsizebasefilename);
806   strcpy(filenamePNGbase, inParam.test_filename);
807   strcat(filenamePNGbase, ".base");
808   /*printf("filenamePNGbase = %s [%d / %d octets]\n",filenamePNGbase, strlen(filenamePNGbase),memsizebasefilename );*/
809
810   /*----------TEST IMAGE--------*/
811
812   if( decod_format == PGX_DFMT )
813     {
814     imageTest = readImageFromFilePGX(inParam.test_filename, nbFilenamePGXtest, inParam.separator_test);
815     if ( imageTest == NULL )
816       goto cleanup;
817     }
818   else if( decod_format == TIF_DFMT )
819     {
820     imageTest = readImageFromFileTIF(inParam.test_filename, nbFilenamePGXtest, "");
821     if ( imageTest == NULL )
822       goto cleanup;
823     }
824   else if( decod_format == PXM_DFMT )
825     {
826     imageTest = readImageFromFilePPM(inParam.test_filename, nbFilenamePGXtest, inParam.separator_test);
827     if ( imageTest == NULL )
828       goto cleanup;
829     }
830
831   filenamePNGtest = (char*) malloc((size_t)memsizetestfilename);
832   strcpy(filenamePNGtest, inParam.test_filename);
833   strcat(filenamePNGtest, ".test");
834   /*printf("filenamePNGtest = %s [%d / %d octets]\n",filenamePNGtest, strlen(filenamePNGtest),memsizetestfilename );*/
835
836   /*----------DIFF IMAGE--------*/
837
838   /* Allocate memory*/
839   param_image_diff = malloc( imageBase->numcomps * sizeof(opj_image_cmptparm_t));
840
841   /* Comparison of header parameters*/
842   printf("Step 1 -> Header comparison\n");
843
844   for (it_comp = 0; it_comp < imageBase->numcomps; it_comp++)
845     {
846     param_image_diff[it_comp].x0 = 0;
847     param_image_diff[it_comp].y0 = 0;
848     param_image_diff[it_comp].dx = 0;
849     param_image_diff[it_comp].dy = 0;
850     param_image_diff[it_comp].sgnd = 0;
851     param_image_diff[it_comp].prec = 8;
852     param_image_diff[it_comp].bpp = 1;
853     param_image_diff[it_comp].h = imageBase->comps[it_comp].h;
854     param_image_diff[it_comp].w = imageBase->comps[it_comp].w;
855
856     if (imageBase->comps[it_comp].sgnd != imageTest->comps[it_comp].sgnd)
857       {
858       printf("ERROR: sign mismatch [comp %d] (%d><%d)\n", it_comp, ((imageBase->comps)[it_comp]).sgnd, ((imageTest->comps)[it_comp]).sgnd);
859       goto cleanup;
860       }
861
862     if (((imageBase->comps)[it_comp]).prec != ((imageTest->comps)[it_comp]).prec)
863       {
864       printf("ERROR: prec mismatch [comp %d] (%d><%d)\n", it_comp, ((imageBase->comps)[it_comp]).prec, ((imageTest->comps)[it_comp]).prec);
865       goto cleanup;
866       }
867
868     if (((imageBase->comps)[it_comp]).bpp != ((imageTest->comps)[it_comp]).bpp)
869       {
870       printf("ERROR: byte per pixel mismatch [comp %d] (%d><%d)\n", it_comp, ((imageBase->comps)[it_comp]).bpp, ((imageTest->comps)[it_comp]).bpp);
871       goto cleanup;
872       }
873
874     if (((imageBase->comps)[it_comp]).h != ((imageTest->comps)[it_comp]).h)
875       {
876       printf("ERROR: height mismatch [comp %d] (%d><%d)\n", it_comp, ((imageBase->comps)[it_comp]).h, ((imageTest->comps)[it_comp]).h);
877       goto cleanup;
878       }
879
880     if (((imageBase->comps)[it_comp]).w != ((imageTest->comps)[it_comp]).w)
881       {
882       printf("ERROR: width mismatch [comp %d] (%d><%d)\n", it_comp, ((imageBase->comps)[it_comp]).w, ((imageTest->comps)[it_comp]).w);
883       goto cleanup;
884       }
885     }
886
887    imageDiff = opj_image_create(imageBase->numcomps, param_image_diff, OPJ_CLRSPC_UNSPECIFIED);
888    /* Free memory*/
889    free(param_image_diff); param_image_diff = NULL;
890
891    /* Measurement computation*/
892    printf("Step 2 -> measurement comparison\n");
893
894    memsizedifffilename = strlen(inParam.test_filename) + 1 + 5 + 2 + 4;
895    filenamePNGdiff = (char*) malloc(memsizedifffilename);
896    strcpy(filenamePNGdiff, inParam.test_filename);
897    strcat(filenamePNGdiff, ".diff");
898    /*printf("filenamePNGdiff = %s [%d / %d octets]\n",filenamePNGdiff, strlen(filenamePNGdiff),memsizedifffilename );*/
899
900    /* Compute pixel diff*/
901    for (it_comp = 0; it_comp < imageDiff->numcomps; it_comp++)
902      {
903      double SE=0,PEAK=0;
904      double MSE=0;
905      for (itpxl = 0; itpxl < ((imageDiff->comps)[it_comp]).w * ((imageDiff->comps)[it_comp]).h; itpxl++)
906        {
907        if (abs( ((imageBase->comps)[it_comp]).data[itpxl] - ((imageTest->comps)[it_comp]).data[itpxl] ) > 0)
908          {
909          valueDiff = ((imageBase->comps)[it_comp]).data[itpxl] - ((imageTest->comps)[it_comp]).data[itpxl];
910          ((imageDiff->comps)[it_comp]).data[itpxl] = abs(valueDiff);
911          sumDiff += valueDiff;
912          nbPixelDiff++;
913
914          SE += (double)valueDiff * valueDiff;
915          PEAK = (PEAK > abs(valueDiff)) ? PEAK : abs(valueDiff);
916          }
917        else
918          ((imageDiff->comps)[it_comp]).data[itpxl] = 0;
919        }/* h*w loop */
920
921      MSE = SE / ( ((imageDiff->comps)[it_comp]).w * ((imageDiff->comps)[it_comp]).h );
922
923      if (!inParam.nr_flag && (inParam.tabMSEvalues != NULL) && (inParam.tabPEAKvalues != NULL))
924        { /* Conformance test*/
925        printf("<DartMeasurement name=\"PEAK_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, PEAK);
926        printf("<DartMeasurement name=\"MSE_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, MSE);
927
928        if ( (MSE > inParam.tabMSEvalues[it_comp]) || (PEAK > inParam.tabPEAKvalues[it_comp]) )
929          {
930          printf("ERROR: MSE (%f) or PEAK (%f) values produced by the decoded file are greater "
931            "than the allowable error (respectively %f and %f) \n",
932            MSE, PEAK, inParam.tabMSEvalues[it_comp], inParam.tabPEAKvalues[it_comp]);
933          goto cleanup;
934          }
935        }
936      else  /* Non regression-test */
937        {
938        if ( nbPixelDiff > 0)
939          {
940          char it_compc[255];
941          it_compc[0] = 0;
942
943          printf("<DartMeasurement name=\"NumberOfPixelsWithDifferences_%d\" type=\"numeric/int\"> %d </DartMeasurement> \n", it_comp, nbPixelDiff);
944          printf("<DartMeasurement name=\"ComponentError_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, sumDiff);
945
946 #ifdef OPJ_HAVE_LIBPNG
947            {
948            char *filenamePNGbase_it_comp, *filenamePNGtest_it_comp, *filenamePNGdiff_it_comp;
949
950            filenamePNGbase_it_comp = (char*) malloc((size_t)memsizebasefilename);
951            strcpy(filenamePNGbase_it_comp,filenamePNGbase);
952
953            filenamePNGtest_it_comp = (char*) malloc((size_t)memsizetestfilename);
954            strcpy(filenamePNGtest_it_comp,filenamePNGtest);
955
956            filenamePNGdiff_it_comp = (char*) malloc(memsizedifffilename);
957            strcpy(filenamePNGdiff_it_comp,filenamePNGdiff);
958
959            sprintf(it_compc, "_%i", it_comp);
960            strcat(it_compc,".png");
961            strcat(filenamePNGbase_it_comp, it_compc);
962            /*printf("filenamePNGbase_it = %s [%d / %d octets]\n",filenamePNGbase_it_comp, strlen(filenamePNGbase_it_comp),memsizebasefilename );*/
963            strcat(filenamePNGtest_it_comp, it_compc);
964            /*printf("filenamePNGtest_it = %s [%d / %d octets]\n",filenamePNGtest_it_comp, strlen(filenamePNGtest_it_comp),memsizetestfilename );*/
965            strcat(filenamePNGdiff_it_comp, it_compc);
966            /*printf("filenamePNGdiff_it = %s [%d / %d octets]\n",filenamePNGdiff_it_comp, strlen(filenamePNGdiff_it_comp),memsizedifffilename );*/
967
968            /*
969            if ( imageToPNG(imageBase, filenamePNGbase_it_comp, it_comp) == EXIT_SUCCESS )
970            {
971            printf("<DartMeasurementFile name=\"BaselineImage_%d\" type=\"image/png\"> %s </DartMeasurementFile> \n", it_comp, filenamePNGbase_it_comp);
972            }
973
974            if ( imageToPNG(imageTest, filenamePNGtest_it_comp, it_comp) == EXIT_SUCCESS )
975            {
976            printf("<DartMeasurementFile name=\"TestImage_%d\" type=\"image/png\"> %s </DartMeasurementFile> \n", it_comp, filenamePNGtest_it_comp);
977            }
978
979            if ( imageToPNG(imageDiff, filenamePNGdiff_it_comp, it_comp) == EXIT_SUCCESS )
980            {
981            printf("<DartMeasurementFile name=\"DiffferenceImage_%d\" type=\"image/png\"> %s </DartMeasurementFile> \n", it_comp, filenamePNGdiff_it_comp);
982            }
983             */
984
985            free(filenamePNGbase_it_comp);
986            free(filenamePNGtest_it_comp);
987            free(filenamePNGdiff_it_comp);
988            }
989 #endif
990          goto cleanup;
991          }
992        }
993      } /* it_comp loop */
994
995    printf("---- TEST SUCCEED ----\n");
996    failed = 0;
997 cleanup:
998   /*-----------------------------*/
999   free(param_image_diff);
1000   /* Free memory */
1001   opj_image_destroy(imageBase);
1002   opj_image_destroy(imageTest);
1003   opj_image_destroy(imageDiff);
1004
1005   free(filenamePNGbase);
1006   free(filenamePNGtest);
1007   free(filenamePNGdiff);
1008
1009   free(inParam.tabMSEvalues);
1010   free(inParam.tabPEAKvalues);
1011   free(inParam.base_filename);
1012   free(inParam.test_filename);
1013
1014   return failed ? EXIT_FAILURE : EXIT_SUCCESS;
1015 }