From: José Fonseca Date: Sun, 12 Dec 2010 11:13:33 +0000 (+0000) Subject: Compare screenshots. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=077142e1750205b63dbc6a03d0ae9e0bda7e4c06;hp=3cb348d77b6fab32694b74a22a91eba395f4a729;p=apitrace Compare screenshots. --- diff --git a/glretrace.py b/glretrace.py index c74d88a..c516c16 100644 --- a/glretrace.py +++ b/glretrace.py @@ -162,7 +162,11 @@ bool __reshape_window = false; unsigned __frame = 0; long long __startTime = 0; -bool __screenshots = 0; +static enum { + MODE_DISPLAY = 0, + MODE_SCREENSHOT, + MODE_COMPARE, +} __mode = MODE_DISPLAY; static void @@ -224,12 +228,34 @@ static void display_noop(void) { static void frame_complete(void) { ++__frame; - if (__screenshots && !__reshape_window) { + if (!__reshape_window && (__mode == MODE_SCREENSHOT || __mode == MODE_COMPARE)) { char filename[PATH_MAX]; + snprintf(filename, sizeof filename, "screenshot_%04u.png", __frame); - Image::Image image(__window_width, __window_height, true); - glReadPixels(0, 0, __window_width, __window_height, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels); - image.writePNG(filename); + + Image::Image *ref; + if (__mode == MODE_COMPARE) { + ref = Image::readPNG(filename); + if (!ref) { + return; + } + if (verbosity) + std::cout << "Read " << filename << "\n"; + } + + Image::Image src(__window_width, __window_height, true); + glReadPixels(0, 0, __window_width, __window_height, GL_RGBA, GL_UNSIGNED_BYTE, src.pixels); + + if (__mode == MODE_SCREENSHOT) { + if (src.writePNG(filename) && verbosity) { + std::cout << "Wrote " << filename << "\n"; + } + } + + if (__mode == MODE_COMPARE) { + std::cout << "Frame " << __frame << " average precision of " << src.compare(*ref) << " bits\n"; + delete ref; + } } } @@ -269,8 +295,12 @@ static void display(void) { " in " << timeInterval << " secs," " average of " << (__frame/timeInterval) << " fps\n"; - glutDisplayFunc(&display_noop); - glutIdleFunc(NULL); + if (__mode == MODE_DISPLAY) { + glutDisplayFunc(&display_noop); + glutIdleFunc(NULL); + } else { + exit(0); + } } static void idle(void) { @@ -282,6 +312,17 @@ static void idle(void) { glutPostRedisplay(); } +static void usage(void) { + std::cout << + "Usage: glretrace [OPTION] TRACE\n" + "Replay TRACE.\n" + "\n" + " -c compare against screenshots\n" + " -db use a double buffer visual\n" + " -s take snapshots\n" + " -v verbose output\n"; +} + int main(int argc, char **argv) { @@ -295,14 +336,20 @@ int main(int argc, char **argv) if (!strcmp(arg, "--")) { break; + } else if (!strcmp(arg, "-c")) { + __mode = MODE_COMPARE; } else if (!strcmp(arg, "-db")) { double_buffer = true; + } else if (!strcmp(arg, "--help")) { + usage(); + return 0; } else if (!strcmp(arg, "-s")) { - __screenshots = true; + __mode = MODE_SCREENSHOT; } else if (!strcmp(arg, "-v")) { ++verbosity; } else { std::cerr << "error: unknown option " << arg << "\n"; + usage(); return 1; } } diff --git a/image.cpp b/image.cpp index ce37c19..9fd1dc8 100644 --- a/image.cpp +++ b/image.cpp @@ -26,6 +26,7 @@ #include +#include #include #include @@ -273,4 +274,37 @@ no_fp: } +double Image::compare(Image &ref) +{ + if (width != ref.width || + height != ref.height) { + return 0.0; + } + + const unsigned char *pSrc = start(); + const unsigned char *pRef = ref.start(); + + unsigned long long error = 0; + for (unsigned y = 0; y < height; ++y) { + for (unsigned x = 0; x < width*4; ++x) { + int delta = pSrc[x] - pRef[x]; + error += delta*delta; + } + + pSrc += stride(); + pRef += ref.stride(); + } + + double numerator = error*2 + 1; + double denominator = height*width*4ULL*255ULL*255ULL*2; + double quotient = numerator/denominator; + + // Precision in bits + double precision = -log(quotient)/log(2.0); + + return precision; +} + + + } /* namespace Image */ diff --git a/image.hpp b/image.hpp index e1919d6..5a9704e 100644 --- a/image.hpp +++ b/image.hpp @@ -59,8 +59,22 @@ public: delete [] pixels; } + inline unsigned char *start(void) { + return flipped ? pixels + (height - 1)*width*4 : pixels; + } + + inline unsigned char *end(void) { + return flipped ? pixels - width*4 : pixels + height*width*4; + } + + inline signed stride(void) const { + return flipped ? -width*4 : width*4; + } + bool writeBMP(const char *filename) const; bool writePNG(const char *filename) const; + + double compare(Image &ref); };