summaryrefslogtreecommitdiffstats
path: root/chromium/tools/site_compare/commands/maskmaker.py
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/tools/site_compare/commands/maskmaker.py')
-rw-r--r--chromium/tools/site_compare/commands/maskmaker.py272
1 files changed, 0 insertions, 272 deletions
diff --git a/chromium/tools/site_compare/commands/maskmaker.py b/chromium/tools/site_compare/commands/maskmaker.py
deleted file mode 100644
index 8aeefcbf005..00000000000
--- a/chromium/tools/site_compare/commands/maskmaker.py
+++ /dev/null
@@ -1,272 +0,0 @@
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Component for automatically creating masks of changing areas of a website.
-
-Works by repeated invokation of a browser and scraping of the resulting page.
-Areas that differ will be added to the auto-generated mask. The mask generator
-considers the mask complete when further scrapes fail to produce any differences
-in the mask.
-"""
-
-import os # Functions for walking the directory tree
-import tempfile # Get a temporary directory to hold intermediates
-import time # Used for sleep() and naming masks by time
-
-import command_line
-import drivers
-from PIL import Image
-from PIL import ImageChops
-import scrapers
-
-
-def CreateCommand(cmdline):
- """Inserts the command and arguments into a command line for parsing."""
- cmd = cmdline.AddCommand(
- ["maskmaker"],
- "Automatically generates a mask from a list of URLs",
- ValidateMaskmaker,
- ExecuteMaskmaker)
-
- cmd.AddArgument(
- ["-bp", "--browserpath"], "Full path to browser's executable",
- type="readfile", metaname="PATH")
- cmd.AddArgument(
- ["-b", "--browser"], "Which browser to use", type="string",
- default="chrome")
- cmd.AddArgument(
- ["-bv", "--browserver"], "Version of the browser", metaname="VERSION")
- cmd.AddArgument(
- ["-o", "--outdir"], "Directory to store generated masks", metaname="DIR",
- required=True)
- cmd.AddArgument(
- ["-u", "--url"], "URL to compare")
- cmd.AddArgument(
- ["-l", "--list"], "List of URLs to compare", type="readfile")
- cmd.AddMutualExclusion(["--url", "--list"])
- cmd.AddArgument(
- ["-s", "--startline"], "First line of URL list", type="int")
- cmd.AddArgument(
- ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
- cmd.AddArgument(
- ["-c", "--count"], "Number of lines of URL file to use", type="int")
- cmd.AddDependency("--startline", "--list")
- cmd.AddRequiredGroup(["--url", "--list"])
- cmd.AddDependency("--endline", "--list")
- cmd.AddDependency("--count", "--list")
- cmd.AddMutualExclusion(["--count", "--endline"])
- cmd.AddDependency("--count", "--startline")
- cmd.AddArgument(
- ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
- "finish loading",
- type="int", default=60)
- cmd.AddArgument(
- ["-w", "--wait"],
- "Amount of time (in seconds) to wait between successive scrapes",
- type="int", default=60)
- cmd.AddArgument(
- ["-sc", "--scrapes"],
- "Number of successive scrapes which must result in no change to a mask "
- "before mask creation is considered complete", type="int", default=10)
- cmd.AddArgument(
- ["-sz", "--size"], "Browser window size", default=(800, 600), type="coords")
- cmd.AddArgument(["-sd", "--scrapedir"], "Directory to store scrapes")
- cmd.AddArgument(
- ["-gu", "--giveup"],
- "Number of times to scrape before giving up", type="int", default=50)
- cmd.AddArgument(
- ["-th", "--threshhold"],
- "Percentage of different pixels (0-100) above which the scrape will be"
- "discarded and the mask not updated.", type="int", default=100)
- cmd.AddArgument(
- ["--er", "--errors"],
- "Number of times a scrape can fail before giving up on the URL.",
- type="int", default=1)
-
-
-def ValidateMaskmaker(command):
- """Validate the arguments to maskmaker. Raises ParseError if failed."""
- executables = [".exe", ".com", ".bat"]
- if command["--browserpath"]:
- if os.path.splitext(command["--browserpath"])[1].lower() not in executables:
- raise command_line.ParseError("Browser filename must be an executable")
-
-
-def ExecuteMaskmaker(command):
- """Performs automatic mask generation."""
-
- # Get the list of URLs to generate masks for
- class MaskmakerURL(object):
- """Helper class for holding information about a URL passed to maskmaker."""
- __slots__ = ['url', 'consecutive_successes', 'errors']
- def __init__(self, url):
- self.url = url
- self.consecutive_successes = 0
- self.errors = 0
-
- if command["--url"]:
- url_list = [MaskmakerURL(command["--url"])]
- else:
- startline = command["--startline"]
- if command["--count"]:
- endline = startline+command["--count"]
- else:
- endline = command["--endline"]
- url_list = [MaskmakerURL(url.strip()) for url in
- open(command["--list"], "r").readlines()[startline:endline]]
-
- complete_list = []
- error_list = []
-
- outdir = command["--outdir"]
- scrapes = command["--scrapes"]
- errors = command["--errors"]
- size = command["--size"]
- scrape_pass = 0
-
- scrapedir = command["--scrapedir"]
- if not scrapedir: scrapedir = tempfile.gettempdir()
-
- # Get the scraper
- scraper = scrapers.GetScraper((command["--browser"], command["--browserver"]))
-
- # Repeatedly iterate through the list of URLs until either every URL has
- # a successful mask or too many errors, or we've exceeded the giveup limit
- while url_list and scrape_pass < command["--giveup"]:
- # Scrape each URL
- for url in url_list:
- print "Processing %r..." % url.url
- mask_filename = drivers.windowing.URLtoFilename(url.url, outdir, ".bmp")
-
- # Load the existing mask. This is in a loop so we can try to recover
- # from error conditions
- while True:
- try:
- mask = Image.open(mask_filename)
- if mask.size != size:
- print " %r already exists and is the wrong size! (%r vs %r)" % (
- mask_filename, mask.size, size)
- mask_filename = "%s_%r%s" % (
- mask_filename[:-4], size, mask_filename[-4:])
- print " Trying again as %r..." % mask_filename
- continue
- break
- except IOError:
- print " %r does not exist, creating" % mask_filename
- mask = Image.new("1", size, 1)
- mask.save(mask_filename)
-
- # Find the stored scrape path
- mask_scrape_dir = os.path.join(
- scrapedir, os.path.splitext(os.path.basename(mask_filename))[0])
- drivers.windowing.PreparePath(mask_scrape_dir)
-
- # Find the baseline image
- mask_scrapes = os.listdir(mask_scrape_dir)
- mask_scrapes.sort()
-
- if not mask_scrapes:
- print " No baseline image found, mask will not be updated"
- baseline = None
- else:
- baseline = Image.open(os.path.join(mask_scrape_dir, mask_scrapes[0]))
-
- mask_scrape_filename = os.path.join(mask_scrape_dir,
- time.strftime("%y%m%d-%H%M%S.bmp"))
-
- # Do the scrape
- result = scraper.Scrape(
- [url.url], mask_scrape_dir, size, (0, 0),
- command["--timeout"], path=command["--browserpath"],
- filename=mask_scrape_filename)
-
- if result:
- # Return value other than None means an error
- print " Scrape failed with error '%r'" % result
- url.errors += 1
- if url.errors >= errors:
- print " ** Exceeded maximum error count for this URL, giving up"
- continue
-
- # Load the new scrape
- scrape = Image.open(mask_scrape_filename)
-
- # Calculate the difference between the new scrape and the baseline,
- # subject to the current mask
- if baseline:
- diff = ImageChops.multiply(ImageChops.difference(scrape, baseline),
- mask.convert(scrape.mode))
-
- # If the difference is none, there's nothing to update
- if max(diff.getextrema()) == (0, 0):
- print " Scrape identical to baseline, no change in mask"
- url.consecutive_successes += 1
- if url.consecutive_successes >= scrapes:
- print " ** No change for %r scrapes, done!" % scrapes
- else:
- # convert the difference to black and white, then change all
- # black pixels (where the scrape and the baseline were identical)
- # to white, all others (where the scrape and the baseline differed)
- # to black.
- #
- # Since the below command is a little unclear, here's how it works.
- # 1. convert("L") converts the RGB image to grayscale
- # 2. point() maps grayscale values (or the individual channels)
- # of an RGB image) to different ones. Because it operates on
- # individual channels, the grayscale conversion from step 1
- # is necessary.
- # 3. The "1" second parameter to point() outputs the result as
- # a monochrome bitmap. If the original RGB image were converted
- # directly to monochrome, PIL would dither it.
- diff = diff.convert("L").point([255]+[0]*255, "1")
-
- # count the number of different pixels
- diff_pixels = diff.getcolors()[0][0]
-
- # is this too much?
- diff_pixel_percent = diff_pixels * 100.0 / (mask.size[0]*mask.size[1])
- if diff_pixel_percent > command["--threshhold"]:
- print (" Scrape differed from baseline by %.2f percent, ignoring"
- % diff_pixel_percent)
- else:
- print " Scrape differed in %d pixels, updating mask" % diff_pixels
- mask = ImageChops.multiply(mask, diff)
- mask.save(mask_filename)
-
- # reset the number of consecutive "good" scrapes
- url.consecutive_successes = 0
-
- # Remove URLs whose mask is deemed done
- complete_list.extend(
- [url for url in url_list if url.consecutive_successes >= scrapes])
- error_list.extend(
- [url for url in url_list if url.errors >= errors])
- url_list = [
- url for url in url_list if
- url.consecutive_successes < scrapes and
- url.errors < errors]
-
- scrape_pass += 1
- print "**Done with scrape pass %d\n" % scrape_pass
-
- if scrape_pass >= command["--giveup"]:
- print "**Exceeded giveup threshhold. Giving up."
- else:
- print "Waiting %d seconds..." % command["--wait"]
- time.sleep(command["--wait"])
-
- print
- print "*** MASKMAKER COMPLETE ***"
- print "Summary report:"
- print " %d masks successfully generated" % len(complete_list)
- for url in complete_list:
- print " ", url.url
- print " %d masks failed with too many errors" % len(error_list)
- for url in error_list:
- print " ", url.url
- if scrape_pass >= command["--giveup"]:
- print (" %d masks were not completed before "
- "reaching the giveup threshhold" % len(url_list))
- for url in url_list:
- print " ", url.url