[cairo-commit] 5 commits - configure.in COPYING test/pdiff

Carl Worth cworth at kemper.freedesktop.org
Wed Nov 29 23:03:29 PST 2006


 COPYING                       |   21 ++
 configure.in                  |    1 
 test/pdiff/CMakeLists.txt     |   55 ++++++
 test/pdiff/CompareArgs.cpp    |  136 ++++++++++++++++
 test/pdiff/CompareArgs.h      |   44 +++++
 test/pdiff/LPyramid.cpp       |   87 ++++++++++
 test/pdiff/LPyramid.h         |   38 ++++
 test/pdiff/Makefile.am        |   14 +
 test/pdiff/Metric.cpp         |  316 +++++++++++++++++++++++++++++++++++++++
 test/pdiff/Metric.h           |   26 +++
 test/pdiff/PerceptualDiff.cpp |   45 +++++
 test/pdiff/README.txt         |   45 +++++
 test/pdiff/RGBAImage.cpp      |  144 +++++++++++++++++
 test/pdiff/RGBAImage.h        |   57 +++++++
 test/pdiff/gpl.txt            |  340 ++++++++++++++++++++++++++++++++++++++++++
 15 files changed, 1366 insertions(+), 3 deletions(-)

New commits:
diff-tree 170d35b034150b69717e52dd85f0f93c392d9f3c (from c863315285911d38b64b8429e279c5e55d0089b8)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Nov 29 23:01:30 2006 -0800

    pdiff: Add missing newlins at end of files.

diff --git a/test/pdiff/CompareArgs.h b/test/pdiff/CompareArgs.h
index 29265c3..a4a1ddd 100644
--- a/test/pdiff/CompareArgs.h
+++ b/test/pdiff/CompareArgs.h
@@ -41,4 +41,4 @@ public:
 	std::string		ErrorStr;			// Error string
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/test/pdiff/LPyramid.cpp b/test/pdiff/LPyramid.cpp
index 6871c15..0e8d68a 100644
--- a/test/pdiff/LPyramid.cpp
+++ b/test/pdiff/LPyramid.cpp
@@ -85,4 +85,3 @@ float LPyramid::Get_Value(int x, int y, 
 	if (l > MAX_PYR_LEVELS) l = MAX_PYR_LEVELS;
 	return Levels[level][index];
 }
-
diff --git a/test/pdiff/LPyramid.h b/test/pdiff/LPyramid.h
index 5f98a42..b53f3ef 100644
--- a/test/pdiff/LPyramid.h
+++ b/test/pdiff/LPyramid.h
@@ -35,4 +35,4 @@ protected:
 	int Height;
 };
 
-#endif // _LPYRAMID_H
\ No newline at end of file
+#endif // _LPYRAMID_H
diff --git a/test/pdiff/Metric.cpp b/test/pdiff/Metric.cpp
index bcfb8ae..58d67c7 100644
--- a/test/pdiff/Metric.cpp
+++ b/test/pdiff/Metric.cpp
@@ -313,4 +313,4 @@ bool Yee_Compare(CompareArgs &args)
 		}
 	}
 	return false;
-}
\ No newline at end of file
+}
diff --git a/test/pdiff/Metric.h b/test/pdiff/Metric.h
index 86540de..a6b234e 100644
--- a/test/pdiff/Metric.h
+++ b/test/pdiff/Metric.h
@@ -23,4 +23,4 @@ class CompareArgs;
 // References: A Perceptual Metric for Production Testing, Hector Yee, Journal of Graphics Tools 2004
 bool Yee_Compare(CompareArgs &args);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/test/pdiff/RGBAImage.h b/test/pdiff/RGBAImage.h
index 473a59f..65802f9 100644
--- a/test/pdiff/RGBAImage.h
+++ b/test/pdiff/RGBAImage.h
@@ -54,4 +54,4 @@ protected:
 	unsigned int *Data;
 };
 
-#endif
\ No newline at end of file
+#endif
diff-tree c863315285911d38b64b8429e279c5e55d0089b8 (from 6e06b68452ec68b7ab227c54284f28a605512ce4)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 21 14:19:35 2006 -0800

    Hook up Makefiles for perceptualdiff.

diff --git a/configure.in b/configure.in
index ea1de98..9847f16 100644
--- a/configure.in
+++ b/configure.in
@@ -828,6 +828,7 @@ pixman/Makefile
 pixman/src/Makefile
 src/Makefile
 test/Makefile
+test/pdiff/Makefile
 perf/Makefile
 doc/Makefile
 doc/public/Makefile
diff --git a/test/pdiff/Makefile.am b/test/pdiff/Makefile.am
new file mode 100644
index 0000000..36bebd0
--- /dev/null
+++ b/test/pdiff/Makefile.am
@@ -0,0 +1,14 @@
+EXTRA_PROGRAMS = perceptualdiff
+
+perceptualdiff_SOURCES =	\
+	CompareArgs.cpp		\
+	CompareArgs.h		\
+	LPyramid.cpp		\
+	LPyramid.h		\
+	Metric.cpp		\
+	Metric.h		\
+	PerceptualDiff.cpp	\
+	RGBAImage.cpp		\
+	RGBAImage.h
+
+LDADD = $(top_builddir)/src/libcairo.la
diff-tree 6e06b68452ec68b7ab227c54284f28a605512ce4 (from 2b92556abe440e9834174aed7395e2827f62897c)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 21 14:19:55 2006 -0800

    Remove all libtiff-related code by #ifdef

diff --git a/test/pdiff/CompareArgs.cpp b/test/pdiff/CompareArgs.cpp
index 25925f8..aa69a7d 100644
--- a/test/pdiff/CompareArgs.cpp
+++ b/test/pdiff/CompareArgs.cpp
@@ -67,8 +67,10 @@ bool CompareArgs::Parse_Args(int argc, c
 	}
 	for (int i = 0; i < argc; i++) {
 		if (i == 1) {
+#if HAVE_LIBTIFF
 			ImgA = RGBAImage::ReadTiff(argv[1]);
 			if (!ImgA) {
+#endif /* HAVE_LIBTIFF */
 				ImgA = RGBAImage::ReadPNG(argv[1]);
 				if (!ImgA)
 				{
@@ -77,10 +79,14 @@ bool CompareArgs::Parse_Args(int argc, c
 					ErrorStr += "\n";
 					return false;
 				}
+#if HAVE_LIBTIFF
 			}
+#endif /* HAVE_LIBTIFF */
 		} else if (i == 2) {			
+#if HAVE_LIBTIFF
 			ImgB = RGBAImage::ReadTiff(argv[2]);
 			if (!ImgB) {
+#endif /* HAVE_LIBTIFF */
 				ImgB = RGBAImage::ReadPNG(argv[2]);
 				if (!ImgB)
 				{
@@ -89,7 +95,9 @@ bool CompareArgs::Parse_Args(int argc, c
 					ErrorStr += "\n";
 					return false;
 				}
+#if HAVE_LIBTIFF
 			}
+#endif /* HAVE_LIBTIFF */
 		} else {
 			if (strstr(argv[i], "-fov")) {
 				if (i + 1 < argc) {
diff --git a/test/pdiff/RGBAImage.cpp b/test/pdiff/RGBAImage.cpp
index 1c38ab4..a39195f 100644
--- a/test/pdiff/RGBAImage.cpp
+++ b/test/pdiff/RGBAImage.cpp
@@ -16,6 +16,8 @@ if not, write to the Free Software Found
 
 #include "RGBAImage.h"
 #include "png.h"
+
+#if HAVE_LIBTIFF
 #include "tiff.h"
 #include "tiffio.h"
 
@@ -53,6 +55,7 @@ RGBAImage* RGBAImage::ReadTiff(char *fil
 	}
 	return fimg;
 }
+#endif /* HAVE_LIBTIFF */
 
 // This portion was written by Scott Corley
 RGBAImage* RGBAImage::ReadPNG(char *filename)
diff-tree 2b92556abe440e9834174aed7395e2827f62897c (from 812fd53499d308ff881751e57c1e3287498ddd0f)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Nov 29 22:55:00 2006 -0800

    Use uint32_t instead of the non-standard uint32

diff --git a/test/pdiff/RGBAImage.cpp b/test/pdiff/RGBAImage.cpp
index 267b460..1c38ab4 100644
--- a/test/pdiff/RGBAImage.cpp
+++ b/test/pdiff/RGBAImage.cpp
@@ -105,11 +105,11 @@ RGBAImage* RGBAImage::ReadPNG(char *file
 	fimg = new RGBAImage(png_ptr->width, png_ptr->height);
 	for (int y = 0; y < (int) png_ptr->height; y++) {
 		for (int x = 0; x < (int) png_ptr->width; x++) {
-			uint32 value = 0;
+			uint32_t value = 0;
 			if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-				value = ((uint32)row_pointers[y][x*4]) | (((uint32)row_pointers[y][x*4+1])<<8) | (((uint32)row_pointers[y][x*4+2])<<16) |(((uint32)row_pointers[y][x*4+3])<<24);
+				value = ((uint32_t)row_pointers[y][x*4]) | (((uint32_t)row_pointers[y][x*4+1])<<8) | (((uint32_t)row_pointers[y][x*4+2])<<16) |(((uint32_t)row_pointers[y][x*4+3])<<24);
 			else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
-				value = ((uint32)row_pointers[y][x*3] /*B*/) | (((uint32)row_pointers[y][x*3+1] /*G*/)<<8) | (((uint32)row_pointers[y][x*3+2]/*R*/)<<16) | (0xFFUL << 24);
+				value = ((uint32_t)row_pointers[y][x*3] /*B*/) | (((uint32_t)row_pointers[y][x*3+1] /*G*/)<<8) | (((uint32_t)row_pointers[y][x*3+2]/*R*/)<<16) | (0xFFUL << 24);
 		   fimg->Set(x,y, value);
 		}
 	}
diff-tree 812fd53499d308ff881751e57c1e3287498ddd0f (from d9fd942e4774aa29967f908001b62dbc987d2f66)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 21 12:15:16 2006 -0800

    Add perceptualdiff program totest/pdiff.
    
    The perceptualdiff program was written by Hector Yee with contributions
    from Scott Corley and Mick Weiss. It is hosted at http://pdiff.sourceforge.net
    The source code added here was obtained by:
    
    	svn co https://svn.sourceforge.net/svnroot/pdiff/trunk pdiff
    
    which gave revision 22 of the source code.
    
    The perceptualdiff program is available under the terms of the GNU GPL,
    so I've added a note to COPYING about this program, (and the fact that
    it is auxiliary only, and does not affect the license of the implementation
    of cairo itself).

diff --git a/COPYING b/COPYING
index 145e629..7019cd6 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
 Cairo is free software.
 
-Every source file in the implementation of cairo is available to be
+Every source file in the implementation[*] of cairo is available to be
 redistributed and/or modified under the terms of either the GNU Lesser
 General Public License (LGPL) version 2.1 or the Mozilla Public
 License (MPL) version 1.1.  Some files are available under more
@@ -13,5 +13,20 @@ conditions of either license:
 	COPYING-LGPL-2.1
 	COPYING-MPL-1.1
 
-Please see each file in the implementation for Copyright and licensing
-information.
+Please see each file in the implementation for copyright and licensing
+information, (in the opening comment of each file).
+
+[*] The implementation of cairo is contained entirely within the "src"
+and "pixman" directories of the cairo source distribution. There are
+other components of the cairo source distribution (such as the "test"
+and "perf") that are auxiliary to the library itself. None of the
+source code in these directories contributes to a build of the cairo
+library itself, (libcairo.so or cairo.dll or similar).
+
+These auxilary components are also free software, but may be under
+different license terms than cairo itself. For example, most of the
+test cases in the perf and test directories are made available under
+an MIT license to simplify any use of this code for reference purposes
+in using cairo itself. Other files might be available under the GNU
+General Public License (GPL), for example. Again, please see the
+opening comment of each file for copyright and licensing information.
diff --git a/test/pdiff/CMakeLists.txt b/test/pdiff/CMakeLists.txt
new file mode 100644
index 0000000..6e4fa7a
--- /dev/null
+++ b/test/pdiff/CMakeLists.txt
@@ -0,0 +1,55 @@
+PROJECT (PerceptualDiff)
+SET(DIFF_SRC PerceptualDiff.cpp LPyramid.cpp RGBAImage.cpp
+CompareArgs.cpp Metric.cpp)
+
+ADD_EXECUTABLE (perceptualdiff ${DIFF_SRC})
+
+# look for libtiff
+FIND_PATH(TIFF_INCLUDE_DIR tiff.h
+  /usr/local/include
+  /usr/include
+  /opt/local/include
+)
+
+FIND_LIBRARY(TIFF_LIBRARY tiff
+  /usr/lib
+  /usr/local/lib
+  /opt/local/lib
+)
+
+IF(TIFF_INCLUDE_DIR)
+  IF(TIFF_LIBRARY)
+    SET( TIFF_FOUND "YES" )
+    SET( TIFF_LIBRARIES ${TIFF_LIBRARY} )
+  ENDIF(TIFF_LIBRARY)
+ENDIF(TIFF_INCLUDE_DIR)
+
+IF(TIFF_FOUND)
+  INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+  TARGET_LINK_LIBRARIES(perceptualdiff ${TIFF_LIBRARY})
+ENDIF(TIFF_FOUND)
+
+# look for libpng
+FIND_PATH(PNG_INCLUDE_DIR png.h
+  /usr/local/include
+  /usr/include
+  /opt/local/include
+)
+
+FIND_LIBRARY(PNG_LIBRARY png
+  /usr/lib
+  /usr/local/lib
+  /opt/local/lib
+)
+
+IF(PNG_INCLUDE_DIR)
+  IF(PNG_LIBRARY)
+    SET( PNG_FOUND "YES" )
+    SET( PNG_LIBRARIES ${PNG_LIBRARY} )
+  ENDIF(PNG_LIBRARY)
+ENDIF(PNG_INCLUDE_DIR)
+
+IF(PNG_FOUND)
+  INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR})
+  TARGET_LINK_LIBRARIES(perceptualdiff ${PNG_LIBRARY})
+ENDIF(PNG_FOUND)
\ No newline at end of file
diff --git a/test/pdiff/CompareArgs.cpp b/test/pdiff/CompareArgs.cpp
new file mode 100644
index 0000000..25925f8
--- /dev/null
+++ b/test/pdiff/CompareArgs.cpp
@@ -0,0 +1,128 @@
+/*
+Comapre Args
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "CompareArgs.h"
+#include "RGBAImage.h"
+#include <stdio.h>
+
+static const char* copyright = 
+"PerceptualDiff version 1.0, Copyright (C) 2006 Yangli Hector Yee\n\
+PerceptualDiff comes with ABSOLUTELY NO WARRANTY;\n\
+This is free software, and you are welcome\n\
+to redistribute it under certain conditions;\n\
+See the GPL page for details: http://www.gnu.org/copyleft/gpl.html\n\n";
+
+static const char *usage =
+"PeceptualDiff image1.tif image2.tif\n\n\
+   Compares image1.tif and image2.tif using a perceptually based image metric\n\
+   Options:\n\
+\t-verbose       : Turns on verbose mode\n\
+\t-fov deg       : Field of view in degrees (0.1 to 89.9)\n\
+\t-threshold p	 : #pixels p below which differences are ignored\n\
+\t-gamma g       : Value to convert rgb into linear space (default 2.2)\n\
+\t-luminance l   : White luminance (default 100.0 cdm^-2)\n\
+\t-output o.ppm  : Write difference to the file o.ppm\n\
+\n\
+\n Note: Input files can also be in the PNG format\
+\n";
+
+CompareArgs::CompareArgs()
+{
+	ImgA = NULL;
+	ImgB = NULL;
+	ImgDiff = NULL;
+	Verbose = false;
+	FieldOfView = 45.0f;
+	Gamma = 2.2f;
+	ThresholdPixels = 100;
+	Luminance = 100.0f;
+}
+
+CompareArgs::~CompareArgs()
+{
+	if (ImgA) delete ImgA;
+	if (ImgB) delete ImgB;
+	if (ImgDiff) delete ImgDiff;
+}
+
+bool CompareArgs::Parse_Args(int argc, char **argv)
+{
+	if (argc < 3) {
+		ErrorStr = copyright;
+		ErrorStr += usage;
+		return false;
+	}
+	for (int i = 0; i < argc; i++) {
+		if (i == 1) {
+			ImgA = RGBAImage::ReadTiff(argv[1]);
+			if (!ImgA) {
+				ImgA = RGBAImage::ReadPNG(argv[1]);
+				if (!ImgA)
+				{
+					ErrorStr = "FAIL: Cannot open ";
+					ErrorStr += argv[1];
+					ErrorStr += "\n";
+					return false;
+				}
+			}
+		} else if (i == 2) {			
+			ImgB = RGBAImage::ReadTiff(argv[2]);
+			if (!ImgB) {
+				ImgB = RGBAImage::ReadPNG(argv[2]);
+				if (!ImgB)
+				{
+					ErrorStr = "FAIL: Cannot open ";
+					ErrorStr += argv[2];
+					ErrorStr += "\n";
+					return false;
+				}
+			}
+		} else {
+			if (strstr(argv[i], "-fov")) {
+				if (i + 1 < argc) {
+					FieldOfView = (float) atof(argv[i + 1]);
+				}
+			} else if (strstr(argv[i], "-verbose")) {
+				Verbose = true;
+			} else 	if (strstr(argv[i], "-threshold")) {
+				if (i + 1 < argc) {
+					ThresholdPixels = atoi(argv[i + 1]);
+				}
+			} else 	if (strstr(argv[i], "-gamma")) {
+				if (i + 1 < argc) {
+					Gamma = (float) atof(argv[i + 1]);
+				}
+			}else 	if (strstr(argv[i], "-luminance")) {
+				if (i + 1 < argc) {
+					Luminance = (float) atof(argv[i + 1]);
+				}
+			}else 	if (strstr(argv[i], "-output")) {
+				if (i + 1 < argc) {
+					ImgDiff = new RGBAImage(ImgA->Get_Width(), ImgA->Get_Height(), argv[i+1]);
+				}
+			}
+		}
+	} // i
+	return true;
+}
+
+void CompareArgs::Print_Args()
+{
+	printf("Field of view is %f degrees\n", FieldOfView);
+	printf("Threshold pixels is %d pixels\n", ThresholdPixels);
+	printf("The Gamma is %f\n", Gamma);
+	printf("The Display's luminance is %f candela per meter squared\n", Luminance);
+}
diff --git a/test/pdiff/CompareArgs.h b/test/pdiff/CompareArgs.h
new file mode 100644
index 0000000..29265c3
--- /dev/null
+++ b/test/pdiff/CompareArgs.h
@@ -0,0 +1,44 @@
+/*
+Comapre Args
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _COMPAREARGS_H
+#define _COMPAREARGS_H
+
+#include <string>
+
+class RGBAImage;
+
+// Args to pass into the comparison function
+class CompareArgs
+{
+public:
+	CompareArgs();
+	~CompareArgs();
+	bool Parse_Args(int argc, char **argv);	
+	void Print_Args();
+	
+	RGBAImage		*ImgA;				// Image A
+	RGBAImage		*ImgB;				// Image B
+	RGBAImage		*ImgDiff;			// Diff image
+	bool			Verbose;			// Print lots of text or not
+	float			FieldOfView;		// Field of view in degrees
+	float			Gamma;				// The gamma to convert to linear color space
+	float			Luminance;			// the display's luminance
+	unsigned int	ThresholdPixels;	// How many pixels different to ignore
+	std::string		ErrorStr;			// Error string
+};
+
+#endif
\ No newline at end of file
diff --git a/test/pdiff/LPyramid.cpp b/test/pdiff/LPyramid.cpp
new file mode 100644
index 0000000..6871c15
--- /dev/null
+++ b/test/pdiff/LPyramid.cpp
@@ -0,0 +1,88 @@
+/*
+Laplacian Pyramid
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "LPyramid.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+LPyramid::LPyramid(float *image, int width, int height) :
+	Width(width),
+	Height(height)
+{
+	// Make the Laplacian pyramid by successively
+	// copying the earlier levels and blurring them
+	for (int i=0; i<MAX_PYR_LEVELS; i++) {
+		if (i == 0) {
+			Levels[i] = Copy(image);
+		} else {
+			Levels[i] = new float[Width * Height];
+			Convolve(Levels[i], Levels[i - 1]);
+		}
+	}
+}
+
+LPyramid::~LPyramid()
+{
+	for (int i=0; i<MAX_PYR_LEVELS; i++) {
+		if (Levels[i]) delete Levels[i];
+	}
+}
+
+float *LPyramid::Copy(float *img)
+{
+	int max = Width * Height;
+	float *out = new float[max];
+	for (int i = 0; i < max; i++) out[i] = img[i];
+	
+	return out;
+}
+
+void LPyramid::Convolve(float *a, float *b)
+// convolves image b with the filter kernel and stores it in a
+{
+	int y,x,i,j,nx,ny;
+	const float Kernel[] = {0.05f, 0.25f, 0.4f, 0.25f, 0.05f};
+
+	for (y=0; y<Height; y++) {
+		for (x=0; x<Width; x++) {
+			int index = y * Width + x;
+			a[index] = 0.0f;
+			for (i=-2; i<=2; i++) {
+				for (j=-2; j<=2; j++) {
+					nx=x+i;
+					ny=y+j;
+					if (nx<0) nx=-nx;
+					if (ny<0) ny=-ny;
+					if (nx>=Width) nx=2*(Width-1)-nx;
+					if (ny>=Height) ny=2*(Height-1)-ny;
+					a[index] += Kernel[i+2] * Kernel[j+2] * b[ny * Width + nx];
+				} 
+			}
+		}
+	}
+}
+
+float LPyramid::Get_Value(int x, int y, int level)
+{
+	int index = x + y * Width;
+	int l = level;
+	if (l > MAX_PYR_LEVELS) l = MAX_PYR_LEVELS;
+	return Levels[level][index];
+}
+
diff --git a/test/pdiff/LPyramid.h b/test/pdiff/LPyramid.h
new file mode 100644
index 0000000..5f98a42
--- /dev/null
+++ b/test/pdiff/LPyramid.h
@@ -0,0 +1,38 @@
+/*
+Laplacian Pyramid
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#ifndef _LPYRAMID_H
+#define _LPYRAMID_H
+
+#define MAX_PYR_LEVELS 8
+
+class LPyramid
+{
+public:	
+	LPyramid(float *image, int width, int height);
+	virtual ~LPyramid();
+	float Get_Value(int x, int y, int level);
+protected:
+	float *Copy(float *img);
+	void Convolve(float *a, float *b);
+	
+	// Succesively blurred versions of the original image
+	float *Levels[MAX_PYR_LEVELS];
+
+	int Width;
+	int Height;
+};
+
+#endif // _LPYRAMID_H
\ No newline at end of file
diff --git a/test/pdiff/Metric.cpp b/test/pdiff/Metric.cpp
new file mode 100644
index 0000000..bcfb8ae
--- /dev/null
+++ b/test/pdiff/Metric.cpp
@@ -0,0 +1,316 @@
+/*
+Metric
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "Metric.h"
+#include "CompareArgs.h"
+#include "RGBAImage.h"
+#include "LPyramid.h"
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265f
+#endif
+
+/*
+* Given the adaptation luminance, this function returns the
+* threshold of visibility in cd per m^2
+* TVI means Threshold vs Intensity function
+* This version comes from Ward Larson Siggraph 1997
+*/ 
+
+float tvi(float adaptation_luminance)
+{
+      // returns the threshold luminance given the adaptation luminance
+      // units are candelas per meter squared
+
+      float log_a, r, result; 
+      log_a = log10f(adaptation_luminance);
+
+      if (log_a < -3.94f) {
+            r = -2.86f;
+      } else if (log_a < -1.44f) {
+            r = powf(0.405f * log_a + 1.6f , 2.18f) - 2.86f;
+      } else if (log_a < -0.0184f) {
+            r = log_a - 0.395f;
+      } else if (log_a < 1.9f) {
+            r = powf(0.249f * log_a + 0.65f, 2.7f) - 0.72f;
+      } else {
+            r = log_a - 1.255f;
+      }
+
+      result = powf(10.0f , r); 
+
+      return result;
+
+} 
+
+// computes the contrast sensitivity function (Barten SPIE 1989)
+// given the cycles per degree (cpd) and luminance (lum)
+float csf(float cpd, float lum)
+{
+	float a, b, result; 
+	
+	a = 440.0f * powf((1.0f + 0.7f / lum), -0.2f);
+	b = 0.3f * powf((1.0f + 100.0f / lum), 0.15f);
+		
+	result = a * cpd * expf(-b * cpd) * sqrtf(1.0f + 0.06f * expf(b * cpd)); 
+	
+	return result;	
+}
+
+/*
+* Visual Masking Function
+* from Daly 1993
+*/
+float mask(float contrast)
+{
+      float a, b, result;
+      a = powf(392.498f * contrast,  0.7f);
+      b = powf(0.0153f * a, 4.0f);
+      result = powf(1.0f + b, 0.25f); 
+
+      return result;
+} 
+
+// convert Adobe RGB (1998) with reference white D65 to XYZ
+void AdobeRGBToXYZ(float r, float g, float b, float &x, float &y, float &z)
+{
+	// matrix is from http://www.brucelindbloom.com/
+	x = r * 0.576700f + g * 0.185556f + b * 0.188212f;
+	y = r * 0.297361f + g * 0.627355f + b * 0.0752847f;
+	z = r * 0.0270328f + g * 0.0706879f + b * 0.991248f;
+}
+
+void XYZToLAB(float x, float y, float z, float &L, float &A, float &B)
+{
+	static float xw = -1;
+	static float yw;
+	static float zw;
+	// reference white
+	if (xw < 0) {
+		AdobeRGBToXYZ(1, 1, 1, xw, yw, zw);
+	}
+	const float epsilon  = 216.0f / 24389.0f;
+	const float kappa = 24389.0f / 27.0f;
+	float f[3];
+	float r[3];
+	r[0] = x / xw;
+	r[1] = y / yw;
+	r[2] = z / zw;
+	for (int i = 0; i < 3; i++) {
+		if (r[i] > epsilon) {
+			f[i] = powf(r[i], 1.0f / 3.0f);
+		} else {
+			f[i] = (kappa * r[i] + 16.0f) / 116.0f;
+		}
+	}
+	L = 116.0f * f[1] - 16.0f;
+	A = 500.0f * (f[0] - f[1]);
+	B = 200.0f * (f[1] - f[2]);
+}
+
+bool Yee_Compare(CompareArgs &args)
+{
+	if ((args.ImgA->Get_Width() != args.ImgB->Get_Width()) ||
+		(args.ImgA->Get_Height() != args.ImgB->Get_Height())) {
+		args.ErrorStr = "Image dimensions do not match\n";
+		return false;
+	}
+	
+	unsigned int i, dim;
+	dim = args.ImgA->Get_Width() * args.ImgA->Get_Height();
+	bool identical = true;
+	for (i = 0; i < dim; i++) {
+		if (args.ImgA->Get(i) != args.ImgB->Get(i)) {
+		  identical = false;
+		  break;
+		}
+	}
+	if (identical) {
+		args.ErrorStr = "Images are binary identical\n";
+		return true;
+	}
+	
+	// assuming colorspaces are in Adobe RGB (1998) convert to XYZ
+	float *aX = new float[dim];
+	float *aY = new float[dim];
+	float *aZ = new float[dim];
+	float *bX = new float[dim];
+	float *bY = new float[dim];
+	float *bZ = new float[dim];
+	float *aLum = new float[dim];
+	float *bLum = new float[dim];
+	
+	float *aA = new float[dim];
+	float *bA = new float[dim];
+	float *aB = new float[dim];
+	float *bB = new float[dim];
+
+	if (args.Verbose) printf("Converting RGB to XYZ\n");
+	
+	unsigned int x, y, w, h;
+	w = args.ImgA->Get_Width();
+	h = args.ImgA->Get_Height();
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			float r, g, b, l;
+			i = x + y * w;
+			r = powf(args.ImgA->Get_Red(i) / 255.0f, args.Gamma);
+			g = powf(args.ImgA->Get_Green(i) / 255.0f, args.Gamma);
+			b = powf(args.ImgA->Get_Blue(i) / 255.0f, args.Gamma);						
+			AdobeRGBToXYZ(r,g,b,aX[i],aY[i],aZ[i]);			
+			XYZToLAB(aX[i], aY[i], aZ[i], l, aA[i], aB[i]);
+			r = powf(args.ImgB->Get_Red(i) / 255.0f, args.Gamma);
+			g = powf(args.ImgB->Get_Green(i) / 255.0f, args.Gamma);
+			b = powf(args.ImgB->Get_Blue(i) / 255.0f, args.Gamma);						
+			AdobeRGBToXYZ(r,g,b,bX[i],bY[i],bZ[i]);
+			XYZToLAB(bX[i], bY[i], bZ[i], l, bA[i], bB[i]);
+			aLum[i] = aY[i] * args.Luminance;
+			bLum[i] = bY[i] * args.Luminance;
+		}
+	}
+	
+	if (args.Verbose) printf("Constructing Laplacian Pyramids\n");
+	
+	LPyramid *la = new LPyramid(aLum, w, h);
+	LPyramid *lb = new LPyramid(bLum, w, h);
+	
+	float num_one_degree_pixels = (float) (2 * tan( args.FieldOfView * 0.5 * M_PI / 180) * 180 / M_PI);
+	float pixels_per_degree = w / num_one_degree_pixels;
+	
+	if (args.Verbose) printf("Performing test\n");
+	
+	float num_pixels = 1;
+	unsigned int adaptation_level = 0;
+	for (i = 0; i < MAX_PYR_LEVELS; i++) {
+		adaptation_level = i;
+		if (num_pixels > num_one_degree_pixels) break;
+		num_pixels *= 2;
+	}
+	
+	float cpd[MAX_PYR_LEVELS];
+	cpd[0] = 0.5f * pixels_per_degree;
+	for (i = 1; i < MAX_PYR_LEVELS; i++) cpd[i] = 0.5f * cpd[i - 1];
+	float csf_max = csf(3.248f, 100.0f);
+	
+	float F_freq[MAX_PYR_LEVELS - 2];
+	for (i = 0; i < MAX_PYR_LEVELS - 2; i++) F_freq[i] = csf_max / csf( cpd[i], 100.0f);
+	
+	unsigned int pixels_failed = 0;
+	for (y = 0; y < h; y++) {
+	  for (x = 0; x < w; x++) {
+		int index = x + y * w;
+		float contrast[MAX_PYR_LEVELS - 2];
+		float sum_contrast = 0;
+		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
+			float n1 = fabsf(la->Get_Value(x,y,i) - la->Get_Value(x,y,i + 1));
+			float n2 = fabsf(lb->Get_Value(x,y,i) - lb->Get_Value(x,y,i + 1));
+			float numerator = (n1 > n2) ? n1 : n2;
+			float d1 = fabsf(la->Get_Value(x,y,i+2));
+			float d2 = fabsf(lb->Get_Value(x,y,i+2));
+			float denominator = (d1 > d2) ? d1 : d2;
+			if (denominator < 1e-5f) denominator = 1e-5f;
+			contrast[i] = numerator / denominator;
+			sum_contrast += contrast[i];
+		}
+		if (sum_contrast < 1e-5) sum_contrast = 1e-5f;
+		float F_mask[MAX_PYR_LEVELS - 2];
+		float adapt = la->Get_Value(x,y,adaptation_level) + lb->Get_Value(x,y,adaptation_level);
+		adapt *= 0.5f;
+		if (adapt < 1e-5) adapt = 1e-5f;
+		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
+			F_mask[i] = mask(contrast[i] * csf(cpd[i], adapt)); 
+		}
+		float factor = 0;
+		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
+			factor += contrast[i] * F_freq[i] * F_mask[i] / sum_contrast;
+		}
+		if (factor < 1) factor = 1;
+		if (factor > 10) factor = 10;
+		float delta = fabsf(la->Get_Value(x,y,0) - lb->Get_Value(x,y,0));
+		bool pass = true;
+		// pure luminance test
+		if (delta > factor * tvi(adapt)) {
+			pass = false;
+		} else {
+			// CIE delta E test with modifications
+			float color_scale = 1.0f;
+			// ramp down the color test in scotopic regions
+			if (adapt < 10.0f) {
+				color_scale = 1.0f - (10.0f - color_scale) / 10.0f;
+				color_scale = color_scale * color_scale;
+			}
+			float da = aA[index] - bA[index];
+			float db = aB[index] - bB[index];
+			da = da * da;
+			db = db * db;
+			float delta_e = (da + db) * color_scale;
+			if (delta_e > factor) {
+				pass = false;
+			}
+		}
+		if (!pass) {
+			pixels_failed++;
+			if (args.ImgDiff) {
+				args.ImgDiff->Set(255, 0, 0, 255, index);
+			}
+		} else {
+			if (args.ImgDiff) {
+				args.ImgDiff->Set(0, 0, 0, 255, index);
+			}
+		}
+	  }
+	}
+	
+	if (aX) delete[] aX;
+	if (aY) delete[] aY;
+	if (aZ) delete[] aZ;
+	if (bX) delete[] bX;
+	if (bY) delete[] bY;
+	if (bZ) delete[] bZ;
+	if (aLum) delete[] aLum;
+	if (bLum) delete[] bLum;
+	if (la) delete la;
+	if (lb) delete lb;
+	if (aA) delete aA;
+	if (bA) delete bA;
+	if (aB) delete aB;
+	if (bB) delete bB;
+	
+	if (pixels_failed < args.ThresholdPixels) {
+		args.ErrorStr = "Images are perceptually indistinguishable\n";
+		return true;
+	}
+	
+	char different[100];
+	sprintf(different, "%d pixels are different\n", pixels_failed);
+
+	args.ErrorStr = "Images are visibly different\n";
+	args.ErrorStr += different;
+	
+	if (args.ImgDiff) {
+		if (args.ImgDiff->WritePPM()) {
+			args.ErrorStr += "Wrote difference image to ";
+			args.ErrorStr+= args.ImgDiff->Get_Name();
+			args.ErrorStr += "\n";
+		} else {
+			args.ErrorStr += "Could not write difference image to ";
+			args.ErrorStr+= args.ImgDiff->Get_Name();
+			args.ErrorStr += "\n";
+		}
+	}
+	return false;
+}
\ No newline at end of file
diff --git a/test/pdiff/Metric.h b/test/pdiff/Metric.h
new file mode 100644
index 0000000..86540de
--- /dev/null
+++ b/test/pdiff/Metric.h
@@ -0,0 +1,26 @@
+/*
+Metric
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _METRIC_H
+#define _METRIC_H
+
+class CompareArgs;
+
+// Image comparison metric using Yee's method
+// References: A Perceptual Metric for Production Testing, Hector Yee, Journal of Graphics Tools 2004
+bool Yee_Compare(CompareArgs &args);
+
+#endif
\ No newline at end of file
diff --git a/test/pdiff/PerceptualDiff.cpp b/test/pdiff/PerceptualDiff.cpp
new file mode 100644
index 0000000..ee79666
--- /dev/null
+++ b/test/pdiff/PerceptualDiff.cpp
@@ -0,0 +1,45 @@
+/*
+PerceptualDiff - a program that compares two images using a perceptual metric
+based on the paper :
+A perceptual metric for production testing. Journal of graphics tools, 9(4):33-40, 2004, Hector Yee
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <string>
+#include "LPyramid.h"
+#include "RGBAImage.h"
+#include "CompareArgs.h"
+#include "Metric.h"
+
+int main(int argc, char **argv)
+{
+	CompareArgs args;
+	
+	if (!args.Parse_Args(argc, argv)) {
+		printf("%s", args.ErrorStr.c_str());
+		return -1;
+	} else {
+		if (args.Verbose) args.Print_Args();
+	}
+	int result = Yee_Compare(args) == true;
+	if (result) {
+		printf("PASS: %s\n", args.ErrorStr.c_str());
+	} else {
+		printf("FAIL: %s\n", args.ErrorStr.c_str());
+	}
+	return result;
+}
diff --git a/test/pdiff/README.txt b/test/pdiff/README.txt
new file mode 100644
index 0000000..a873f3c
--- /dev/null
+++ b/test/pdiff/README.txt
@@ -0,0 +1,45 @@
+pdiff - a program that compares two images using
+a perceptually based image metric.
+Copyright (C) 2006 Yangli Hector Yee
+yeehector at users.sourceforge.net
+http://pdiff.sourceforge.net/
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details in the file gpl.txt.
+
+Build Instructions
+1. Download cross platform make from http://www.cmake.org
+2. Download libtiff from http://www.libtiff.org. Download libpng from http://www.libpng.org
+3. Edit CMakeLists.txt to tell it where to find your tiff library
+4. Type cmake .
+5. Type make . (or on Windows systems cmake makes a Visual Studio
+Project file)
+6. To specify the install directory, use make install DESTDIR="/home/me/mydist"
+
+Usage
+
+pdiff image1.(tif | png) image2.(tif | png) [options]
+-verbose : Turns on verbose mode
+-fov deg: field of view, deg, in degrees. Usually between 10.0 to 85.0. 
+This controls how much of the screen the oberserver is seeing. Front row of 
+a theatre has a field of view of around 25 degrees. Back row has a field of
+ view of around 60 degrees.
+-threshold p : Sets the number of pixels, p, to reject. For example if p is
+ 100, then the test fails if 100 or more pixels are perceptably different.
+-gamma g : The gamma to use to convert to RGB linear space. Default is 2.2
+-luminance l: The luminance of the display the observer is seeing. Default
+ is 100 candela per meter squared
+-output foo.ppm : Saves the difference image to foo.ppm
+
+Credits
+
+Hector Yee, project administrator and originator - hectorgon.blogspot.com
+Scott Corley, for png file IO code
+Mick Weiss, Linux build and release & QA
\ No newline at end of file
diff --git a/test/pdiff/RGBAImage.cpp b/test/pdiff/RGBAImage.cpp
new file mode 100644
index 0000000..267b460
--- /dev/null
+++ b/test/pdiff/RGBAImage.cpp
@@ -0,0 +1,141 @@
+/*
+RGBAImage.cpp
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "RGBAImage.h"
+#include "png.h"
+#include "tiff.h"
+#include "tiffio.h"
+
+// Reads Tiff Images
+RGBAImage* RGBAImage::ReadTiff(char *filename)
+{
+	RGBAImage *fimg = 0;
+	
+    TIFF* tif = TIFFOpen(filename, "r");
+	char emsg[1024];
+	emsg[0] = 0;
+    if (tif) {
+		TIFFRGBAImage img;
+		
+		if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+			size_t npixels;
+			uint32* raster;
+
+			npixels = img.width * img.height;
+			raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
+			if (raster != NULL) {
+				if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) {
+					// result is in ABGR
+					fimg = new RGBAImage(img.width, img.height);
+					for (int y = img.height - 1; y >= 0; y--) {
+						for (int x = 0; x < (int) img.width; x++) {
+						   fimg->Set(x,img.height - (y+1), raster[x + y * img.width]);
+						}
+					}
+				}
+			_TIFFfree(raster);
+			}
+	    }
+	    TIFFRGBAImageEnd(&img);
+	}
+	return fimg;
+}
+
+// This portion was written by Scott Corley
+RGBAImage* RGBAImage::ReadPNG(char *filename)
+{
+	RGBAImage *fimg = 0;
+	FILE *fp=fopen(filename, "rb");
+	if (!fp)
+	{
+		return NULL;
+	}
+	png_byte header[8];
+
+	fread(header, 1, 8, fp);
+	bool is_png = !png_sig_cmp(header, 0, 8);
+	if (!is_png)
+	{
+		return NULL;
+	}
+
+    png_structp png_ptr = png_create_read_struct
+       (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+        NULL, NULL);
+    if (!png_ptr)
+        return (NULL);
+
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+        png_destroy_read_struct(&png_ptr,
+           (png_infopp)NULL, (png_infopp)NULL);
+        return (NULL);
+    }
+
+    png_infop end_info = png_create_info_struct(png_ptr);
+    if (!end_info)
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+          (png_infopp)NULL);
+        return (NULL);
+    }
+
+	png_init_io(png_ptr, fp);
+	png_set_sig_bytes(png_ptr, 8);
+
+	png_read_png(png_ptr, info_ptr, 0, NULL);
+
+	png_bytep *row_pointers;
+	row_pointers = png_get_rows(png_ptr, info_ptr);
+
+	fimg = new RGBAImage(png_ptr->width, png_ptr->height);
+	for (int y = 0; y < (int) png_ptr->height; y++) {
+		for (int x = 0; x < (int) png_ptr->width; x++) {
+			uint32 value = 0;
+			if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+				value = ((uint32)row_pointers[y][x*4]) | (((uint32)row_pointers[y][x*4+1])<<8) | (((uint32)row_pointers[y][x*4+2])<<16) |(((uint32)row_pointers[y][x*4+3])<<24);
+			else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+				value = ((uint32)row_pointers[y][x*3] /*B*/) | (((uint32)row_pointers[y][x*3+1] /*G*/)<<8) | (((uint32)row_pointers[y][x*3+2]/*R*/)<<16) | (0xFFUL << 24);
+		   fimg->Set(x,y, value);
+		}
+	}
+
+	png_read_destroy(png_ptr, info_ptr, end_info);
+	return fimg;
+}
+		   
+bool RGBAImage::WritePPM()
+{	
+	if (Width <= 0) return false;
+	if (Height <=0 ) return false;
+	FILE *out = fopen(Name.c_str(), "wb");
+	if (!out) return false;
+	fprintf(out, "P6\n%d %d 255\n", Width, Height);
+	for (int y = 0; y < Height; y++) {
+		for (int x = 0; x < Width; x++) {
+			int i = x + y * Width;
+			unsigned char r = Get_Red(i);
+			unsigned char g = Get_Green(i);
+			unsigned char b = Get_Blue(i);
+			fwrite(&r, 1, 1, out);
+			fwrite(&g, 1, 1, out);
+			fwrite(&b, 1, 1, out);
+		}
+	}
+	fclose(out);
+	return true;
+}
diff --git a/test/pdiff/RGBAImage.h b/test/pdiff/RGBAImage.h
new file mode 100644
index 0000000..473a59f
--- /dev/null
+++ b/test/pdiff/RGBAImage.h
@@ -0,0 +1,57 @@
+/*
+RGBAImage.h
+Copyright (C) 2006 Yangli Hector Yee
+
+This program is free software; you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program;
+if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _RGAIMAGE_H
+#define _RGBAIMAGE_H
+
+#include<string>
+
+// assumes data is in the ABGR format
+class RGBAImage
+{
+public:
+	RGBAImage(int w, int h, const char *name = 0)
+	{
+		Width = w;
+		Height = h;
+		if (name) Name = name;
+		Data = new unsigned int[w * h];
+	};
+	~RGBAImage() { if (Data) delete[] Data; }
+	unsigned char Get_Red(unsigned int i) { return (Data[i] & 0xFF); }
+	unsigned char Get_Green(unsigned int i) { return ((Data[i]>>8) & 0xFF); }
+	unsigned char Get_Blue(unsigned int i) { return ((Data[i]>>16) & 0xFF); }
+	unsigned char Get_Alpha(unsigned int i) { return ((Data[i]>>24) & 0xFF); }
+	void Set(unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned int i)
+	{ Data[i] = r | (g << 8) | (b << 16) | (a << 24); }
+	int Get_Width(void) const { return Width; }
+	int Get_Height(void) const { return Height; }
+	void Set(int x, int y, unsigned int d) { Data[x + y * Width] = d; }
+	unsigned int Get(int x, int y) const { return Data[x + y * Width]; }
+	unsigned int Get(int i) const { return Data[i]; }
+	const std::string &Get_Name(void) const { return Name; }
+	
+	bool WritePPM();
+	static RGBAImage* ReadTiff(char *filename);
+	static RGBAImage* ReadPNG(char *filename);
+protected:
+	int Width;
+	int Height;
+	std::string Name;
+	unsigned int *Data;
+};
+
+#endif
\ No newline at end of file
diff --git a/test/pdiff/gpl.txt b/test/pdiff/gpl.txt
new file mode 100644
index 0000000..f90922e
--- /dev/null
+++ b/test/pdiff/gpl.txt
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.


More information about the cairo-commit mailing list