def _FramesFromMp4(self, mp4_file):
        host_platform = platform.GetHostPlatform()
        if not host_platform.CanLaunchApplication('avconv'):
            host_platform.InstallApplication('avconv')

        def GetDimensions(video):
            proc = subprocess.Popen(['avconv', '-i', video],
                                    stderr=subprocess.PIPE)
            dimensions = None
            output = ''
            for line in proc.stderr.readlines():
                output += line
                if 'Video:' in line:
                    dimensions = line.split(',')[2]
                    dimensions = map(int, dimensions.split()[0].split('x'))
                    break
            proc.communicate()
            assert dimensions, (
                'Failed to determine video dimensions. output=%s' % output)
            return dimensions

        def GetFrameTimestampMs(stderr):
            """Returns the frame timestamp in integer milliseconds from the dump log.

      The expected line format is:
      '  dts=1.715  pts=1.715\n'

      We have to be careful to only read a single timestamp per call to avoid
      deadlock because avconv interleaves its writes to stdout and stderr.
      """
            while True:
                line = ''
                next_char = ''
                while next_char != '\n':
                    next_char = stderr.read(1)
                    line += next_char
                if 'pts=' in line:
                    return int(1000 * float(line.split('=')[-1]))

        dimensions = GetDimensions(mp4_file)
        frame_length = dimensions[0] * dimensions[1] * 3
        frame_data = bytearray(frame_length)

        # Use rawvideo so that we don't need any external library to parse frames.
        proc = subprocess.Popen([
            'avconv', '-i', mp4_file, '-vcodec', 'rawvideo', '-pix_fmt',
            'rgb24', '-dump', '-loglevel', 'debug', '-f', 'rawvideo', '-'
        ],
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE)
        while True:
            num_read = proc.stdout.readinto(frame_data)
            if not num_read:
                raise StopIteration
            assert num_read == len(
                frame_data), 'Unexpected frame size: %d' % num_read
            yield (GetFrameTimestampMs(proc.stderr),
                   image_util.FromRGBPixels(dimensions[0], dimensions[1],
                                            frame_data))
  def testHistogramDistanceIgnoreColor(self):
    pixels = [1, 2, 3, 1, 2, 3,
              1, 2, 3, 1, 2, 3]
    bmp = image_util.FromRGBPixels(2, 2, pixels)

    hist1 = image_util.GetColorHistogram(bmp, ignore_color=RgbaColor(1, 2, 3))
    hist2 = image_util.GetColorHistogram(bmp)

    self.assertEquals(hist1.Distance(hist2), 0)
 def testWriteCroppedBmpToPngFile(self):
   pixels = [255, 0, 0, 255, 255, 0, 0, 0, 0,
             255, 255, 0, 0, 255, 0, 0, 0, 0]
   orig = image_util.FromRGBPixels(3, 2, pixels)
   orig = image_util.Crop(orig, 0, 0, 2, 2)
   temp_file = tempfile.NamedTemporaryFile(suffix='.png').name
   image_util.WritePngFile(orig, temp_file)
   new_file = image_util.FromPngFile(temp_file)
   self.assertTrue(image_util.AreEqual(orig, new_file, likely_equal=True))
  def testCrop(self):
    pixels = [0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0,
              0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0,
              0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0]
    bmp = image_util.FromRGBPixels(4, 3, pixels)
    bmp = image_util.Crop(bmp, 1, 2, 2, 1)

    self.assertEquals(2, image_util.Width(bmp))
    self.assertEquals(1, image_util.Height(bmp))
    image_util.GetPixelColor(bmp, 0, 0).AssertIsRGB(1, 2, 0)
    image_util.GetPixelColor(bmp, 1, 0).AssertIsRGB(2, 2, 0)
    self.assertEquals(image_util.Pixels(bmp), bytearray([1, 2, 0, 2, 2, 0]))
  def testGetBoundingBox(self):
    pixels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
              0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    bmp = image_util.FromRGBPixels(4, 3, pixels)
    box, count = image_util.GetBoundingBox(bmp, RgbaColor(1, 0, 0))
    self.assertEquals(box, (1, 1, 2, 1))
    self.assertEquals(count, 2)

    box, count = image_util.GetBoundingBox(bmp, RgbaColor(0, 1, 0))
    self.assertEquals(box, None)
    self.assertEquals(count, 0)
  def testHistogramIgnoreColor(self):
    pixels = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,
              1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3,
              1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3]
    bmp = image_util.FromRGBPixels(4, 3, pixels)

    hist = image_util.GetColorHistogram(bmp,
                                        ignore_color=RgbaColor(1, 2, 3))
    self.assertEquals(hist.r[1], 0)
    self.assertEquals(hist.r[5], 2)
    self.assertEquals(hist.r[8], 2)
    self.assertEquals(hist.g[2], 0)
    self.assertEquals(hist.g[4], 2)
    self.assertEquals(hist.g[7], 2)
    self.assertEquals(hist.b[3], 0)
    self.assertEquals(hist.b[6], 4)
  def testHistogramIgnoreColorTolerance(self):
    pixels = [1, 2, 3, 4, 5, 6,
              7, 8, 9, 8, 7, 6]
    bmp = image_util.FromRGBPixels(2, 2, pixels)

    hist = image_util.GetColorHistogram(
        bmp, ignore_color=RgbaColor(0, 1, 2), tolerance=1)
    self.assertEquals(hist.r[1], 0)
    self.assertEquals(hist.r[4], 1)
    self.assertEquals(hist.r[7], 1)
    self.assertEquals(hist.r[8], 1)
    self.assertEquals(hist.g[2], 0)
    self.assertEquals(hist.g[5], 1)
    self.assertEquals(hist.g[7], 1)
    self.assertEquals(hist.g[8], 1)
    self.assertEquals(hist.b[3], 0)
    self.assertEquals(hist.b[6], 2)
    self.assertEquals(hist.b[9], 1)
  def testHistogram(self):
    pixels = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,
              1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3,
              1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3]
    bmp = image_util.FromRGBPixels(4, 3, pixels)
    bmp = image_util.Crop(bmp, 1, 1, 2, 2)

    hist = image_util.GetColorHistogram(bmp)
    for i in xrange(3):
      self.assertEquals(sum(hist[i]),
                        image_util.Width(bmp) * image_util.Height(bmp))
    self.assertEquals(hist.r[1], 0)
    self.assertEquals(hist.r[5], 2)
    self.assertEquals(hist.r[8], 2)
    self.assertEquals(hist.g[2], 0)
    self.assertEquals(hist.g[4], 2)
    self.assertEquals(hist.g[7], 2)
    self.assertEquals(hist.b[3], 0)
    self.assertEquals(hist.b[6], 4)