imgcmp.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 578 行 · 第 1/2 页

C
578
字号
	for (compno = 0; compno < numcomps; ++compno) {
		width = jas_image_cmptwidth(origimage, compno);
		height = jas_image_cmptheight(origimage, compno);
		depth = jas_image_cmptprec(origimage, compno);
		if (jas_image_cmptwidth(reconimage, compno) != width ||
		 jas_image_cmptheight(reconimage, compno) != height) {
			jas_eprintf("image dimensions differ\n");
			return EXIT_FAILURE;
		}
		if (jas_image_cmptprec(reconimage, compno) != depth) {
			jas_eprintf("precisions differ\n");
			return EXIT_FAILURE;
		}

		if (!(origdata = jas_matrix_create(height, width))) {
			jas_eprintf("internal error\n");
			return EXIT_FAILURE;
		}
		if (!(recondata = jas_matrix_create(height, width))) {
			jas_eprintf("internal error\n");
			return EXIT_FAILURE;
		}
		if (jas_image_readcmpt(origimage, compno, 0, 0, width, height,
		  origdata)) {
			jas_eprintf("cannot read component data\n");
			return EXIT_FAILURE;
		}
		if (jas_image_readcmpt(reconimage, compno, 0, 0, width, height,
		  recondata)) {
			jas_eprintf("cannot read component data\n");
			return EXIT_FAILURE;
		}

		if (diffpath) {
			if (!(diffstream = jas_stream_fopen(diffpath, "rwb"))) {
				jas_eprintf("cannot open diff stream\n");
				return EXIT_FAILURE;
			}
			if (!(diffimage = makediffimage(origdata, recondata))) {
				jas_eprintf("cannot make diff image\n");
				return EXIT_FAILURE;
			}
			fmtid = jas_image_strtofmt("pnm");
			if (jas_image_encode(diffimage, diffstream, fmtid, 0)) {
				jas_eprintf("cannot save\n");
				return EXIT_FAILURE;
			}
			jas_stream_close(diffstream);
			jas_image_destroy(diffimage);
		}

		if (metric != metricid_none) {
			d = getdistortion(origdata, recondata, depth, metric);
			if (d > maxdist) {
				maxdist = d;
			}
			if (d < mindist) {
				mindist = d;
			}
			if (!maxonly && !minonly) {
				if (metric == metricid_pae || metric == metricid_equal) {
					printf("%ld\n", (long) ceil(d));
				} else {
					printf("%f\n", d);
				}
			}
		}
		jas_matrix_destroy(origdata);
		jas_matrix_destroy(recondata);
	}

	if (metric != metricid_none && (maxonly || minonly)) {
		if (maxonly) {
			d = maxdist;
		} else if (minonly) {
			d = mindist;
		} else {
			abort();
		}
		
		if (metric == metricid_pae || metric == metricid_equal) {
			jas_eprintf("%ld\n", (long) ceil(d));
		} else {
			jas_eprintf("%f\n", d);
		}
	}

	jas_image_destroy(origimage);
	jas_image_destroy(reconimage);
	jas_image_clearfmts();

	return EXIT_SUCCESS;
}

/******************************************************************************\
* Distortion metric computation functions.
\******************************************************************************/

double getdistortion(jas_matrix_t *orig, jas_matrix_t *recon, int depth, int metric)
{
	double d;

	switch (metric) {
	case metricid_psnr:
	default:
		d = psnr(orig, recon, depth);
		break;
	case metricid_mae:
		d = msen(orig, recon, 1);
		break;
	case metricid_mse:
		d = msen(orig, recon, 2);
		break;
	case metricid_rmse:
		d = sqrt(msen(orig, recon, 2));
		break;
	case metricid_pae:
		d = pae(orig, recon);
		break;
	case metricid_equal:
		d = (pae(orig, recon) == 0) ? 0 : 1;
		break;
	}
	return d;
}

/* Compute peak absolute error. */

double pae(jas_matrix_t *x, jas_matrix_t *y)
{
	double s;
	double d;
	int i;
	int j;

	s = 0.0;
	for (i = 0; i < jas_matrix_numrows(x); i++) {
		for (j = 0; j < jas_matrix_numcols(x); j++) {
			d = abs(jas_matrix_get(y, i, j) - jas_matrix_get(x, i, j));
			if (d > s) {
				s = d;
			}
		}
	}

	return s;
}

/* Compute either mean-squared error or mean-absolute error. */

double msen(jas_matrix_t *x, jas_matrix_t *y, int n)
{
	double s;
	double d;
	int i;
	int j;

	s = 0.0;
	for (i = 0; i < jas_matrix_numrows(x); i++) {
		for (j = 0; j < jas_matrix_numcols(x); j++) {
			d = jas_matrix_get(y, i, j) - jas_matrix_get(x, i, j);
			if (n == 1) {
				s += fabs(d);
			} else if (n == 2) {
				s += d * d;
			} else {
				abort();
			}
		}
	}

	return s / ((double) jas_matrix_numrows(x) * jas_matrix_numcols(x));
}

/* Compute peak signal-to-noise ratio. */

double psnr(jas_matrix_t *x, jas_matrix_t *y, int depth)
{
	double m;
	double p;
	m = msen(x, y, 2);
	p = ((1 << depth) - 1);
	return 20.0 * log10(p / sqrt(m));
}

/******************************************************************************\
*
\******************************************************************************/

jas_image_t *makediffimage(jas_matrix_t *origdata, jas_matrix_t *recondata)
{
	jas_image_t *diffimage;
	jas_matrix_t *diffdata[3];
	int width;
	int height;
	int i;
	int j;
	int k;
	jas_image_cmptparm_t compparms[3];
	jas_seqent_t a;
	jas_seqent_t b;

	width = jas_matrix_numcols(origdata);
	height = jas_matrix_numrows(origdata);

	for (i = 0; i < 3; ++i) {
		compparms[i].tlx = 0;
		compparms[i].tly = 0;
		compparms[i].hstep = 1;
		compparms[i].vstep = 1;
		compparms[i].width = width;
		compparms[i].height = height;
		compparms[i].prec = 8;
		compparms[i].sgnd = jas_false;
	}
	if (!(diffimage = jas_image_create(3, compparms, JAS_CLRSPC_SRGB))) {
		abort();
	}

	for (i = 0; i < 3; ++i) {
		if (!(diffdata[i] = jas_matrix_create(height, width))) {
			jas_eprintf("internal error\n");
			return 0;
		}
	}

	for (j = 0; j < height; ++j) {
		for (k = 0; k < width; ++k) {
			a = jas_matrix_get(origdata, j, k);
			b = jas_matrix_get(recondata, j, k);
			if (a > b) {
				jas_matrix_set(diffdata[0], j, k, 255);
				jas_matrix_set(diffdata[1], j, k, 0);
				jas_matrix_set(diffdata[2], j, k, 0);
			} else if (a < b) {
				jas_matrix_set(diffdata[0], j, k, 0);
				jas_matrix_set(diffdata[1], j, k, 255);
				jas_matrix_set(diffdata[2], j, k, 0);
			} else {
				jas_matrix_set(diffdata[0], j, k, a);
				jas_matrix_set(diffdata[1], j, k, a);
				jas_matrix_set(diffdata[2], j, k, a);
			}
		}
	}

	for (i = 0; i < 3; ++i) {
		if (jas_image_writecmpt(diffimage, i, 0, 0, width, height, diffdata[i])) {
			return 0;
		}
	}

	return diffimage;
}

/******************************************************************************\
*
\******************************************************************************/

void cmdinfo()
{
	jas_eprintf("Image Comparison Utility (Version %s).\n",
	  JAS_VERSION);
	jas_eprintf(
	  "Copyright (c) 2001 Michael David Adams.\n"
	  "All rights reserved.\n"
	  );
}

void usage()
{
	cmdinfo();
	jas_eprintf("usage:\n");
	jas_eprintf("%s ", cmdname);
	jas_eprintf(
	  "-f reference_image_file -F other_image_file [-m metric]\n"
	  );
	jas_eprintf(
	  "The metric argument may assume one of the following values:\n"
	  "    psnr .... peak signal to noise ratio\n"
	  "    mse ..... mean squared error\n"
	  "    rmse .... root mean squared error\n"
	  "    pae ..... peak absolute error\n"
	  "    mae ..... mean absolute error\n"
	  "    equal ... equality (boolean)\n"
	  );
	exit(EXIT_FAILURE);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?