Blame tests/gdtest/gdtest.c

Packit Service df60bb
#include <config.h>
Packit Service df60bb
#include <assert.h>
Packit Service df60bb
#include <setjmp.h>
Packit Service df60bb
#include <stdlib.h>
Packit Service df60bb
#include <stdio.h>
Packit Service df60bb
#include <string.h>
Packit Service df60bb
#include <math.h>
Packit Service df60bb
#include <limits.h>
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_DIRENT_H
Packit Service df60bb
#include <dirent.h>
Packit Service df60bb
#endif
Packit Service df60bb
#ifdef HAVE_UNISTD_H
Packit Service df60bb
#include <unistd.h>
Packit Service df60bb
#endif
Packit Service df60bb
#ifdef HAVE_SYS_STAT_H
Packit Service df60bb
#include <sys/stat.h>
Packit Service df60bb
#endif
Packit Service df60bb
#ifdef HAVE_SYS_TYPES_H
Packit Service df60bb
#include <sys/types.h>
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
# include "readdir.h"
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#include "gd.h"
Packit Service df60bb
Packit Service df60bb
#include "gdtest.h"
Packit Service df60bb
Packit Service df60bb
/* max is already defined in windows/msvc */
Packit Service df60bb
#ifndef max
Packit Service df60bb
	static inline int max(int a, int b) {return a > b ? a : b;}
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
void gdSilence(int priority, const char *format, va_list args)
Packit Service df60bb
{
Packit Service df60bb
	(void)priority;
Packit Service df60bb
	(void)format;
Packit Service df60bb
	(void)args;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_LIBPNG
Packit Service df60bb
gdImagePtr gdTestImageFromPng(const char *filename)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr image;
Packit Service df60bb
	FILE *fp;
Packit Service df60bb
Packit Service df60bb
	/* If the path is relative, then assume it's in the tests/ dir. */
Packit Service df60bb
	if (filename[0] == '/' || filename[0] == '.'
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
	|| filename[1] == ':'
Packit Service df60bb
#endif
Packit Service df60bb
	) {
Packit Service df60bb
		fp = fopen(filename, "rb");
Packit Service df60bb
	} else {
Packit Service df60bb
		fp = gdTestFileOpen(filename);
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if (fp == NULL) {
Packit Service df60bb
			return NULL;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	image = gdImageCreateFromPng(fp);
Packit Service df60bb
	fclose(fp);
Packit Service df60bb
	return image;
Packit Service df60bb
}
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
static char *tmpdir_base;
Packit Service df60bb
Packit Service df60bb
/* This is kind of hacky, but it's meant to be simple. */
Packit Service df60bb
static void _clean_dir(const char *dir)
Packit Service df60bb
{
Packit Service df60bb
	DIR *d;
Packit Service df60bb
	struct dirent *de;
Packit Service df60bb
Packit Service df60bb
	d = opendir(dir);
Packit Service df60bb
	if (d == NULL)
Packit Service df60bb
		return;
Packit Service df60bb
Packit Service df60bb
	if (chdir(dir) != 0)
Packit Service df60bb
		goto done;
Packit Service df60bb
Packit Service df60bb
	while ((de = readdir(d)) != NULL) {
Packit Service df60bb
		struct stat st;
Packit Service df60bb
Packit Service df60bb
		if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
Packit Service df60bb
			continue;
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
	{
Packit Service df60bb
		WIN32_FILE_ATTRIBUTE_DATA data;
Packit Service df60bb
Packit Service df60bb
		if (!GetFileAttributesEx(de->d_name, GetFileExInfoStandard, &data)) {
Packit Service df60bb
			continue;
Packit Service df60bb
		}
Packit Service df60bb
		if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
Packit Service df60bb
			_clean_dir(de->d_name);
Packit Service df60bb
		} else {
Packit Service df60bb
			unlink(de->d_name);
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
#else
Packit Service df60bb
		if (lstat(de->d_name, &st) != 0)
Packit Service df60bb
			continue;
Packit Service df60bb
Packit Service df60bb
		if (S_ISDIR(st.st_mode))
Packit Service df60bb
			_clean_dir(de->d_name);
Packit Service df60bb
		else
Packit Service df60bb
			unlink(de->d_name);
Packit Service df60bb
#endif
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if (chdir("..")) {
Packit Service df60bb
		/* Ignore. */;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
 done:
Packit Service df60bb
	closedir(d);
Packit Service df60bb
	rmdir(dir);
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static void tmpdir_cleanup(void)
Packit Service df60bb
{
Packit Service df60bb
	_clean_dir(tmpdir_base);
Packit Service df60bb
	free(tmpdir_base);
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
char* strrstr (char* haystack, char* needle)
Packit Service df60bb
{
Packit Service df60bb
  int needle_length = strlen(needle);
Packit Service df60bb
  char * haystack_end = haystack + strlen(haystack) - needle_length;
Packit Service df60bb
  char * p;
Packit Service df60bb
  int i;
Packit Service df60bb
Packit Service df60bb
  for(p = haystack_end; p >= haystack; --p)
Packit Service df60bb
  {
Packit Service df60bb
    for(i = 0; i < needle_length; ++i) {
Packit Service df60bb
      if(p[i] != needle[i])
Packit Service df60bb
        goto next;
Packit Service df60bb
    }
Packit Service df60bb
    return p;
Packit Service df60bb
Packit Service df60bb
    next:;
Packit Service df60bb
  }
Packit Service df60bb
  return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
Packit Service df60bb
typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime);
Packit Service df60bb
Packit Service df60bb
static MyGetSystemTimeAsFileTime get_time_func(void)
Packit Service df60bb
{
Packit Service df60bb
	MyGetSystemTimeAsFileTime timefunc = NULL;
Packit Service df60bb
	HMODULE hMod = GetModuleHandle("kernel32.dll");
Packit Service df60bb
Packit Service df60bb
	if (hMod) {
Packit Service df60bb
		/* Max possible resolution <1us, win8/server2012 */
Packit Service df60bb
		timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimePreciseAsFileTime");
Packit Service df60bb
Packit Service df60bb
		if(!timefunc) {
Packit Service df60bb
			/* 100ns blocks since 01-Jan-1641 */
Packit Service df60bb
			timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimeAsFileTime");
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return timefunc;
Packit Service df60bb
}
Packit Service df60bb
static MyGetSystemTimeAsFileTime timefunc = NULL;
Packit Service df60bb
static int getfilesystemtime(struct timeval *tv)
Packit Service df60bb
{
Packit Service df60bb
	FILETIME ft;
Packit Service df60bb
	unsigned __int64 ff = 0;
Packit Service df60bb
	ULARGE_INTEGER fft;
Packit Service df60bb
Packit Service df60bb
	if (timefunc == NULL) {
Packit Service df60bb
		timefunc = get_time_func();
Packit Service df60bb
	}
Packit Service df60bb
	timefunc(&ft;;
Packit Service df60bb
Packit Service df60bb
    /*
Packit Service df60bb
	 * Do not cast a pointer to a FILETIME structure to either a
Packit Service df60bb
	 * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.
Packit Service df60bb
	 * via  http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx
Packit Service df60bb
	 */
Packit Service df60bb
	fft.HighPart = ft.dwHighDateTime;
Packit Service df60bb
	fft.LowPart = ft.dwLowDateTime;
Packit Service df60bb
	ff = fft.QuadPart;
Packit Service df60bb
Packit Service df60bb
	ff /= 10Ui64; /* convert to microseconds */
Packit Service df60bb
	ff -= 11644473600000000Ui64; /* convert to unix epoch */
Packit Service df60bb
Packit Service df60bb
	tv->tv_sec = (long)(ff / 1000000Ui64);
Packit Service df60bb
	tv->tv_usec = (long)(ff % 1000000Ui64);
Packit Service df60bb
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static char *
Packit Service df60bb
mkdtemp (char *tmpl)
Packit Service df60bb
{
Packit Service df60bb
	static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Packit Service df60bb
	static const int NLETTERS = sizeof (letters) - 1;
Packit Service df60bb
	static int counter = 0;
Packit Service df60bb
	char *XXXXXX;
Packit Service df60bb
	struct timeval tv;
Packit Service df60bb
	_int64 value;
Packit Service df60bb
	int count;
Packit Service df60bb
Packit Service df60bb
	/* find the last occurrence of "XXXXXX" */
Packit Service df60bb
	XXXXXX = strrstr(tmpl, "XXXXXX");
Packit Service df60bb
Packit Service df60bb
	if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6)) {
Packit Service df60bb
		errno = EINVAL;
Packit Service df60bb
		return NULL;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* Get some more or less random data.  */
Packit Service df60bb
	getfilesystemtime(&tv;;
Packit Service df60bb
	value = (tv.tv_usec ^ tv.tv_sec) + counter++;
Packit Service df60bb
Packit Service df60bb
	for (count = 0; count < 100; value += 7777, ++count) {
Packit Service df60bb
		_int64 v = value;
Packit Service df60bb
Packit Service df60bb
		/* Fill in the random bits.  */
Packit Service df60bb
		XXXXXX[0] = letters[v % NLETTERS];
Packit Service df60bb
		v /= NLETTERS;
Packit Service df60bb
		XXXXXX[1] = letters[v % NLETTERS];
Packit Service df60bb
		v /= NLETTERS;
Packit Service df60bb
		XXXXXX[2] = letters[v % NLETTERS];
Packit Service df60bb
		v /= NLETTERS;
Packit Service df60bb
		XXXXXX[3] = letters[v % NLETTERS];
Packit Service df60bb
		v /= NLETTERS;
Packit Service df60bb
		XXXXXX[4] = letters[v % NLETTERS];
Packit Service df60bb
		v /= NLETTERS;
Packit Service df60bb
		XXXXXX[5] = letters[v % NLETTERS];
Packit Service df60bb
Packit Service df60bb
		/* tmpl is in UTF-8 on Windows, thus use g_mkdir() */
Packit Service df60bb
		if (mkdir(tmpl) == 0) {
Packit Service df60bb
			return tmpl;
Packit Service df60bb
		}
Packit Service df60bb
		printf("failed to create directory\n");
Packit Service df60bb
		if (errno != EEXIST)
Packit Service df60bb
			/* Any other error will apply also to other names we might
Packit Service df60bb
			 *  try, and there are 2^32 or so of them, so give up now.
Packit Service df60bb
			 */
Packit Service df60bb
			return NULL;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* We got out of the loop because we ran out of combinations to try.  */
Packit Service df60bb
	errno = EEXIST;
Packit Service df60bb
	return NULL;
Packit Service df60bb
}
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
const char *gdTestTempDir(void)
Packit Service df60bb
{
Packit Service df60bb
	if (tmpdir_base == NULL) {
Packit Service df60bb
		char *tmpdir;
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
		char tmpdir_root[MAX_PATH];
Packit Service df60bb
		size_t tmpdir_root_len = GetTempPath(MAX_PATH, tmpdir_root);
Packit Service df60bb
		gdTestAssert(!(tmpdir_root_len > MAX_PATH || (tmpdir_root_len == 0)));
Packit Service df60bb
		gdTestAssert((tmpdir_root_len + 30 < MAX_PATH));
Packit Service df60bb
#else
Packit Service df60bb
		char *tmpdir_root;
Packit Service df60bb
		tmpdir_root = getenv("TMPDIR");
Packit Service df60bb
		if (tmpdir_root == NULL)
Packit Service df60bb
			tmpdir_root = "/tmp";
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
		/* The constant here is a lazy over-estimate. */
Packit Service df60bb
		tmpdir = malloc(strlen(tmpdir_root) + 30);
Packit Service df60bb
		gdTestAssert(tmpdir != NULL);
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
		sprintf(tmpdir, "%sgdtest.XXXXXX", tmpdir_root);
Packit Service df60bb
#else
Packit Service df60bb
		sprintf(tmpdir, "%s/gdtest.XXXXXX", tmpdir_root);
Packit Service df60bb
#endif
Packit Service df60bb
		tmpdir_base = mkdtemp(tmpdir);
Packit Service df60bb
		gdTestAssert(tmpdir_base != NULL);
Packit Service df60bb
Packit Service df60bb
		atexit(tmpdir_cleanup);
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return tmpdir_base;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
char *gdTestTempFile(const char *template)
Packit Service df60bb
{
Packit Service df60bb
	const char *tempdir = gdTestTempDir();
Packit Service df60bb
	char *ret;
Packit Service df60bb
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
	{
Packit Service df60bb
		char *tmpfilename;
Packit Service df60bb
		UINT error;
Packit Service df60bb
Packit Service df60bb
		ret = malloc(MAX_PATH);
Packit Service df60bb
		gdTestAssert(ret != NULL);
Packit Service df60bb
		if (template == NULL) {
Packit Service df60bb
			error = GetTempFileName(tempdir,
Packit Service df60bb
										  "gdtest",
Packit Service df60bb
										  0,
Packit Service df60bb
										  ret);
Packit Service df60bb
				gdTestAssert(error != 0);
Packit Service df60bb
		} else {
Packit Service df60bb
			sprintf(ret, "%s\\%s", tempdir, template);		
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
#else
Packit Service df60bb
	if (template == NULL) {
Packit Service df60bb
		template = "gdtemp.XXXXXX";
Packit Service df60bb
	}
Packit Service df60bb
	ret = malloc(strlen(tempdir) + 10 + strlen(template));
Packit Service df60bb
	gdTestAssert(ret != NULL);
Packit Service df60bb
	sprintf(ret, "%s/%s", tempdir, template);
Packit Service df60bb
Packit Service df60bb
	if (strstr(template, "XXXXXX") != NULL) {
Packit Service df60bb
		int fd = mkstemp(ret);
Packit Service df60bb
		gdTestAssert(fd != -1);
Packit Service df60bb
		close(fd);
Packit Service df60bb
	}
Packit Service df60bb
#endif
Packit Service df60bb
	return ret;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
FILE *gdTestTempFp(void)
Packit Service df60bb
{
Packit Service df60bb
	char *file = gdTestTempFile(NULL);
Packit Service df60bb
	FILE *fp = fopen(file, "wb");
Packit Service df60bb
	gdTestAssert(fp != NULL);
Packit Service df60bb
	free(file);
Packit Service df60bb
	return fp;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
char *gdTestFilePathV(const char *path, va_list args)
Packit Service df60bb
{
Packit Service df60bb
	size_t len;
Packit Service df60bb
	const char *p;
Packit Service df60bb
	char *file;
Packit Service df60bb
	va_list args_len;
Packit Service df60bb
Packit Service df60bb
	/* Figure out how much space we need. */
Packit Service df60bb
	va_copy(args_len, args);
Packit Service df60bb
	len = strlen(GDTEST_TOP_DIR) + 1;
Packit Service df60bb
	p = path;
Packit Service df60bb
	do {
Packit Service df60bb
		len += strlen(p) + 1;
Packit Service df60bb
	} while ((p = va_arg(args_len, const char *)) != NULL);
Packit Service df60bb
	va_end(args_len);
Packit Service df60bb
Packit Service df60bb
	/* Now build the path. */
Packit Service df60bb
	file = malloc(len);
Packit Service df60bb
	gdTestAssert(file != NULL);
Packit Service df60bb
	strcpy(file, GDTEST_TOP_DIR);
Packit Service df60bb
	p = path;
Packit Service df60bb
	do {
Packit Service df60bb
#ifdef _WIN32
Packit Service df60bb
		strcat(file, "\\");
Packit Service df60bb
#else
Packit Service df60bb
		strcat(file, "/");
Packit Service df60bb
#endif
Packit Service df60bb
		strcat(file, p);
Packit Service df60bb
	} while ((p = va_arg(args, const char *)) != NULL);
Packit Service df60bb
	va_end(args);
Packit Service df60bb
Packit Service df60bb
	return file;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
char *gdTestFilePathX(const char *path, ...)
Packit Service df60bb
{
Packit Service df60bb
	va_list args;
Packit Service df60bb
	va_start(args, path);
Packit Service df60bb
	return gdTestFilePathV(path, args);
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
FILE *gdTestFileOpenX(const char *path, ...)
Packit Service df60bb
{
Packit Service df60bb
	va_list args;
Packit Service df60bb
	FILE *fp;
Packit Service df60bb
	char *file;
Packit Service df60bb
Packit Service df60bb
	va_start(args, path);
Packit Service df60bb
	file = gdTestFilePathV(path, args);
Packit Service df60bb
	fp = fopen(file, "rb");
Packit Service df60bb
	gdTestAssert(fp != NULL);
Packit Service df60bb
	free(file);
Packit Service df60bb
	return fp;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/* Compare two buffers, returning the number of pixels that are
Packit Service df60bb
 * different and the maximum difference of any single color channel in
Packit Service df60bb
 * result_ret.
Packit Service df60bb
 *
Packit Service df60bb
 * This function should be rewritten to compare all formats supported by
Packit Service df60bb
 * cairo_format_t instead of taking a mask as a parameter.
Packit Service df60bb
 */
Packit Service df60bb
void gdTestImageDiff(gdImagePtr buf_a, gdImagePtr buf_b,
Packit Service df60bb
                     gdImagePtr buf_diff, CuTestImageResult *result_ret)
Packit Service df60bb
{
Packit Service df60bb
	int x, y;
Packit Service df60bb
	int c1, c2;
Packit Service df60bb
#   define UP_DIFF(var) result_ret->max_diff = max((var), result_ret->max_diff)
Packit Service df60bb
Packit Service df60bb
	for (y = 0; y < gdImageSY(buf_a); y++) {
Packit Service df60bb
		for (x = 0; x < gdImageSX(buf_a); x++) {
Packit Service df60bb
			c1 = gdImageGetTrueColorPixel(buf_a, x, y);
Packit Service df60bb
			c2 = gdImageGetTrueColorPixel(buf_b, x, y);
Packit Service df60bb
Packit Service df60bb
			/* check if the pixels are the same */
Packit Service df60bb
			if (c1 != c2) {
Packit Service df60bb
				int r1,b1,g1,a1,r2,b2,g2,a2;
Packit Service df60bb
				unsigned int diff_a,diff_r,diff_g,diff_b;
Packit Service df60bb
Packit Service df60bb
				a1 = gdTrueColorGetAlpha(c1);
Packit Service df60bb
				a2 = gdTrueColorGetAlpha(c2);
Packit Service df60bb
				diff_a = abs (a1 - a2);
Packit Service df60bb
				diff_a *= 4;  /* emphasize */
Packit Service df60bb
Packit Service df60bb
				if (diff_a) {
Packit Service df60bb
					diff_a += 128; /* make sure it's visible */
Packit Service df60bb
				}
Packit Service df60bb
				if (diff_a > gdAlphaMax) {
Packit Service df60bb
					diff_a = gdAlphaMax/2;
Packit Service df60bb
				}
Packit Service df60bb
Packit Service df60bb
				r1 = gdTrueColorGetRed(c1);
Packit Service df60bb
				r2 = gdTrueColorGetRed(c2);
Packit Service df60bb
				diff_r = abs (r1 - r2);
Packit Service df60bb
				// diff_r *= 4;  /* emphasize */
Packit Service df60bb
				if (diff_r) {
Packit Service df60bb
					diff_r += gdRedMax/2; /* make sure it's visible */
Packit Service df60bb
				}
Packit Service df60bb
				if (diff_r > 255) {
Packit Service df60bb
					diff_r = 255;
Packit Service df60bb
				}
Packit Service df60bb
				UP_DIFF(diff_r);
Packit Service df60bb
Packit Service df60bb
				g1 = gdTrueColorGetGreen(c1);
Packit Service df60bb
				g2 = gdTrueColorGetGreen(c2);
Packit Service df60bb
				diff_g = abs (g1 - g2);
Packit Service df60bb
Packit Service df60bb
				diff_g *= 4;  /* emphasize */
Packit Service df60bb
				if (diff_g) {
Packit Service df60bb
					diff_g += gdGreenMax/2; /* make sure it's visible */
Packit Service df60bb
				}
Packit Service df60bb
				if (diff_g > 255) {
Packit Service df60bb
					diff_g = 255;
Packit Service df60bb
				}
Packit Service df60bb
				UP_DIFF(diff_g);
Packit Service df60bb
Packit Service df60bb
				b1 = gdTrueColorGetBlue(c1);
Packit Service df60bb
				b2 = gdTrueColorGetBlue(c2);
Packit Service df60bb
				diff_b = abs (b1 - b2);
Packit Service df60bb
				diff_b *= 4;  /* emphasize */
Packit Service df60bb
				if (diff_b) {
Packit Service df60bb
					diff_b += gdBlueMax/2; /* make sure it's visible */
Packit Service df60bb
				}
Packit Service df60bb
				if (diff_b > 255) {
Packit Service df60bb
					diff_b = 255;
Packit Service df60bb
				}
Packit Service df60bb
				UP_DIFF(diff_b);
Packit Service df60bb
Packit Service df60bb
				result_ret->pixels_changed++;
Packit Service df60bb
				if (buf_diff) gdImageSetPixel(buf_diff, x,y, gdTrueColorAlpha(diff_r, diff_g, diff_b, diff_a));
Packit Service df60bb
			} else {
Packit Service df60bb
				if (buf_diff) gdImageSetPixel(buf_diff, x,y, gdTrueColorAlpha(255,255,255,0));
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
#   undef UP_DIFF
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
Packit Service df60bb
/* Return the largest difference between two corresponding pixels and
Packit Service df60bb
 * channels. */
Packit Service df60bb
unsigned int gdMaxPixelDiff(gdImagePtr a, gdImagePtr b)
Packit Service df60bb
{
Packit Service df60bb
    int diff = 0;
Packit Service df60bb
    int x, y;
Packit Service df60bb
Packit Service df60bb
    if (a == NULL || b == NULL || a->sx != b->sx || a->sy != b->sy)
Packit Service df60bb
        return UINT_MAX;
Packit Service df60bb
Packit Service df60bb
    for (x = 0; x < a->sx; x++) {
Packit Service df60bb
        for (y = 0; y < a->sy; y++) {
Packit Service df60bb
            int c1, c2;
Packit Service df60bb
Packit Service df60bb
			c1 = gdImageGetTrueColorPixel(a, x, y);
Packit Service df60bb
			c2 = gdImageGetTrueColorPixel(b, x, y);
Packit Service df60bb
            if (c1 == c2) continue;
Packit Service df60bb
Packit Service df60bb
            diff = max(diff, abs(gdTrueColorGetAlpha(c1) - gdTrueColorGetAlpha(c2)));
Packit Service df60bb
            diff = max(diff, abs(gdTrueColorGetRed(c1)   - gdTrueColorGetRed(c2)));
Packit Service df60bb
            diff = max(diff, abs(gdTrueColorGetGreen(c1) - gdTrueColorGetGreen(c2)));
Packit Service df60bb
            diff = max(diff, abs(gdTrueColorGetBlue(c1)  - gdTrueColorGetBlue(c2)));
Packit Service df60bb
        }/* for */
Packit Service df60bb
    }/* for */
Packit Service df60bb
Packit Service df60bb
    return diff;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_LIBPNG
Packit Service df60bb
int gdTestImageCompareToImage(const char* file, unsigned int line, const char* message,
Packit Service df60bb
                              gdImagePtr expected, gdImagePtr actual)
Packit Service df60bb
{
Packit Service df60bb
	unsigned int width_a, height_a;
Packit Service df60bb
	unsigned int width_b, height_b;
Packit Service df60bb
	gdImagePtr surface_diff = NULL;
Packit Service df60bb
	CuTestImageResult result = {0, 0};
Packit Service df60bb
Packit Service df60bb
	(void)message;
Packit Service df60bb
Packit Service df60bb
	if (!actual) {
Packit Service df60bb
		_gdTestErrorMsg(file, line, "Image is NULL\n");
Packit Service df60bb
		goto fail;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	width_a  = gdImageSX(expected);
Packit Service df60bb
	height_a = gdImageSY(expected);
Packit Service df60bb
	width_b  = gdImageSX(actual);
Packit Service df60bb
	height_b = gdImageSY(actual);
Packit Service df60bb
Packit Service df60bb
	if (width_a  != width_b  || height_a != height_b) {
Packit Service df60bb
		_gdTestErrorMsg(file, line,
Packit Service df60bb
				"Image size mismatch: (%ux%u) vs. (%ux%u)\n       for %s vs. buffer\n",
Packit Service df60bb
				width_a, height_a,
Packit Service df60bb
				width_b, height_b,
Packit Service df60bb
				file);
Packit Service df60bb
		goto fail;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	surface_diff = gdImageCreateTrueColor(width_a, height_a);
Packit Service df60bb
Packit Service df60bb
	gdTestImageDiff(expected, actual, surface_diff, &result);
Packit Service df60bb
	if (result.pixels_changed>0) {
Packit Service df60bb
		char file_diff[255];
Packit Service df60bb
		char file_out[1024];
Packit Service df60bb
		FILE *fp;
Packit Service df60bb
		int len, p;
Packit Service df60bb
Packit Service df60bb
		_gdTestErrorMsg(file, line,
Packit Service df60bb
				"Total pixels changed: %d with a maximum channel difference of %d.\n",
Packit Service df60bb
				result.pixels_changed,
Packit Service df60bb
				result.max_diff
Packit Service df60bb
			);
Packit Service df60bb
Packit Service df60bb
		p = len = strlen(file);
Packit Service df60bb
		p--;
Packit Service df60bb
Packit Service df60bb
		/* Use only the filename (and store it in the bld dir not the src dir
Packit Service df60bb
		 */
Packit Service df60bb
		while(p > 0 && (file[p] != '/' && file[p] != '\\')) {
Packit Service df60bb
			p--;
Packit Service df60bb
		}
Packit Service df60bb
		sprintf(file_diff, "%s_%u_diff.png", file + p  + 1, line);
Packit Service df60bb
		sprintf(file_out, "%s_%u_out.png", file + p  + 1, line);
Packit Service df60bb
Packit Service df60bb
		fp = fopen(file_diff, "wb");
Packit Service df60bb
		if (!fp) goto fail;
Packit Service df60bb
		gdImagePng(surface_diff,fp);
Packit Service df60bb
		fclose(fp);
Packit Service df60bb
Packit Service df60bb
		fp = fopen(file_out, "wb");
Packit Service df60bb
		if (!fp) goto fail;
Packit Service df60bb
		gdImagePng(actual, fp);
Packit Service df60bb
		fclose(fp);
Packit Service df60bb
		return 0;
Packit Service df60bb
	} else {
Packit Service df60bb
		if (surface_diff) {
Packit Service df60bb
			gdImageDestroy(surface_diff);
Packit Service df60bb
		}
Packit Service df60bb
		return 1;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
fail:
Packit Service df60bb
	if (surface_diff) {
Packit Service df60bb
		gdImageDestroy(surface_diff);
Packit Service df60bb
	}
Packit Service df60bb
	return 1;
Packit Service df60bb
}
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_LIBPNG
Packit Service df60bb
int gdTestImageCompareToFile(const char* file, unsigned int line, const char* message,
Packit Service df60bb
                             const char *expected_file, gdImagePtr actual)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr expected = 0;
Packit Service df60bb
	int res = 1;
Packit Service df60bb
Packit Service df60bb
	expected = gdTestImageFromPng(expected_file);
Packit Service df60bb
Packit Service df60bb
	if (!expected) {
Packit Service df60bb
		_gdTestErrorMsg(file, line, "Cannot open PNG <%s>\n", expected_file);
Packit Service df60bb
		res = 0;
Packit Service df60bb
	} else {
Packit Service df60bb
		res = gdTestImageCompareToImage(file, line, message, expected, actual);
Packit Service df60bb
		gdImageDestroy(expected);
Packit Service df60bb
	}
Packit Service df60bb
	return res;
Packit Service df60bb
}
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
static int failureCount = 0;
Packit Service df60bb
Packit Service df60bb
int gdNumFailures() {
Packit Service df60bb
    return failureCount;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
int _gdTestAssert(const char* file, unsigned int line, int condition)
Packit Service df60bb
{
Packit Service df60bb
	if (condition) return 1;
Packit Service df60bb
	_gdTestErrorMsg(file, line, "Assert failed in <%s:%i>\n", file, line);
Packit Service df60bb
Packit Service df60bb
    ++failureCount;
Packit Service df60bb
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
int _gdTestAssertMsg(const char* file, unsigned int line, int condition, const char* message, ...)
Packit Service df60bb
{
Packit Service df60bb
	va_list args;
Packit Service df60bb
	
Packit Service df60bb
	if (condition) return 1;
Packit Service df60bb
  
Packit Service df60bb
	fprintf(stderr, "%s:%u: ", file, line);
Packit Service df60bb
	va_start(args, message);
Packit Service df60bb
	vfprintf(stderr, message, args);
Packit Service df60bb
	va_end(args);
Packit Service df60bb
Packit Service df60bb
	fflush(stderr);
Packit Service df60bb
Packit Service df60bb
	++failureCount;
Packit Service df60bb
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
int _gdTestErrorMsg(const char* file, unsigned int line, const char* format, ...) /* {{{ */
Packit Service df60bb
{
Packit Service df60bb
	va_list args;
Packit Service df60bb
Packit Service df60bb
	fprintf(stderr, "%s:%u: ", file, line);
Packit Service df60bb
	va_start(args, format);
Packit Service df60bb
	vfprintf(stderr, format, args);
Packit Service df60bb
	va_end(args);
Packit Service df60bb
	fflush(stderr);
Packit Service df60bb
Packit Service df60bb
    ++failureCount;
Packit Service df60bb
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
/* }}} */