inline bool color_equal<GrayscaleTraits>(color_t c1, color_t c2, int tolerance) { return color_equal_16(c1, c2, tolerance); }
/* flooder: * Fills a horizontal line around the specified position, and adds it * to the list of drawn segments. Returns the first x coordinate after * the part of the line which it has dealt with. */ static int flooder(Image *image, int x, int y, const gfx::Rect& bounds, color_t src_color, int tolerance, void *data, AlgoHLine proc) { FLOODED_LINE *p; int left = 0, right = 0; int c; switch (image->pixelFormat()) { case IMAGE_RGB: { uint32_t* address = reinterpret_cast<uint32_t*>(image->getPixelAddress(0, y)); // Check start pixel if (!color_equal_32((int)*(address+x), src_color, tolerance)) return x+1; // Work left from starting point for (left=x-1; left>=bounds.x; left--) { if (!color_equal_32((int)*(address+left), src_color, tolerance)) break; } // Work right from starting point for (right=x+1; right<bounds.x2(); right++) { if (!color_equal_32((int)*(address+right), src_color, tolerance)) break; } } break; case IMAGE_GRAYSCALE: { uint16_t* address = reinterpret_cast<uint16_t*>(image->getPixelAddress(0, y)); // Check start pixel if (!color_equal_16((int)*(address+x), src_color, tolerance)) return x+1; // Work left from starting point for (left=x-1; left>=bounds.x; left--) { if (!color_equal_16((int)*(address+left), src_color, tolerance)) break; } // Work right from starting point for (right=x+1; right<bounds.x2(); right++) { if (!color_equal_16((int)*(address+right), src_color, tolerance)) break; } } break; case IMAGE_INDEXED: { uint8_t* address = image->getPixelAddress(0, y); // Check start pixel if (!color_equal_8((int)*(address+x), src_color, tolerance)) return x+1; // Work left from starting point for (left=x-1; left>=bounds.x; left--) { if (!color_equal_8((int)*(address+left), src_color, tolerance)) break; } // Work right from starting point for (right=x+1; right<bounds.x2(); right++) { if (!color_equal_8((int)*(address+right), src_color, tolerance)) break; } } break; default: // Check start pixel if (get_pixel(image, x, y) != src_color) return x+1; // Work left from starting point for (left=x-1; left>=bounds.x; left--) { if (get_pixel(image, left, y) != src_color) break; } // Work right from starting point for (right=x+1; right<bounds.x2(); right++) { if (get_pixel(image, right, y) != src_color) break; } break; } left++; right--; /* draw the line */ (*proc)(left, y, right, data); /* store it in the list of flooded segments */ c = y; p = FLOOD_LINE(c); if (p->flags) { while (p->next) { c = p->next; p = FLOOD_LINE(c); } p->next = c = flood_count++; flood_buf.resize(flood_count); p = FLOOD_LINE(c); } p->flags = FLOOD_IN_USE; p->lpos = left; p->rpos = right; p->y = y; p->next = 0; if (y > bounds.y) p->flags |= FLOOD_TODO_ABOVE; if (y+1 < bounds.y2()) p->flags |= FLOOD_TODO_BELOW; return right+2; }
/* flooder: * Fills a horizontal line around the specified position, and adds it * to the list of drawn segments. Returns the first x coordinate after * the part of the line which it has dealt with. */ static int flooder (Image *image, int x, int y, int src_color, int tolerance, void *data, AlgoHLine proc) { FLOODED_LINE *p; int left = 0, right = 0; int c; switch (image->getPixelFormat()) { case IMAGE_RGB: { uint32_t* address = ((uint32_t**)image->line)[y]; /* check start pixel */ if (!color_equal_32((int)*(address+x), src_color, tolerance)) return x+1; /* work left from starting point */ for (left=x-1; left>=0; left--) { if (!color_equal_32((int)*(address+left), src_color, tolerance)) break; } /* work right from starting point */ for (right=x+1; right<image->w; right++) { if (!color_equal_32((int)*(address+right), src_color, tolerance)) break; } } break; case IMAGE_GRAYSCALE: { uint16_t* address = ((uint16_t**)image->line)[y]; /* check start pixel */ if (!color_equal_16((int)*(address+x), src_color, tolerance)) return x+1; /* work left from starting point */ for (left=x-1; left>=0; left--) { if (!color_equal_16((int)*(address+left), src_color, tolerance)) break; } /* work right from starting point */ for (right=x+1; right<image->w; right++) { if (!color_equal_16((int)*(address+right), src_color, tolerance)) break; } } break; case IMAGE_INDEXED: { uint8_t* address = ((uint8_t**)image->line)[y]; /* check start pixel */ if (!color_equal_8((int)*(address+x), src_color, tolerance)) return x+1; /* work left from starting point */ for (left=x-1; left>=0; left--) { if (!color_equal_8((int)*(address+left), src_color, tolerance)) break; } /* work right from starting point */ for (right=x+1; right<image->w; right++) { if (!color_equal_8((int)*(address+right), src_color, tolerance)) break; } } break; default: /* check start pixel */ if (image_getpixel(image, x, y) != src_color) return x+1; /* work left from starting point */ for (left=x-1; left>=0; left--) { if (image_getpixel(image, left, y) != src_color) break; } /* work right from starting point */ for (right=x+1; right<image->w; right++) { if (image_getpixel(image, right, y) != src_color) break; } break; } left++; right--; /* draw the line */ (*proc)(left, y, right, data); /* store it in the list of flooded segments */ c = y; p = FLOOD_LINE(c); if (p->flags) { while (p->next) { c = p->next; p = FLOOD_LINE(c); } p->next = c = flood_count++; _grow_scratch_mem(sizeof(FLOODED_LINE) * flood_count); p = FLOOD_LINE(c); } p->flags = FLOOD_IN_USE; p->lpos = left; p->rpos = right; p->y = y; p->next = 0; if (y > 0) p->flags |= FLOOD_TODO_ABOVE; if (y+1 < image->h) p->flags |= FLOOD_TODO_BELOW; return right+2; }