anim_diff: add a -raw_comparison flag
If this flag is not used, RGB is premultiplied before comparison. Otherwise, the raw R/G/B values are compared, which can be a problem in transparent area (alpha=0 R/G/B=anything) Change-Id: I131cc10ec92414ad508b81f599a60d0097cac470
This commit is contained in:
		
				
					committed by
					
						
						James Zern
					
				
			
			
				
	
			
			
			
						parent
						
							155c1b222b
						
					
				
				
					commit
					acb297e9c2
				
			@@ -37,6 +37,7 @@ bool CompareValues(T a, T b, const std::string& output_str) {
 | 
			
		||||
// is OK for other aspects like offsets, dispose/blend method to vary.
 | 
			
		||||
bool CompareAnimatedImagePair(const AnimatedImage& img1,
 | 
			
		||||
                              const AnimatedImage& img2,
 | 
			
		||||
                              bool premultiply,
 | 
			
		||||
                              double min_psnr) {
 | 
			
		||||
  bool ok = true;
 | 
			
		||||
  ok = CompareValues(img1.canvas_width, img2.canvas_width,
 | 
			
		||||
@@ -68,7 +69,7 @@ bool CompareAnimatedImagePair(const AnimatedImage& img1,
 | 
			
		||||
    int max_diff;
 | 
			
		||||
    double psnr;
 | 
			
		||||
    GetDiffAndPSNR(rgba1, rgba2, img1.canvas_width, img1.canvas_height,
 | 
			
		||||
                   &max_diff, &psnr);
 | 
			
		||||
                   premultiply, &max_diff, &psnr);
 | 
			
		||||
    if (min_psnr > 0.) {
 | 
			
		||||
      if (psnr < min_psnr) {
 | 
			
		||||
        fprintf(stderr, "Frame #%zu, psnr = %.2lf (min_psnr = %f)\n", i,
 | 
			
		||||
@@ -87,7 +88,7 @@ bool CompareAnimatedImagePair(const AnimatedImage& img1,
 | 
			
		||||
 | 
			
		||||
void Help() {
 | 
			
		||||
  printf("\nUsage: anim_diff <image1> <image2> [-dump_frames <folder>] "
 | 
			
		||||
         "[-min_psnr <float>]\n");
 | 
			
		||||
         "[-min_psnr <float>][-raw_comparison]\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
@@ -98,6 +99,7 @@ int main(int argc, const char* argv[]) {
 | 
			
		||||
  double min_psnr = 0.;
 | 
			
		||||
  bool got_input1 = false;
 | 
			
		||||
  bool got_input2 = false;
 | 
			
		||||
  bool premultiply = true;
 | 
			
		||||
  const char* files[2];
 | 
			
		||||
 | 
			
		||||
  if (argc < 3) {
 | 
			
		||||
@@ -127,6 +129,8 @@ int main(int argc, const char* argv[]) {
 | 
			
		||||
      } else {
 | 
			
		||||
        parse_error = true;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (!strcmp(argv[c], "-raw_comparison")) {
 | 
			
		||||
      premultiply = false;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (!got_input1) {
 | 
			
		||||
        files[0] = argv[c];
 | 
			
		||||
@@ -161,7 +165,8 @@ int main(int argc, const char* argv[]) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!CompareAnimatedImagePair(images[0], images[1], min_psnr)) {
 | 
			
		||||
  if (!CompareAnimatedImagePair(images[0], images[1],
 | 
			
		||||
                                premultiply, min_psnr)) {
 | 
			
		||||
    fprintf(stderr, "\nFiles %s and %s differ.\n", files[0], files[1]);
 | 
			
		||||
    return -3;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -815,20 +815,41 @@ bool ReadAnimatedImage(const char filename[], AnimatedImage* const image,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Accumulate(double v1, double v2, double* const max_diff,
 | 
			
		||||
                       double* const sse) {
 | 
			
		||||
  const double diff = fabs(v1 - v2);
 | 
			
		||||
  if (diff > *max_diff) *max_diff = diff;
 | 
			
		||||
  *sse += diff * diff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
 | 
			
		||||
                    uint32_t width, uint32_t height, int* const max_diff,
 | 
			
		||||
                    double* const psnr) {
 | 
			
		||||
                    uint32_t width, uint32_t height, bool premultiply,
 | 
			
		||||
                    int* const max_diff, double* const psnr) {
 | 
			
		||||
  const uint32_t stride = width * kNumChannels;
 | 
			
		||||
  *max_diff = 0;
 | 
			
		||||
  const int kAlphaChannel = kNumChannels - 1;
 | 
			
		||||
  double f_max_diff = 0.;
 | 
			
		||||
  double sse = 0.;
 | 
			
		||||
  for (uint32_t y = 0; y < height; ++y) {
 | 
			
		||||
    for (uint32_t x = 0; x < stride; ++x) {
 | 
			
		||||
    for (uint32_t x = 0; x < stride; x += kNumChannels) {
 | 
			
		||||
      const size_t offset = y * stride + x;
 | 
			
		||||
      const int diff = abs(rgba1[offset] - rgba2[offset]);
 | 
			
		||||
      if (diff > *max_diff) *max_diff = diff;
 | 
			
		||||
      sse += diff * diff;
 | 
			
		||||
      const int alpha1 = rgba1[offset + kAlphaChannel];
 | 
			
		||||
      const int alpha2 = rgba2[offset + kAlphaChannel];
 | 
			
		||||
      Accumulate(alpha1, alpha2, &f_max_diff, &sse);
 | 
			
		||||
      if (!premultiply) {
 | 
			
		||||
        for (int k = 0; k < kAlphaChannel; ++k) {
 | 
			
		||||
          Accumulate(rgba1[offset + k], rgba2[offset + k], &f_max_diff, &sse);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        // premultiply R/G/B channels with alpha value
 | 
			
		||||
        for (int k = 0; k < kAlphaChannel; ++k) {
 | 
			
		||||
          Accumulate(rgba1[offset + k] * alpha1 / 255.,
 | 
			
		||||
                     rgba2[offset + k] * alpha2 / 255.,
 | 
			
		||||
                     &f_max_diff, &sse);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  *max_diff = static_cast<int>(f_max_diff);
 | 
			
		||||
  if (*max_diff == 0) {
 | 
			
		||||
    *psnr = 99.;  // PSNR when images are identical.
 | 
			
		||||
  } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,10 @@ bool ReadAnimatedImage(const char filename[], AnimatedImage* const image,
 | 
			
		||||
                       bool dump_frames, const char dump_folder[]);
 | 
			
		||||
 | 
			
		||||
// Given two RGBA buffers, calculate max pixel difference and PSNR.
 | 
			
		||||
// If 'premultiply' is true, R/G/B values will be pre-multiplied by the
 | 
			
		||||
// transparency before comparison.
 | 
			
		||||
void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
 | 
			
		||||
                    uint32_t width, uint32_t height, int* const max_diff,
 | 
			
		||||
                    double* const psnr);
 | 
			
		||||
                    uint32_t width, uint32_t height, bool premultiply,
 | 
			
		||||
                    int* const max_diff, double* const psnr);
 | 
			
		||||
 | 
			
		||||
#endif  // WEBP_EXAMPLES_ANIM_UTIL_H_
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user