| Index: trunk/src/tools/telemetry/telemetry/core/bitmap.py
|
| ===================================================================
|
| --- trunk/src/tools/telemetry/telemetry/core/bitmap.py (revision 243477)
|
| +++ trunk/src/tools/telemetry/telemetry/core/bitmap.py (working copy)
|
| @@ -51,7 +51,6 @@
|
| self._height = height
|
| self._pixels = pixels
|
| self._metadata = metadata or {}
|
| - self._crop_box = None
|
|
|
| @property
|
| def bpp(self):
|
| @@ -61,36 +60,16 @@
|
| @property
|
| def width(self):
|
| """Width of the bitmap."""
|
| - if self._crop_box:
|
| - return self._crop_box[2]
|
| return self._width
|
|
|
| @property
|
| def height(self):
|
| """Height of the bitmap."""
|
| - if self._crop_box:
|
| - return self._crop_box[3]
|
| return self._height
|
|
|
| @property
|
| - def _as_tuple(self):
|
| - # If we got a list of ints, we need to convert it into a byte buffer.
|
| - pixels = self._pixels
|
| - if type(pixels) is not bytearray:
|
| - pixels = bytearray(pixels)
|
| - if type(pixels) is not bytes:
|
| - pixels = bytes(pixels)
|
| - crop_box = self._crop_box or (0, 0, self._width, self._height)
|
| - return pixels, self._width, self._bpp, crop_box
|
| -
|
| - @property
|
| def pixels(self):
|
| """Flat pixel array of the bitmap."""
|
| - if self._crop_box:
|
| - from telemetry.core import bitmaptools
|
| - self._pixels = bitmaptools.Crop(self._as_tuple)
|
| - _, _, self._width, self._height = self._crop_box
|
| - self._crop_box = None
|
| if type(self._pixels) is not bytearray:
|
| self._pixels = bytearray(self._pixels)
|
| return self._pixels
|
| @@ -104,13 +83,12 @@
|
|
|
| def GetPixelColor(self, x, y):
|
| """Returns a RgbaColor for the pixel at (x, y)."""
|
| - pixels = self.pixels
|
| base = self._bpp * (y * self._width + x)
|
| if self._bpp == 4:
|
| - return RgbaColor(pixels[base + 0], pixels[base + 1],
|
| - pixels[base + 2], pixels[base + 3])
|
| - return RgbaColor(pixels[base + 0], pixels[base + 1],
|
| - pixels[base + 2])
|
| + return RgbaColor(self._pixels[base + 0], self._pixels[base + 1],
|
| + self._pixels[base + 2], self._pixels[base + 3])
|
| + return RgbaColor(self._pixels[base + 0], self._pixels[base + 1],
|
| + self._pixels[base + 2])
|
|
|
| def WritePngFile(self, path):
|
| with open(path, "wb") as f:
|
| @@ -131,12 +109,25 @@
|
| return Bitmap.FromPng(base64.b64decode(base64_png))
|
|
|
| def IsEqual(self, other, tolerance=0):
|
| - """Determines whether two Bitmaps are identical within a given tolerance.
|
| - Ignores alpha channel."""
|
| - from telemetry.core import bitmaptools
|
| - # pylint: disable=W0212
|
| - return bitmaptools.Equal(self._as_tuple, other._as_tuple, tolerance)
|
| + """Determines whether two Bitmaps are identical within a given tolerance."""
|
|
|
| + # Dimensions must be equal
|
| + if self.width != other.width or self.height != other.height:
|
| + return False
|
| +
|
| + # Loop over each pixel and test for equality
|
| + if tolerance or self.bpp != other.bpp:
|
| + for y in range(self.height):
|
| + for x in range(self.width):
|
| + c0 = self.GetPixelColor(x, y)
|
| + c1 = other.GetPixelColor(x, y)
|
| + if not c0.IsEqual(c1, tolerance):
|
| + return False
|
| + else:
|
| + return self.pixels == other.pixels
|
| +
|
| + return True
|
| +
|
| def Diff(self, other):
|
| """Returns a new Bitmap that represents the difference between this image
|
| and another Bitmap."""
|
| @@ -178,28 +169,55 @@
|
| return diff
|
|
|
| def GetBoundingBox(self, color, tolerance=0):
|
| - """Finds the minimum box surrounding all occurences of |color|.
|
| - Returns: (top, left, width, height), match_count
|
| - Ignores the alpha channel."""
|
| - from telemetry.core import bitmaptools
|
| - int_color = (color.r << 16) | (color.g << 8) | color.b
|
| - return bitmaptools.BoundingBox(self._as_tuple, int_color, tolerance)
|
| + """Returns a (top, left, width, height) tuple of the minimum box
|
| + surrounding all occurences of |color|."""
|
| + # TODO(szym): Implement this.
|
| + raise NotImplementedError("GetBoundingBox not yet implemented.")
|
|
|
| - def Crop(self, left, top, width, height):
|
| - """Crops the current bitmap down to the specified box."""
|
| - cur_box = self._crop_box or (0, 0, self._width, self._height)
|
| - cur_left, cur_top, cur_width, cur_height = cur_box
|
| + def Crop(self, top, left, width, height):
|
| + """Crops the current bitmap down to the specified box.
|
|
|
| + TODO(szym): Make this O(1).
|
| + """
|
| if (left < 0 or top < 0 or
|
| - (left + width) > cur_width or
|
| - (top + height) > cur_height):
|
| + (left + width) > self.width or
|
| + (top + height) > self.height):
|
| raise ValueError('Invalid dimensions')
|
|
|
| - self._crop_box = cur_left + left, cur_top + top, width, height
|
| + img_data = [[0 for x in xrange(width * self.bpp)]
|
| + for y in xrange(height)]
|
| +
|
| + # Copy each pixel in the sub-rect.
|
| + # TODO(tonyg): Make this faster by avoiding the copy and artificially
|
| + # restricting the dimensions.
|
| + for y in range(height):
|
| + for x in range(width):
|
| + c = self.GetPixelColor(x + left, y + top)
|
| + offset = x * self.bpp
|
| + img_data[y][offset] = c.r
|
| + img_data[y][offset + 1] = c.g
|
| + img_data[y][offset + 2] = c.b
|
| + if self.bpp == 4:
|
| + img_data[y][offset + 3] = c.a
|
| +
|
| + # This particular method can only save to a file, so the result will be
|
| + # written into an in-memory buffer and read back into a Bitmap
|
| + crop_img = png.from_array(img_data, mode='RGBA' if self.bpp == 4 else 'RGB')
|
| + output = cStringIO.StringIO()
|
| + try:
|
| + crop_img.save(output)
|
| + width, height, pixels, meta = png.Reader(
|
| + bytes=output.getvalue()).read_flat()
|
| + self._width = width
|
| + self._height = height
|
| + self._pixels = pixels
|
| + self._metadata = meta
|
| + finally:
|
| + output.close()
|
| +
|
| return self
|
|
|
| def ColorHistogram(self):
|
| - """Computes a histogram of the pixel colors in this Bitmap.
|
| - Returns a list of 3x256 integers."""
|
| - from telemetry.core import bitmaptools
|
| - return bitmaptools.Histogram(self._as_tuple)
|
| + """Returns a histogram of the pixel colors in this Bitmap."""
|
| + # TODO(szym): Implement this.
|
| + raise NotImplementedError("ColorHistogram not yet implemented.")
|
|
|