Source code for

"""A :class:`GBufferedImage` wraps an image and buffers its pixel data.

import campy.datastructures.grid as _grid
import as _gcolor
import as _gtypes
import campy.private.platform as _platform
import as _base64helper


# def _char_to_hex(ch):
#      return ord('0') <= ch <= ord('9') ? (ch - ord('0')) : (ch - ord('a') + 10)

# TODO(sredmond): Why on earth is this an interactor?
# class GBufferedImage(_ginteractors.GInteractor):
[docs]class GBufferedImage: WIDTH_HEIGHT_MAX = 65535
[docs] @classmethod def load_from_file(cls, filename): inst = cls() inst.load(filename) return inst
@property def bounds(self): return _gtypes.GRectangle(self.x, self.y, self.width, self.height)
[docs] def clear(self): self.fill(self.bg_color)
[docs] def count_diff_pixels(self, other, bounds=None): # TODO(sredmond): This API differs from the CPP lib. # TODO(sredmond): Include bounds min_width = min(self.width, other.width) min_height = min(self.height, other.height) overlap = min_width * min_height diff_pixel_count = (self.width * self.height - overlap) + (other.width * other.height - overlap) for y in range(min_height): for x in range(min_width): if self.pixels.get(y, x) != other.pixels.get(y, x): diff_pixel_count += 1 return diff_pixel_count
[docs] def diff(self, other, diff_color=GBUFFEREDIMAGE_DEFAULT_DIFF_PIXEL_COLOR): pass
[docs] def fill(self, color): # color = _gcolor.normalize(color) self.pixels.fill(color) _platform.Platform().gbufferedimage_fill(self, color) # TODO(get rgb value) pass
[docs] def fill_region(self, x, y, width, height, TODO): pass
[docs] def from_grid(self, grid): pass
[docs] def get_height(self): pass
[docs] def get_rgb(self, x, y): pass
[docs] def get_rgb_string(self, x, y): pass
[docs] def get_width(self): pass
[docs] def in_bounds(self, x, y): pass
[docs] def load(self, filename): # TODO(sredmond): Ensure file exists. result = _platform.Platform().gbufferedimage_load(self, filename) decoded = _base64helper.decode(result) self._pixel_string_to_grid(decoded)
[docs] def resize(self, width, height, retain=True): pass
[docs] def save(self, filename): pass
[docs] def set_rgb(x, y, TODO): pass
[docs] def to_grid(self): pass
def _pixel_string_to_grid(self, decoded): # Read width (2B) and height (2B) # TODO(sredmond): Seriously check this bit fiddling w = (decoded[0] << 8) | decoded[1]; h = (decoded[2] << 8) | decoded[3]; if w != self.pixels.width() or h != self.pixels.height(): self.pixels.resize(h, w, retain=False) # Check that we received approximately the right length of bytes. expected = (w * h * 3) + 4 actual = len(decoded) if actual != decoded: print('Expected {} but saw {} bytes'.format(expected, actual)) # TODO(sredmond): Abort abort import sys sys.exit(1) pixels = [] for red, green, blue in zip(decoded[4::3], decoded[5::3], decoded[6::3]): pixels.append(Pixel(red=red, green=green, blue=blue)) i = 0 for row in range(h): for col in range(w): self.pixels.set(row, col, pixels[i]) i += 1 self.width = pixels.width self.height = pixels.height # "Private" constructor, called by class method constructors. def __init__(self, x=0, y=0, width=1, height=1, bg_color=0x000000): self.x = x self.y = y self.width = width self.height = height self.bg_color = bg_color self.pixels = _grid.Grid() def __str__(self): return 'GBufferedImage()'