/** * 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); }
int main(int argc, char **argv){ struct image img; read_image("/home/os/workspace/azazazaza/Debug/Untitled.png", &img); bufer_init(img.width, img.height); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowSize(img.width, img.height); glutInitWindowPosition(100, 100); wnd_id = glutCreateWindow("Image"); glClearColor (1.0, 1.0, 1.0, 0.0); glutDisplayFunc(displayFunc); glPointSize(1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)img.width, 0.0, (GLdouble)img.height); /* draw image */ //set_pixels(img.pixels, img.width * img.height); struct b8_image *grayscale = binarize_image(&img); glBegin(GL_POINTS); for(unsigned int pix = 0; pix < grayscale->width * grayscale->height; pix++){ set_pixel_(grayscale->pixels[pix].color, grayscale->pixels[pix].color, grayscale->pixels[pix].color, grayscale->pixels[pix].x, grayscale->pixels[pix].y ); } glEnd(); glFlush(); printf("OK\n"); glutMainLoop(); return 0; }
/** * From https://github.com/Jnmattern/Minimalist_2.0/blob/master/src/bitmap.h */ static void bmpDrawLine(uint8_t *pixels, int bytes_per_row, int x1, int y1, int x2, int y2) { int dx, dy, e; if ((dx = x2-x1) != 0) { if (dx > 0) { if ((dy = y2-y1) != 0) { if (dy > 0) { // vecteur oblique dans le 1er quadran if (dx >= dy) { // vecteur diagonal ou oblique proche de l’horizontale, dans le 1er octant e = dx; dx = 2*e; dy = 2*dy; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1++; if (x1 == x2) break; e -= dy; if (e < 0) { y1++; e += dx; } } } else { // vecteur oblique proche de la verticale, dans le 2nd octant e = dy; dy = 2*e; dx = 2*dx; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1++; if (y1 == y2) break; e -= dx; if (e < 0) { x1++; e += dy; } } } } else { // dy < 0 (et dx > 0) // vecteur oblique dans le 4e cadran if (dx >= -dy) { // vecteur diagonal ou oblique proche de l’horizontale, dans le 8e octant e = dx; dx = 2*e; dy = 2*dy; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1++; if (x1 == x2) break; e += dy; if (e < 0) { y1--; e += dx; } } } else { // vecteur oblique proche de la verticale, dans le 7e octant e = dy; dy = 2*e; dx = 2*dx; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1--; if (y1 == y2) break; e += dx; if (e > 0) { x1++; e += dy; } } } } } else { // dy = 0 (et dx > 0) // vecteur horizontal vers la droite while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1++; if (x1 == x2) break; } } } else { // dx < 0 if ((dy = y2-y1) != 0) { if (dy > 0) { // vecteur oblique dans le 2nd quadran if (-dx >= dy) { // vecteur diagonal ou oblique proche de l’horizontale, dans le 4e octant e = dx; dx = 2*e; dy = 2*dy; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1--; if (x1 == x2) break; e += dy; if (e >= 0) { y1++; e += dx; } } } else { // vecteur oblique proche de la verticale, dans le 3e octant e = dy; dy = 2*e; dx = 2*dx; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1++; if (y1 == y2) break; e += dx; if (e <= 0) { x1--; e += dy; } } } } else { // dy < 0 (et dx < 0) // vecteur oblique dans le 3e cadran if (dx <= dy) { // vecteur diagonal ou oblique proche de l’horizontale, dans le 5e octant e = dx; dx = 2*e; dy = 2*dy; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1--; if (x1 == x2) break; e -= dy; if (e >= 0) { y1--; e += dx; } } } else { // vecteur oblique proche de la verticale, dans le 6e octant e = dy; dy = 2*e; dx = 2*dx; while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1--; if (y1 == y2) break; e -= dx; if (e >= 0) { x1--; e += dy; } } } } } else { // dy = 0 (et dx < 0) // vecteur horizontal vers la gauche while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); x1--; if (x1 == x2) break; } } } } else { // dx = 0 if ((dy = y2-y1) != 0) { if (dy > 0) { // vecteur vertical croissant while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1++; if (y1 == y2) break; } } else { // dy < 0 (et dx = 0) // vecteur vertical décroissant while (1) { set_pixel_(pixels, bytes_per_row, x1, y1); y1--; if (y1 == y2) break; } } } } }