From d421a856d08fba2fa0fdbd362d947497a952b347 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 13 Dec 2006 18:08:25 -0800 Subject: [PATCH] pdiff: Re-indent all code I've given up on trying to preserve the old code formatting for compatibility. We're not planning on augmenting the algorithm itself, just integrating it into cairo. So I don't expect to make changes that we'll be all that interested in pushing upstream. --- test/pdiff/CompareArgs.cpp | 162 +++++------ test/pdiff/CompareArgs.h | 46 +-- test/pdiff/LPyramid.cpp | 100 +++---- test/pdiff/LPyramid.h | 38 +-- test/pdiff/Metric.cpp | 518 +++++++++++++++++----------------- test/pdiff/PerceptualDiff.cpp | 52 ++-- test/pdiff/RGBAImage.cpp | 166 +++++------ test/pdiff/RGBAImage.h | 86 +++--- test/pdiff/pdiff.h | 20 +- 9 files changed, 594 insertions(+), 594 deletions(-) diff --git a/test/pdiff/CompareArgs.cpp b/test/pdiff/CompareArgs.cpp index 60520b042..2c5e5d41e 100644 --- a/test/pdiff/CompareArgs.cpp +++ b/test/pdiff/CompareArgs.cpp @@ -1,17 +1,17 @@ /* -Comapre Args -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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" @@ -41,89 +41,89 @@ static const char *usage = CompareArgs::CompareArgs() { - ImgA = NULL; - ImgB = NULL; - ImgDiff = NULL; - Verbose = false; - FieldOfView = 45.0f; - Gamma = 2.2f; - ThresholdPixels = 100; - Luminance = 100.0f; + 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; + if (ImgA) delete ImgA; + if (ImgB) delete ImgB; + if (ImgDiff) delete ImgDiff; } bool CompareArgs::Parse_Args(int argc, char **argv) { - cairo_surface_t *surface; - if (argc < 3) { - ErrorStr = copyright; - ErrorStr += usage; + cairo_surface_t *surface; + if (argc < 3) { + ErrorStr = copyright; + ErrorStr += usage; + return false; + } + for (int i = 0; i < argc; i++) { + if (i == 1) { + surface = cairo_image_surface_create_from_png (argv[1]); + if (cairo_surface_status (surface)) + { + ErrorStr = "FAIL: Cannot open "; + ErrorStr += argv[1]; + ErrorStr += " "; + ErrorStr += cairo_status_to_string (cairo_surface_status (surface)); + ErrorStr += "\n"; return false; - } - for (int i = 0; i < argc; i++) { - if (i == 1) { - surface = cairo_image_surface_create_from_png (argv[1]); - if (cairo_surface_status (surface)) - { - ErrorStr = "FAIL: Cannot open "; - ErrorStr += argv[1]; - ErrorStr += " "; - ErrorStr += cairo_status_to_string (cairo_surface_status (surface)); - ErrorStr += "\n"; - return false; - } - ImgA = new RGBACairoImage (surface); - } else if (i == 2) { - surface = cairo_image_surface_create_from_png (argv[2]); - if (cairo_surface_status (surface)) - { - ErrorStr = "FAIL: Cannot open "; - ErrorStr += argv[2]; - ErrorStr += " "; - ErrorStr += cairo_status_to_string (cairo_surface_status (surface)); - ErrorStr += "\n"; - return false; - } - ImgB = new RGBACairoImage (surface); - } 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]); - } - } + } + ImgA = new RGBACairoImage (surface); + } else if (i == 2) { + surface = cairo_image_surface_create_from_png (argv[2]); + if (cairo_surface_status (surface)) + { + ErrorStr = "FAIL: Cannot open "; + ErrorStr += argv[2]; + ErrorStr += " "; + ErrorStr += cairo_status_to_string (cairo_surface_status (surface)); + ErrorStr += "\n"; + return false; + } + ImgB = new RGBACairoImage (surface); + } else { + if (strstr(argv[i], "-fov")) { + if (i + 1 < argc) { + FieldOfView = (float) atof(argv[i + 1]); } - } // i - return true; + } 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); + 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 index fc6993fff..fb5fc9d10 100644 --- a/test/pdiff/CompareArgs.h +++ b/test/pdiff/CompareArgs.h @@ -1,17 +1,17 @@ /* -Comapre Args -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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 @@ -26,20 +26,20 @@ class RGBACairoImage; class CompareArgs { public: - CompareArgs(); - ~CompareArgs(); - bool Parse_Args(int argc, char **argv); - void Print_Args(); + 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 + 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 diff --git a/test/pdiff/LPyramid.cpp b/test/pdiff/LPyramid.cpp index be0daa5eb..cefd24b4b 100644 --- a/test/pdiff/LPyramid.cpp +++ b/test/pdiff/LPyramid.cpp @@ -1,17 +1,17 @@ /* -Laplacian Pyramid -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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" @@ -22,66 +22,66 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, ////////////////////////////////////////////////////////////////////// LPyramid::LPyramid(float *image, int width, int height) : - Width(width), - Height(height) + Width(width), + Height(height) { - // Make the Laplacian pyramid by successively - // copying the earlier levels and blurring them - for (int i=0; i=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]; - } - } - } + for (y=0; y=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]; + 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 index 162d464d3..bb9777afc 100644 --- a/test/pdiff/LPyramid.h +++ b/test/pdiff/LPyramid.h @@ -1,17 +1,17 @@ /* -Laplacian Pyramid -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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 @@ -21,18 +21,18 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, class LPyramid { public: - LPyramid(float *image, int width, int height); - virtual ~LPyramid(); - float Get_Value(int x, int y, int level); + 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); + float *Copy(float *img); + void Convolve(float *a, float *b); - // Succesively blurred versions of the original image - float *Levels[MAX_PYR_LEVELS]; + // Succesively blurred versions of the original image + float *Levels[MAX_PYR_LEVELS]; - int Width; - int Height; + int Width; + int Height; }; #endif // _LPYRAMID_H diff --git a/test/pdiff/Metric.cpp b/test/pdiff/Metric.cpp index ded0afc36..b92dd5c92 100644 --- a/test/pdiff/Metric.cpp +++ b/test/pdiff/Metric.cpp @@ -1,17 +1,17 @@ /* -Metric -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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" @@ -26,35 +26,35 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, #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 -*/ + * 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 + // returns the threshold luminance given the adaptation luminance + // units are candelas per meter squared - float log_a, r, result; - log_a = log10f(adaptation_luminance); + 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; - } + 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); + result = powf(10.0f , r); - return result; + return result; } @@ -62,65 +62,65 @@ float tvi(float adaptation_luminance) // given the cycles per degree (cpd) and luminance (lum) float csf(float cpd, float lum) { - float a, b, result; + 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); + 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)); + result = a * cpd * expf(-b * cpd) * sqrtf(1.0f + 0.06f * expf(b * cpd)); - return result; + return result; } /* -* Visual Masking Function -* from Daly 1993 -*/ + * 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); + 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; + 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; + // 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); + 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; } - 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]); + } + L = 116.0f * f[1] - 16.0f; + A = 500.0f * (f[0] - f[1]); + B = 200.0f * (f[1] - f[2]); } int Yee_Compare_Images(RGBAImage *image_a, @@ -132,56 +132,56 @@ int Yee_Compare_Images(RGBAImage *image_a, 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, pixels_failed; - 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; - } - - pixels_failed = Yee_Compare_Images (args.ImgA, args.ImgB, - args.Gamma, args.Luminance, - args.FieldOfView, args.Verbose); - - 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 IMAGE_DIFF_CODE_ENABLED - 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"; - } -#endif - args.ErrorStr += "Generation of image \"difference\" is currently disabled\n"; - } + 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, pixels_failed; + 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; + } + + pixels_failed = Yee_Compare_Images (args.ImgA, args.ImgB, + args.Gamma, args.Luminance, + args.FieldOfView, args.Verbose); + + 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 IMAGE_DIFF_CODE_ENABLED + 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"; + } +#endif + args.ErrorStr += "Generation of image \"difference\" is currently disabled\n"; + } + return false; } int @@ -191,14 +191,14 @@ pdiff_compare (cairo_surface_t *surface_a, double luminance, double field_of_view) { - RGBAImage *image_a, *image_b; + RGBAImage *image_a, *image_b; - image_a = new RGBACairoImage (surface_a); - image_b = new RGBACairoImage (surface_b); + image_a = new RGBACairoImage (surface_a); + image_b = new RGBACairoImage (surface_b); - return Yee_Compare_Images (image_a, image_b, - gamma, luminance, - field_of_view, false); + return Yee_Compare_Images (image_a, image_b, + gamma, luminance, + field_of_view, false); } int Yee_Compare_Images(RGBAImage *image_a, @@ -208,159 +208,159 @@ int Yee_Compare_Images(RGBAImage *image_a, float field_of_view, bool verbose) { - unsigned int i, dim; - dim = image_a->Get_Width() * image_a->Get_Height(); + unsigned int i, dim; + dim = image_a->Get_Width() * image_a->Get_Height(); - // 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]; + // 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]; + float *aA = new float[dim]; + float *bA = new float[dim]; + float *aB = new float[dim]; + float *bB = new float[dim]; - if (verbose) printf("Converting RGB to XYZ\n"); + if (verbose) printf("Converting RGB to XYZ\n"); - unsigned int x, y, w, h; - w = image_a->Get_Width(); - h = image_a->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(image_a->Get_Red(i) / 255.0f, gamma); - g = powf(image_a->Get_Green(i) / 255.0f, gamma); - b = powf(image_a->Get_Blue(i) / 255.0f, gamma); + unsigned int x, y, w, h; + w = image_a->Get_Width(); + h = image_a->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(image_a->Get_Red(i) / 255.0f, gamma); + g = powf(image_a->Get_Green(i) / 255.0f, gamma); + b = powf(image_a->Get_Blue(i) / 255.0f, 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(image_b->Get_Red(i) / 255.0f, gamma); - g = powf(image_b->Get_Green(i) / 255.0f, gamma); - b = powf(image_b->Get_Blue(i) / 255.0f, 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(image_b->Get_Red(i) / 255.0f, gamma); + g = powf(image_b->Get_Green(i) / 255.0f, gamma); + b = powf(image_b->Get_Blue(i) / 255.0f, 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] * luminance; - bLum[i] = bY[i] * luminance; - } + 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] * luminance; + bLum[i] = bY[i] * luminance; } + } - if (verbose) printf("Constructing Laplacian Pyramids\n"); + if (verbose) printf("Constructing Laplacian Pyramids\n"); - LPyramid *la = new LPyramid(aLum, w, h); - LPyramid *lb = new LPyramid(bLum, w, h); + LPyramid *la = new LPyramid(aLum, w, h); + LPyramid *lb = new LPyramid(bLum, w, h); - float num_one_degree_pixels = (float) (2 * tan(field_of_view * 0.5 * M_PI / 180) * 180 / M_PI); - float pixels_per_degree = w / num_one_degree_pixels; + float num_one_degree_pixels = (float) (2 * tan(field_of_view * 0.5 * M_PI / 180) * 180 / M_PI); + float pixels_per_degree = w / num_one_degree_pixels; - if (verbose) printf("Performing test\n"); + if (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 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 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); + 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]; + 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; } - 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 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; } - 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 (!pass) + pixels_failed++; #if IMAGE_DIFF_ENABLED - if (!pass) { - if (args.ImgDiff) { - args.ImgDiff->Set(255, 0, 0, 255, index); - } - } else { - if (args.ImgDiff) { - args.ImgDiff->Set(0, 0, 0, 255, index); - } + if (!pass) { + if (args.ImgDiff) { + args.ImgDiff->Set(255, 0, 0, 255, index); } + } else { + if (args.ImgDiff) { + args.ImgDiff->Set(0, 0, 0, 255, index); + } + } #endif - } } + } - 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 (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; - return pixels_failed; + return pixels_failed; } diff --git a/test/pdiff/PerceptualDiff.cpp b/test/pdiff/PerceptualDiff.cpp index ee796665a..70c6e12b8 100644 --- a/test/pdiff/PerceptualDiff.cpp +++ b/test/pdiff/PerceptualDiff.cpp @@ -1,19 +1,19 @@ /* -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 + 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 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. + 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 + 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 @@ -27,19 +27,19 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, int main(int argc, char **argv) { - CompareArgs args; + 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; + 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/RGBAImage.cpp b/test/pdiff/RGBAImage.cpp index a39195fe0..0b540d211 100644 --- a/test/pdiff/RGBAImage.cpp +++ b/test/pdiff/RGBAImage.cpp @@ -1,17 +1,17 @@ /* -RGBAImage.cpp -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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" @@ -24,60 +24,60 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Reads Tiff Images RGBAImage* RGBAImage::ReadTiff(char *filename) { - RGBAImage *fimg = 0; + RGBAImage *fimg = 0; TIFF* tif = TIFFOpen(filename, "r"); - char emsg[1024]; - emsg[0] = 0; + char emsg[1024]; + emsg[0] = 0; if (tif) { - TIFFRGBAImage img; + TIFFRGBAImage img; - if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { - size_t npixels; - uint32* raster; + 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); + 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; + TIFFRGBAImageEnd(&img); + } + return fimg; } #endif /* HAVE_LIBTIFF */ // 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]; + 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; - } + 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); + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); if (!png_ptr) return (NULL); @@ -85,7 +85,7 @@ RGBAImage* RGBAImage::ReadPNG(char *filename) if (!info_ptr) { png_destroy_read_struct(&png_ptr, - (png_infopp)NULL, (png_infopp)NULL); + (png_infopp)NULL, (png_infopp)NULL); return (NULL); } @@ -93,52 +93,52 @@ RGBAImage* RGBAImage::ReadPNG(char *filename) if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); + (png_infopp)NULL); return (NULL); } - png_init_io(png_ptr, fp); - png_set_sig_bytes(png_ptr, 8); + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); - png_read_png(png_ptr, info_ptr, 0, NULL); + png_read_png(png_ptr, info_ptr, 0, NULL); - png_bytep *row_pointers; - row_pointers = png_get_rows(png_ptr, info_ptr); + 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_t value = 0; - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - 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_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); - } + 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_t value = 0; + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + 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_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); } + } - png_read_destroy(png_ptr, info_ptr, end_info); - return fimg; + 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); - } + 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; + } + fclose(out); + return true; } diff --git a/test/pdiff/RGBAImage.h b/test/pdiff/RGBAImage.h index f5d27c564..31727fa35 100644 --- a/test/pdiff/RGBAImage.h +++ b/test/pdiff/RGBAImage.h @@ -1,17 +1,17 @@ /* -RGBAImage.h -Copyright (C) 2006 Yangli Hector Yee + 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 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. + 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 + 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 @@ -24,51 +24,51 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, class RGBAImage { public: - RGBAImage() { Width = 0; Height = 0; Data = 0; } - RGBAImage(int w, int h, const char *name = 0) + RGBAImage() { Width = 0; Height = 0; Data = 0; } + RGBAImage(int w, int h, const char *name = 0) { - Width = w; - Height = h; - if (name) Name = name; - Data = new unsigned int[w * h]; + Width = w; + Height = h; + if (name) Name = name; + Data = new unsigned int[w * h]; }; - ~RGBAImage() { if (Data) delete[] Data; } - virtual unsigned char Get_Red(unsigned int i) { return (Data[i] & 0xFF); } - virtual unsigned char Get_Green(unsigned int i) { return ((Data[i]>>8) & 0xFF); } - virtual unsigned char Get_Blue(unsigned int i) { return ((Data[i]>>16) & 0xFF); } - virtual unsigned char Get_Alpha(unsigned int i) { return ((Data[i]>>24) & 0xFF); } - virtual void Set(unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned int i) + ~RGBAImage() { if (Data) delete[] Data; } + virtual unsigned char Get_Red(unsigned int i) { return (Data[i] & 0xFF); } + virtual unsigned char Get_Green(unsigned int i) { return ((Data[i]>>8) & 0xFF); } + virtual unsigned char Get_Blue(unsigned int i) { return ((Data[i]>>16) & 0xFF); } + virtual unsigned char Get_Alpha(unsigned int i) { return ((Data[i]>>24) & 0xFF); } + virtual 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; } - virtual void Set(int x, int y, unsigned int d) { Data[x + y * Width] = d; } - virtual unsigned int Get(int x, int y) const { return Data[x + y * Width]; } - virtual unsigned int Get(int i) const { return Data[i]; } - const std::string &Get_Name(void) const { return Name; } + int Get_Width(void) const { return Width; } + int Get_Height(void) const { return Height; } + virtual void Set(int x, int y, unsigned int d) { Data[x + y * Width] = d; } + virtual unsigned int Get(int x, int y) const { return Data[x + y * Width]; } + virtual 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); + bool WritePPM(); + static RGBAImage* ReadTiff(char *filename); + static RGBAImage* ReadPNG(char *filename); protected: - int Width; - int Height; - std::string Name; - unsigned int *Data; + int Width; + int Height; + std::string Name; + unsigned int *Data; }; class RGBACairoImage : public RGBAImage { public: RGBACairoImage (cairo_surface_t *surface) - { - Width = cairo_image_surface_get_width (surface); - Height = cairo_image_surface_get_height (surface); - Data = (unsigned int *) cairo_image_surface_get_data (surface); - if (cairo_image_surface_get_stride (surface) != 4 * Width) { - fprintf (stderr, "Error: Currently only support images where stride == 4 * width\n"); - exit (1); + { + Width = cairo_image_surface_get_width (surface); + Height = cairo_image_surface_get_height (surface); + Data = (unsigned int *) cairo_image_surface_get_data (surface); + if (cairo_image_surface_get_stride (surface) != 4 * Width) { + fprintf (stderr, "Error: Currently only support images where stride == 4 * width\n"); + exit (1); + } } - } ~RGBACairoImage() { } unsigned int ARGB_to_ABGR(unsigned int pixel) const { diff --git a/test/pdiff/pdiff.h b/test/pdiff/pdiff.h index 7c2c401a9..195a34c4e 100644 --- a/test/pdiff/pdiff.h +++ b/test/pdiff/pdiff.h @@ -1,17 +1,17 @@ /* -Copyright (C) 2006 Yangli Hector Yee -Copyright (C) 2006 Red Hat, Inc. + Copyright (C) 2006 Yangli Hector Yee + Copyright (C) 2006 Red Hat, Inc. -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 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. + 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 + 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 _PDIFF_H