Exemple #1
0
 def combine_color_needs(self, target, source):
     """Combine by filling in null elements. Raise an error if full."""
     for a in source:
         if a == NULL:
             return
         for k, b in enumerate(target):
             if a == b:
                 break
             elif b == NULL:
                 target[k] = a
                 break
         else:
             raise errors.PaletteOverflowError(is_block=True)
Exemple #2
0
    def process_tile(self, tile_y, tile_x, subtile_y, subtile_x):
        """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.ColorNotAllowedError(
                            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
Exemple #3
0
 def tile_palette_fault(self, tile_y, tile_x):
     raise errors.PaletteOverflowError(tile_y, tile_x)