X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=scripts%2Fsnapdiff.py;h=59ec870ea06954eee1f5ca69f9297d5c42ee3f2d;hb=beda4440ab82ed4e8f7568fd5a19d8d595b748a3;hp=60d9ae97ca740b26b5820f76567a4d414c6055d3;hpb=6d5954b051edc89b3d0c70e7385aae7439dacd91;p=apitrace diff --git a/scripts/snapdiff.py b/scripts/snapdiff.py index 60d9ae9..59ec870 100755 --- a/scripts/snapdiff.py +++ b/scripts/snapdiff.py @@ -39,17 +39,26 @@ import operator from PIL import Image from PIL import ImageChops from PIL import ImageEnhance +from PIL import ImageFilter -thumb_size = 320, 320 +thumbSize = 320 +gaussian_kernel = ImageFilter.Kernel((3, 3), [1, 2, 1, 2, 4, 2, 1, 2, 1], 16) class Comparer: '''Image comparer.''' def __init__(self, ref_image, src_image, alpha = False): - self.ref_im = Image.open(ref_image) - self.src_im = Image.open(src_image) + if isinstance(ref_image, basestring): + self.ref_im = Image.open(ref_image) + else: + self.ref_im = ref_image + + if isinstance(src_image, basestring): + self.src_im = Image.open(src_image) + else: + self.src_im = src_image # Ignore if not alpha: @@ -58,7 +67,13 @@ class Comparer: self.diff = ImageChops.difference(self.src_im, self.ref_im) + def size_mismatch(self): + return self.ref_im.size != self.src_im.size + def write_diff(self, diff_image, fuzz = 0.05): + if self.size_mismatch(): + return + # make a difference image similar to ImageMagick's compare utility mask = ImageEnhance.Brightness(self.diff).enhance(1.0/fuzz) mask = mask.convert('L') @@ -70,9 +85,16 @@ class Comparer: diff_im = Image.blend(self.src_im, diff_im, 0xcc/255.0) diff_im.save(diff_image) - def precision(self): + def precision(self, filter=False): + if self.size_mismatch(): + return 0.0 + + diff = self.diff + if filter: + diff = diff.filter(gaussian_kernel) + # See also http://effbot.org/zone/pil-comparing-images.htm - h = self.diff.histogram() + h = diff.histogram() square_error = 0 for i in range(1, 256): square_error += sum(h[i : 3*256: 256])*i*i @@ -80,8 +102,12 @@ class Comparer: bits = -math.log(rel_error)/math.log(2.0) return bits - def ae(self): + def ae(self, fuzz = 0.05): # Compute absolute error + + if self.size_mismatch(): + return sys.maxint + # TODO: this is approximate due to the grayscale conversion h = self.diff.convert('L').histogram() ae = sum(h[int(255 * fuzz) + 1 : 256]) @@ -96,7 +122,18 @@ def surface(html, image): and (not os.path.exists(thumb) \ or os.path.getmtime(thumb) < os.path.getmtime(image)): im = Image.open(image) - im.thumbnail(thumb_size) + imageWidth, imageHeight = im.size + if imageWidth <= thumbSize and imageHeight <= thumbSize: + if imageWidth >= imageHeight: + imageHeight = imageHeight*thumbSize/imageWidth + imageWidth = thumbSize + else: + imageWidth = imageWidth*thumbSize/imageHeight + imageHeight = thumbSize + html.write('
%s | %s | Δ | |
---|---|---|---|
File | %s | %s | Δ |
%s | \n' % (bgcolor, ref_image, image)) + if not match or options.show_all: + if options.overwrite \ + or not os.path.exists(delta_image) \ + or (os.path.getmtime(delta_image) < os.path.getmtime(ref_image) \ + and os.path.getmtime(delta_image) < os.path.getmtime(src_image)): + comparer.write_diff(delta_image, fuzz=options.fuzz) + surface(html, ref_image) + surface(html, src_image) + surface(html, delta_image) html.write('