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.
This commit is contained in:
Carl Worth 2006-12-13 18:08:25 -08:00
parent 4f6611ef6c
commit d421a856d0
9 changed files with 594 additions and 594 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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<MAX_PYR_LEVELS; i++) {
if (i == 0) {
Levels[i] = Copy(image);
} else {
Levels[i] = new float[Width * Height];
Convolve(Levels[i], Levels[i - 1]);
}
// 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];
}
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];
int max = Width * Height;
float *out = new float[max];
for (int i = 0; i < max; i++) out[i] = img[i];
return out;
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};
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];
}
}
}
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];
int index = x + y * Width;
int l = level;
if (l > MAX_PYR_LEVELS) l = MAX_PYR_LEVELS;
return Levels[level][index];
}

View file

@ -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

View file

@ -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;
}

View file

@ -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 <stdio.h>
@ -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;
}

View file

@ -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;
}

View file

@ -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 {

View file

@ -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