compare_images.c 33 KB

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