def get_nes_color(self, y, x): """Get the nes color corresponding to the pixel at position y,x.""" p = self.pixels[x, y] color_val = (p[0] << 16) + (p[1] << 8) + p[2] if color_val in rgb.RGB_XLAT: return rgb.RGB_XLAT[color_val] else: nc = self.components_to_nescolor(p[0], p[1], p[2]) if nc == -1: raise errors.CouldntConvertRGB(p, y / 8, x / 8, y % 8, x % 8) return nc
def build_tile_from_pixels_ignoring_unknown(self, tile_pixels, popt): pixels = tile_pixels.load() tile = chr_data.ChrTile() for row in range(8): for col in range(8): i = row * 8 + col p = pixels[col, row] color_val = (p[0] << 16) + (p[1] << 8) + p[2] if color_val in rgb.RGB_XLAT: nc = rgb.RGB_XLAT[color_val] else: nc = self.components_to_nescolor(p[0], p[1], p[2]) if nc == -1: raise errors.CouldntConvertRGB(p, tile_y, tile_x, i, j) try: val = popt.index(nc) except ValueError: val = 0 tile.put_pixel(row, col, val) return tile
def process_tile(self, tile_y, tile_x, subtile_y=0, subtile_x=0): """Process the tile and save artifact information. Process the tile to obtain its color needs and dot profile, verifying that the tile contains colors that match the system palette, and does not contain too many colors. This method is called many times for an image, so it contains a lot of micro-optimizations. The image should have already been loaded using self.load_image. Return the color_needs and dot_profile. tile_y: The y position of the tile, 0..31. tile_x: The x position of the tile, 0..29. subtile_y: Pixel y offset within the tile. subtile_x: Pixel x offset within the tile. """ pixel_y = tile_y * TILE_SIZE + subtile_y pixel_x = tile_x * TILE_SIZE + subtile_x color_needs = bytearray([NULL, NULL, NULL, NULL]) dot_profile = bytearray(TILE_SIZE * TILE_SIZE) # Check if this tile overruns the image. if pixel_y + TILE_SIZE > self.image_y or pixel_x + TILE_SIZE > self.image_x: return color_needs, dot_profile # Get local variables for frequently accessed data. This improves # performance. 'xlat' is mutated whenever 'components_to_nescolor_func' is # called. ps = self.pixels xlat = rgb.RGB_XLAT components_to_nescolor_func = self.components_to_nescolor for i in xrange(TILE_SIZE): row = i * TILE_SIZE for j in xrange(TILE_SIZE): # Inlined call to get_nes_color(pixel_y, pixel_x) to get nc. p = ps[pixel_x + j, pixel_y + i] color_val = (p[0] << 16) + (p[1] << 8) + p[2] if color_val in xlat: nc = xlat[color_val] else: nc = components_to_nescolor_func(p[0], p[1], p[2]) if nc == -1: raise errors.CouldntConvertRGB(p, tile_y, tile_x, i, j) # Add the nescolor 'nc' to the 'color_needs'. Insert it into the first # position that is equal to NULL, otherwise raise an error. Loop is # unrolled for performance. while True: idx = 0 if color_needs[idx] == nc: break elif color_needs[idx] == NULL: color_needs[idx] = nc break idx = 1 if color_needs[idx] == nc: break elif color_needs[idx] == NULL: color_needs[idx] = nc break idx = 2 if color_needs[idx] == nc: break elif color_needs[idx] == NULL: color_needs[idx] = nc break idx = 3 if color_needs[idx] == nc: break elif color_needs[idx] == NULL: color_needs[idx] = nc break raise errors.PaletteOverflowError(tile_y, tile_x) dot_profile[row + j] = idx return color_needs, dot_profile