def parse(raw_data: bytes, width: int, height: int, colors: Colors, image_config: ImageConfig,
           room_numbers: List[int]) \
         -> Tuple[ImageType, Dict[int, Tuple[int, int, int, int]]]:
     rooms = {}
     scale = image_config[CONF_SCALE]
     trim_left = int(image_config[CONF_TRIM][CONF_LEFT] * width / 100)
     trim_right = int(image_config[CONF_TRIM][CONF_RIGHT] * width / 100)
     trim_top = int(image_config[CONF_TRIM][CONF_TOP] * height / 100)
     trim_bottom = int(image_config[CONF_TRIM][CONF_BOTTOM] * height / 100)
     trimmed_height = height - trim_top - trim_bottom
     trimmed_width = width - trim_left - trim_right
     if trimmed_width == 0 or trimmed_height == 0:
         return ImageHandler.create_empty_map_image(colors), rooms
     image = Image.new('RGBA', (trimmed_width, trimmed_height))
     pixels = image.load()
     unknown_pixels = set()
     for img_y in range(trimmed_height):
         for img_x in range(trimmed_width):
             pixel_type = raw_data[img_x + trim_left + width * (img_y + trim_bottom)]
             x = img_x
             y = trimmed_height - 1 - img_y
             if pixel_type == ImageHandlerRoidmi.MAP_OUTSIDE:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_MAP_OUTSIDE, colors)
             elif pixel_type == ImageHandlerRoidmi.MAP_WALL:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_MAP_WALL_V2, colors)
             elif pixel_type == ImageHandlerRoidmi.MAP_UNKNOWN:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_UNKNOWN, colors)
             elif pixel_type in room_numbers:
                 room_x = img_x + trim_left
                 room_y = img_y + trim_bottom
                 room_number = pixel_type
                 if room_number not in rooms:
                     rooms[room_number] = (room_x, room_y, room_x, room_y)
                 else:
                     rooms[room_number] = (min(rooms[room_number][0], room_x),
                                           min(rooms[room_number][1], room_y),
                                           max(rooms[room_number][2], room_x),
                                           max(rooms[room_number][3], room_y))
                 default = ImageHandler.ROOM_COLORS[room_number % len(ImageHandler.ROOM_COLORS)]
                 pixels[x, y] = ImageHandler.__get_color__(f"{COLOR_ROOM_PREFIX}{room_number}", colors, default)
             else:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_UNKNOWN, colors)
                 unknown_pixels.add(pixel_type)
     if image_config["scale"] != 1 and trimmed_width != 0 and trimmed_height != 0:
         image = image.resize((int(trimmed_width * scale), int(trimmed_height * scale)), resample=Image.NEAREST)
     if len(unknown_pixels) > 0:
         _LOGGER.warning('unknown pixel_types: %s', unknown_pixels)
     return image, rooms
예제 #2
0
 def parse(buf: ParsingBuffer, width: int, height: int, colors: Colors, image_config: ImageConfig,
           draw_cleaned_area: bool) \
         -> Tuple[ImageType, Dict[int, Tuple[int, int, int, int]], Set[int], Optional[ImageType]]:
     rooms = {}
     cleaned_areas = set()
     scale = image_config[CONF_SCALE]
     trim_left = int(image_config[CONF_TRIM][CONF_LEFT] * width / 100)
     trim_right = int(image_config[CONF_TRIM][CONF_RIGHT] * width / 100)
     trim_top = int(image_config[CONF_TRIM][CONF_TOP] * height / 100)
     trim_bottom = int(image_config[CONF_TRIM][CONF_BOTTOM] * height / 100)
     trimmed_height = height - trim_top - trim_bottom
     trimmed_width = width - trim_left - trim_right
     if trimmed_width == 0 or trimmed_height == 0:
         return ImageHandler.create_empty_map_image(colors), rooms, cleaned_areas, None
     image = Image.new('RGBA', (trimmed_width, trimmed_height))
     pixels = image.load()
     cleaned_areas_layer = None
     cleaned_areas_pixels = None
     if draw_cleaned_area:
         cleaned_areas_layer = Image.new('RGBA', (trimmed_width, trimmed_height))
         cleaned_areas_pixels = cleaned_areas_layer.load()
     buf.skip('trim_bottom', trim_bottom * width)
     unknown_pixels = set()
     for img_y in range(trimmed_height):
         buf.skip('trim_left', trim_left)
         for img_x in range(trimmed_width):
             pixel_type = buf.get_uint8('pixel')
             x = img_x
             y = trimmed_height - 1 - img_y
             if pixel_type == ImageHandlerViomi.MAP_OUTSIDE:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_MAP_OUTSIDE, colors)
             elif pixel_type == ImageHandlerViomi.MAP_WALL:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_MAP_WALL_V2, colors)
             elif pixel_type == ImageHandlerViomi.MAP_SCAN:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_SCAN, colors)
             elif pixel_type == ImageHandlerViomi.MAP_NEW_DISCOVERED_AREA:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_NEW_DISCOVERED_AREA, colors)
             elif ImageHandlerViomi.MAP_ROOM_MIN <= pixel_type <= ImageHandlerViomi.MAP_SELECTED_ROOM_MAX:
                 room_x = img_x + trim_left
                 room_y = img_y + trim_bottom
                 if pixel_type < ImageHandlerViomi.MAP_SELECTED_ROOM_MIN:
                     room_number = pixel_type
                 else:
                     room_number = pixel_type - ImageHandlerViomi.MAP_SELECTED_ROOM_MIN + ImageHandlerViomi.MAP_ROOM_MIN
                     cleaned_areas.add(room_number)
                     if draw_cleaned_area:
                         cleaned_areas_pixels[x, y] = ImageHandler.__get_color__(COLOR_CLEANED_AREA, colors)
                 if room_number not in rooms:
                     rooms[room_number] = (room_x, room_y, room_x, room_y)
                 else:
                     rooms[room_number] = (min(rooms[room_number][0], room_x),
                                           min(rooms[room_number][1], room_y),
                                           max(rooms[room_number][2], room_x),
                                           max(rooms[room_number][3], room_y))
                 default = ImageHandler.ROOM_COLORS[room_number % len(ImageHandler.ROOM_COLORS)]
                 pixels[x, y] = ImageHandler.__get_color__(f"{COLOR_ROOM_PREFIX}{room_number}", colors, default)
             else:
                 pixels[x, y] = ImageHandler.__get_color__(COLOR_UNKNOWN, colors)
                 unknown_pixels.add(pixel_type)
         buf.skip('trim_right', trim_right)
     buf.skip('trim_top', trim_top * width)
     if image_config["scale"] != 1 and trimmed_width != 0 and trimmed_height != 0:
         image = image.resize((int(trimmed_width * scale), int(trimmed_height * scale)), resample=Image.NEAREST)
         if draw_cleaned_area:
             cleaned_areas_layer = cleaned_areas_layer.resize(
                 (int(trimmed_width * scale), int(trimmed_height * scale)), resample=Image.NEAREST)
     if len(unknown_pixels) > 0:
         _LOGGER.warning('unknown pixel_types: %s', unknown_pixels)
     return image, rooms, cleaned_areas, cleaned_areas_layer
예제 #3
0
 def draw_elements(colors, drawables, sizes, map_data: MapData,
                   image_config):
     scale = float(image_config[CONF_SCALE])
     for drawable in drawables:
         if DRAWABLE_CHARGER == drawable and map_data.charger is not None:
             ImageHandler.draw_charger(map_data.image, map_data.charger,
                                       sizes, colors)
         if DRAWABLE_VACUUM_POSITION == drawable and map_data.vacuum_position is not None:
             ImageHandler.draw_vacuum_position(map_data.image,
                                               map_data.vacuum_position,
                                               sizes, colors)
         if DRAWABLE_OBSTACLES == drawable and map_data.obstacles is not None:
             ImageHandler.draw_obstacles(map_data.image, map_data.obstacles,
                                         sizes, colors)
         if DRAWABLE_IGNORED_OBSTACLES == drawable and map_data.ignored_obstacles is not None:
             ImageHandler.draw_ignored_obstacles(map_data.image,
                                                 map_data.ignored_obstacles,
                                                 sizes, colors)
         if DRAWABLE_OBSTACLES_WITH_PHOTO == drawable and map_data.obstacles_with_photo is not None:
             ImageHandler.draw_obstacles_with_photo(
                 map_data.image, map_data.obstacles_with_photo, sizes,
                 colors)
         if DRAWABLE_IGNORED_OBSTACLES_WITH_PHOTO == drawable and map_data.ignored_obstacles_with_photo is not None:
             ImageHandler.draw_ignored_obstacles_with_photo(
                 map_data.image, map_data.ignored_obstacles_with_photo,
                 sizes, colors)
         if DRAWABLE_PATH == drawable and map_data.path is not None:
             ImageHandler.draw_path(map_data.image, map_data.path, colors,
                                    scale)
         if DRAWABLE_GOTO_PATH == drawable and map_data.goto_path is not None:
             ImageHandler.draw_goto_path(map_data.image, map_data.goto_path,
                                         colors, scale)
         if DRAWABLE_PREDICTED_PATH == drawable and map_data.predicted_path is not None:
             ImageHandler.draw_predicted_path(map_data.image,
                                              map_data.predicted_path,
                                              colors, scale)
         if DRAWABLE_NO_GO_AREAS == drawable and map_data.no_go_areas is not None:
             ImageHandler.draw_no_go_areas(map_data.image,
                                           map_data.no_go_areas, colors)
         if DRAWABLE_NO_MOPPING_AREAS == drawable and map_data.no_mopping_areas is not None:
             ImageHandler.draw_no_mopping_areas(map_data.image,
                                                map_data.no_mopping_areas,
                                                colors)
         if DRAWABLE_VIRTUAL_WALLS == drawable and map_data.walls is not None:
             ImageHandler.draw_walls(map_data.image, map_data.walls, colors)
         if DRAWABLE_ZONES == drawable and map_data.zones is not None:
             ImageHandler.draw_zones(map_data.image, map_data.zones, colors)
         if DRAWABLE_CLEANED_AREA == drawable and DRAWABLE_CLEANED_AREA in map_data.image.additional_layers:
             ImageHandler.draw_layer(map_data.image, drawable)
예제 #4
0
 def create_empty(colors) -> MapData:
     map_data = MapData()
     empty_map = ImageHandler.create_empty_map_image(
         colors, "Vacuum not supported")
     map_data.image = ImageData.create_empty(empty_map)
     return map_data
 def create_empty(colors, text) -> MapData:
     map_data = MapData()
     empty_map = ImageHandler.create_empty_map_image(colors, text)
     map_data.image = ImageData.create_empty(empty_map)
     return map_data
 def parse(raw_data: bytes, width: int, height: int, colors: Colors,
           image_config: ImageConfig) -> Tuple[ImageType, dict]:
     rooms = {}
     scale = image_config[CONF_SCALE]
     trim_left = int(image_config[CONF_TRIM][CONF_LEFT] * width / 100)
     trim_right = int(image_config[CONF_TRIM][CONF_RIGHT] * width / 100)
     trim_top = int(image_config[CONF_TRIM][CONF_TOP] * height / 100)
     trim_bottom = int(image_config[CONF_TRIM][CONF_BOTTOM] * height / 100)
     trimmed_height = height - trim_top - trim_bottom
     trimmed_width = width - trim_left - trim_right
     image = Image.new('RGBA', (trimmed_width, trimmed_height))
     if width == 0 or height == 0:
         return ImageHandler.create_empty_map_image(colors), {}
     pixels = image.load()
     for img_y in range(trimmed_height):
         for img_x in range(trimmed_width):
             pixel_type = raw_data[img_x + trim_left + width *
                                   (img_y + trim_bottom)]
             x = img_x
             y = trimmed_height - img_y - 1
             if pixel_type == ImageHandlerXiaomi.MAP_OUTSIDE:
                 pixels[x, y] = ImageHandler.__get_color__(
                     COLOR_MAP_OUTSIDE, colors)
             elif pixel_type == ImageHandlerXiaomi.MAP_WALL:
                 pixels[x, y] = ImageHandler.__get_color__(
                     COLOR_MAP_WALL, colors)
             elif pixel_type == ImageHandlerXiaomi.MAP_INSIDE:
                 pixels[x, y] = ImageHandler.__get_color__(
                     COLOR_MAP_INSIDE, colors)
             elif pixel_type == ImageHandlerXiaomi.MAP_SCAN:
                 pixels[x,
                        y] = ImageHandler.__get_color__(COLOR_SCAN, colors)
             else:
                 obstacle = pixel_type & 0x07
                 if obstacle == 0:
                     pixels[x, y] = ImageHandler.__get_color__(
                         COLOR_GREY_WALL, colors)
                 elif obstacle == 1:
                     pixels[x, y] = ImageHandler.__get_color__(
                         COLOR_MAP_WALL_V2, colors)
                 elif obstacle == 7:
                     room_number = (pixel_type & 0xFF) >> 3
                     room_x = img_x + trim_left
                     room_y = img_y + trim_bottom
                     if room_number not in rooms:
                         rooms[room_number] = (room_x, room_y, room_x,
                                               room_y)
                     else:
                         rooms[room_number] = (min(rooms[room_number][0],
                                                   room_x),
                                               min(rooms[room_number][1],
                                                   room_y),
                                               max(rooms[room_number][2],
                                                   room_x),
                                               max(rooms[room_number][3],
                                                   room_y))
                     default = ImageHandler.ROOM_COLORS[room_number >> 1]
                     pixels[x, y] = ImageHandler.__get_color__(
                         f"{COLOR_ROOM_PREFIX}{room_number}", colors,
                         default)
                 else:
                     pixels[x, y] = ImageHandler.__get_color__(
                         COLOR_UNKNOWN, colors)
     if image_config["scale"] != 1 and width != 0 and height != 0:
         image = image.resize(
             (int(trimmed_width * scale), int(trimmed_height * scale)),
             resample=Image.NEAREST)
     return image, rooms
예제 #7
0
    def parse(raw_data: bytes, header, colors, image_config,
              map_data_type: str) -> Tuple[ImageType, Dict[int, Room]]:
        scale = image_config[CONF_SCALE]
        trim_left = int(image_config[CONF_TRIM][CONF_LEFT] *
                        header.image_width / 100)
        trim_right = int(image_config[CONF_TRIM][CONF_RIGHT] *
                         header.image_width / 100)
        trim_top = int(image_config[CONF_TRIM][CONF_TOP] *
                       header.image_height / 100)
        trim_bottom = int(image_config[CONF_TRIM][CONF_BOTTOM] *
                          header.image_height / 100)
        trimmed_height = header.image_height - trim_top - trim_bottom
        trimmed_width = header.image_width - trim_left - trim_right
        image = Image.new('RGBA', (trimmed_width, trimmed_height))
        if header.image_width == 0 or header.image_height == 0:
            return ImageHandler.create_empty_map_image(colors), {}
        pixels = image.load()
        rooms = {}

        for img_y in range(trimmed_height):
            for img_x in range(trimmed_width):
                x = img_x
                y = trimmed_height - img_y - 1
                room_x = img_x + trim_left
                room_y = img_y + trim_bottom

                # TODO : use MapDataParserDreame.MapDataTypes enum
                if map_data_type == "regular":
                    px = raw_data[img_x + trim_left + header.image_width *
                                  (img_y + trim_bottom)]
                    segment_id = px >> 2
                    if 0 < segment_id < 62:
                        if segment_id not in rooms:
                            rooms[segment_id] = Room(segment_id, room_x,
                                                     room_y, room_x, room_y)
                        rooms[segment_id] = Room(
                            segment_id, min(rooms[segment_id].x0, room_x),
                            min(rooms[segment_id].y0, room_y),
                            max(rooms[segment_id].x1, room_x),
                            max(rooms[segment_id].y1, room_y))
                        default = ImageHandler.ROOM_COLORS[segment_id >> 1]
                        pixels[x, y] = ImageHandler.__get_color__(
                            f"{COLOR_ROOM_PREFIX}{segment_id}", colors,
                            default)
                    else:
                        masked_px = px & 0b00000011

                        if masked_px == ImageHandlerDreame.PixelTypes.NONE:
                            pixels[x, y] = ImageHandler.__get_color__(
                                COLOR_MAP_OUTSIDE, colors)
                        elif masked_px == ImageHandlerDreame.PixelTypes.FLOOR:
                            pixels[x, y] = ImageHandler.__get_color__(
                                COLOR_MAP_INSIDE, colors)
                        elif masked_px == ImageHandlerDreame.PixelTypes.WALL:
                            pixels[x, y] = ImageHandler.__get_color__(
                                COLOR_MAP_WALL, colors)
                        else:
                            _LOGGER.warning(f'unhandled pixel type: {px}')
                elif map_data_type == "rism":
                    px = raw_data[img_x + trim_left + header.image_width *
                                  (img_y + trim_bottom)]
                    segment_id = px & 0b01111111
                    wall_flag = px >> 7

                    if wall_flag:
                        pixels[x, y] = ImageHandler.__get_color__(
                            COLOR_MAP_WALL, colors)
                    elif segment_id > 0:
                        if segment_id not in rooms:
                            rooms[segment_id] = Room(segment_id, room_x,
                                                     room_y, room_x, room_y)
                        rooms[segment_id] = Room(
                            segment_id, min(rooms[segment_id].x0, room_x),
                            min(rooms[segment_id].y0, room_y),
                            max(rooms[segment_id].x1, room_x),
                            max(rooms[segment_id].y1, room_y))
                        default = ImageHandler.ROOM_COLORS[segment_id >> 1]
                        pixels[x, y] = ImageHandler.__get_color__(
                            f"{COLOR_ROOM_PREFIX}{segment_id}", colors,
                            default)

        if image_config[
                "scale"] != 1 and header.image_width != 0 and header.image_height != 0:
            image = image.resize(
                (int(trimmed_width * scale), int(trimmed_height * scale)),
                resample=Image.NEAREST)
        return image, rooms