void graphics_draw_pixel_color(GBitmap *bitmap, GPoint point, GColor color) { uint16_t row_size_bytes = gbitmap_get_bytes_per_row(bitmap); uint8_t *imagebuffer = gbitmap_get_data(bitmap); GRect bounds = gbitmap_get_bounds(bitmap); if (grect_contains_point(&bounds, &point)) { uint8_t *line = imagebuffer + (row_size_bytes * point.y); line[point.x] = color.argb; } }
/** * Flood fill algorithm : http://en.wikipedia.org/wiki/Flood_fill * TO BE IMPROVED to reduce memory consumption */ static void floodFill(GBitmap* bitmap, uint8_t* pixels, int bytes_per_row, GPoint start, GPoint offset, GColor8 fill_color){ uint8_t* img_pixels = gbitmap_get_data(bitmap); GRect bounds_bmp = gbitmap_get_bounds(bitmap); int16_t w_bmp = bounds_bmp.size.w; uint32_t max_size = 1000; GPoint *queue = malloc(sizeof(GPoint) * max_size); uint32_t size = 0; int32_t x = start.x - offset.x; int32_t y = start.y - offset.y; queue[size++] = (GPoint){x, y}; int32_t w,e; while(size > 0) { size--; x = queue[size].x; y = queue[size].y; w = e = x; while(!get_pixel_(pixels, bytes_per_row, e, y)) e++; while(w>=0 && !get_pixel_(pixels, bytes_per_row, w, y)) w--; // Increase the size of the queue if needed if(size > (max_size - 2*(e-w))){ max_size += 1000; GPoint *tmp_queue = malloc(sizeof(GPoint) * max_size); memcpy(tmp_queue, queue, sizeof(GPoint) * size); free(queue); queue = tmp_queue; } for(x=w+1; x<e; x++) { // change the color of the pixel in the final image if(grect_contains_point(&bounds_bmp,&((GPoint){x + offset.x, y + offset.y}))) img_pixels[x + offset.x + w_bmp * (y + offset.y)] = fill_color.argb; set_pixel_(pixels, bytes_per_row, x, y); if(!get_pixel_(pixels, bytes_per_row, x, y+1)){ queue[size++] = (GPoint){x, y+1}; } if(!get_pixel_(pixels, bytes_per_row, x, y-1)){ queue[size++] = (GPoint){x, y-1}; } } } free(queue); }