[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60372] branches/soc-2013-paint: Modify fill tool to be adaptive.
Antony Riakiotakis
kalast at gmail.com
Wed Sep 25 22:58:54 CEST 2013
Revision: 60372
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60372
Author: psy-fi
Date: 2013-09-25 20:58:53 +0000 (Wed, 25 Sep 2013)
Log Message:
-----------
Modify fill tool to be adaptive. It uses a fill threshold to spread from
the mouse position outwards to colors similar to the initial one. I'm
not entirely sure about the threshold algorithm, but it is a solid base
that can be improved upon.
Only byte images working for now, float images coming next.
Modified Paths:
--------------
branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py
branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c
branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_2d.c
branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h
branches/soc-2013-paint/source/blender/makesdna/DNA_brush_types.h
branches/soc-2013-paint/source/blender/makesrna/intern/rna_brush.c
Modified: branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py
===================================================================
--- branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py 2013-09-25 20:28:49 UTC (rev 60371)
+++ branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py 2013-09-25 20:58:53 UTC (rev 60372)
@@ -770,11 +770,14 @@
col.separator()
col.prop(brush, "blur_mode")
- if brush.image_tool == 'CLONE':
+ elif brush.image_tool == 'CLONE':
col.separator()
col.prop(brush, "clone_image", text="Image")
col.prop(brush, "clone_alpha", text="Alpha")
-
+
+ elif brush.image_tool == 'FILL':
+ col.prop(brush, "fill_threshold")
+
row = col.row(align=True)
if capabilities.has_space_attenuation:
Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c 2013-09-25 20:28:49 UTC (rev 60371)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c 2013-09-25 20:58:53 UTC (rev 60372)
@@ -823,7 +823,7 @@
float color[3];
srgb_to_linearrgb_v3_v3(color, brush->rgb);
- paint_2d_bucket_fill(C, color, brush->alpha);
+ paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
}
else {
paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, 1.0, 0.0);
@@ -1436,7 +1436,7 @@
undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
image_undo_restore, image_undo_free);
- paint_2d_bucket_fill(C, color, 1.0);
+ paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
undo_paint_push_end(UNDO_PAINT_IMAGE);
}
Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_2d.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_2d.c 2013-09-25 20:28:49 UTC (rev 60371)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_2d.c 2013-09-25 20:58:53 UTC (rev 60372)
@@ -41,6 +41,8 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_math_color_blend.h"
+#include "BLI_gsqueue.h"
+#include "BLI_bitmap.h"
#include "BKE_context.h"
#include "BKE_brush.h"
@@ -1279,17 +1281,42 @@
MEM_freeN(s);
}
+static void paint_2d_fill_add_pixel_byte(int i, int j, ImBuf *ibuf, GSQueue *stack, BLI_bitmap *touched, float color[4], float threshold)
+{
+ int coordinate = j * ibuf->x + i;
+ if (i >= ibuf->x || i < 0 || j >= ibuf->y || j < 0)
+ return;
+
+ if (!BLI_BITMAP_GET(touched, coordinate)) {
+ float color_f[4];
+ unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
+ float luminance;
+ rgba_uchar_to_float(color_f, color_b);
+
+ sub_v3_v3(color_f, color);
+
+ luminance = (fabs(color_f[0]) + fabs(color_f[0]) + fabs(color_f[0]))/3.0;
+ if (luminance < threshold) {
+ BLI_gsqueue_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate);
+ }
+}
+
/* this function expects linear space color values */
-void paint_2d_bucket_fill (const bContext *C, float color[3], float strength)
+void paint_2d_bucket_fill (const bContext *C, float color[3], Brush *br, float mouse_init[2], void *ps)
{
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = sima->image;
+ ImagePaintState *s = ps;
+
ImBuf *ibuf;
- unsigned short i = 0, j = 0;
+ int i = 0, j = 0;
unsigned int color_b;
float color_f[4];
+ float strength = br ? br->alpha : 1.0;
bool do_float;
@@ -1303,34 +1330,115 @@
do_float = (ibuf->rect_float != NULL);
/* first check if our image is float. If it is not we should correct the colour to
- * be in gamma space */
-
+ * be in gamma space. strictly speaking this is not correct, but blender does not paint
+ * byte images in linear space */
if (!do_float) {
linearrgb_to_srgb_uchar3((unsigned char *)&color_b, color);
- *(((char *)&color_b) + 3) = strength*255;
+ *(((char *)&color_b) + 3) = strength * 255;
} else {
copy_v3_v3(color_f, color);
color_f[3] = strength;
}
- /* this will be substituted by something else when selection is available */
- imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ if (!mouse_init || !br) {
+ /* first case, no image UV, fill the whole image */
+ imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
- if (do_float) {
- for (; i < ibuf->x; i++) {
- for (j = 0; j < ibuf->y; j++) {
- blend_color_mix_float(ibuf->rect_float + 4 * (j * ibuf->x + i),
- ibuf->rect_float + 4 * (j * ibuf->x + i), color_f);
+ if (do_float) {
+ for (; i < ibuf->x; i++) {
+ for (j = 0; j < ibuf->y; j++) {
+ blend_color_mix_float(ibuf->rect_float + 4 * (j * ibuf->x + i),
+ ibuf->rect_float + 4 * (j * ibuf->x + i), color_f);
+ }
}
}
+ else {
+ for (; i < ibuf->x; i++) {
+ for (j = 0; j < ibuf->y; j++) {
+ blend_color_mix_byte((unsigned char *)(ibuf->rect + j * ibuf->x + i),
+ (unsigned char *)(ibuf->rect + j * ibuf->x + i), (unsigned char *)&color_b);
+ }
+ }
+ }
}
else {
- for (; i < ibuf->x; i++) {
- for (j = 0; j < ibuf->y; j++) {
- blend_color_mix_byte((unsigned char *)(ibuf->rect + j * ibuf->x + i),
- (unsigned char *)(ibuf->rect + j * ibuf->x + i), (unsigned char *)&color_b);
+ /* second case, start sweeping the neighboring pixels, looking for pixels whose
+ * value is within the brush fill threshold from the fill color */
+ GSQueue *stack;
+ BLI_bitmap *touched;
+ int coordinate;
+ int width = ibuf->x;
+ float image_init[2];
+ int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
+ float pixel_color[4];
+
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ i = image_init[0] * ibuf->x;
+ j = image_init[1] * ibuf->y;
+
+ if (i >= ibuf->x || i < 0 || j > ibuf->y || j < 0) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ /* change image invalidation method later */
+ imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+
+ stack = BLI_gsqueue_new(sizeof(int));
+ touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap");
+
+ coordinate = (j * ibuf->x + i);
+
+ if (do_float) {
+
+ }
+ else {
+ int pixel_color_b = *(ibuf->rect + coordinate);
+ rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
+ }
+
+ BLI_gsqueue_push(stack, &coordinate);
+ BLI_BITMAP_SET(touched, coordinate);
+
+ if (do_float) {
+ blend_color_mix_float(ibuf->rect_float + 4 * (j * ibuf->x + i),
+ ibuf->rect_float + 4 * (j * ibuf->x + i), color_f);
+ BLI_gsqueue_pop(stack, &coordinate);
+ }
+ else {
+ while (!BLI_gsqueue_is_empty(stack)) {
+ BLI_gsqueue_pop(stack, &coordinate);
+
+ blend_color_mix_byte((unsigned char *)(ibuf->rect + coordinate),
+ (unsigned char *)(ibuf->rect + coordinate), (unsigned char *)&color_b);
+
+ /* reconstruct the coordinates here */
+ i = coordinate % width;
+ j = coordinate / width;
+
+ paint_2d_fill_add_pixel_byte(i - 1, j - 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i - 1, j, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i - 1, j + 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i, j + 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i, j - 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i + 1, j - 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i + 1, j, ibuf, stack, touched, pixel_color, br->fill_threshold);
+ paint_2d_fill_add_pixel_byte(i + 1, j + 1, ibuf, stack, touched, pixel_color, br->fill_threshold);
+
+ if (i > maxx)
+ maxx = i;
+ if (i < minx)
+ minx = i;
+ if (j > maxy)
+ maxy = j;
+ if (i > miny)
+ miny = j;
}
}
+
+ MEM_freeN(touched);
+ BLI_gsqueue_free(stack);
}
imapaint_image_update(sima, ima, ibuf, false);
Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h 2013-09-25 20:28:49 UTC (rev 60371)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h 2013-09-25 20:58:53 UTC (rev 60372)
@@ -159,7 +159,7 @@
void paint_2d_redraw(const bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser, float pressure, float distance);
-void paint_2d_bucket_fill(const struct bContext *C, float color[3], float strength);
+void paint_2d_bucket_fill(const struct bContext *C, float color[3], struct Brush *br, float mouse_init[], void *ps);
void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, float mouse_init[2], float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], float pressure, float distance);
Modified: branches/soc-2013-paint/source/blender/makesdna/DNA_brush_types.h
===================================================================
--- branches/soc-2013-paint/source/blender/makesdna/DNA_brush_types.h 2013-09-25 20:28:49 UTC (rev 60371)
+++ branches/soc-2013-paint/source/blender/makesdna/DNA_brush_types.h 2013-09-25 20:58:53 UTC (rev 60372)
@@ -120,8 +120,10 @@
float sharp_threshold;
int blur_kernel_radius;
int blur_mode;
- int pad;
+ /* fill tool */
+ float fill_threshold;
+
float add_col[3];
float sub_col[3];
Modified: branches/soc-2013-paint/source/blender/makesrna/intern/rna_brush.c
===================================================================
--- branches/soc-2013-paint/source/blender/makesrna/intern/rna_brush.c 2013-09-25 20:28:49 UTC (rev 60371)
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list