Exemple #1
0
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
  ARegion *ar = CTX_wm_region(C);
  uiBut *but = NULL;
  float color[4];
  bool gamma;

  RNA_float_get_array(op->ptr, "color", color);
  gamma = RNA_boolean_get(op->ptr, "gamma");

  /* find button under mouse, check if it has RNA color property and
   * if it does copy the data */
  but = ui_region_find_active_but(ar);

  if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
    const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
    BLI_assert(color_len <= 4);

    /* keep alpha channel as-is */
    if (color_len == 4) {
      color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
    }

    if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
      if (!gamma) {
        IMB_colormanagement_scene_linear_to_srgb_v3(color);
      }
      RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
      RNA_property_update(C, &but->rnapoin, but->rnaprop);
    }
    else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
      if (gamma) {
        IMB_colormanagement_srgb_to_scene_linear_v3(color);
      }
      RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
      RNA_property_update(C, &but->rnapoin, but->rnaprop);
    }
  }
  else {
    if (gamma) {
      srgb_to_linearrgb_v3_v3(color, color);
    }

    ED_imapaint_bucket_fill(C, color, op);
  }

  ED_region_tag_redraw(ar);

  return OPERATOR_FINISHED;
}
Exemple #2
0
static void eyedropper_sample(bContext *C, Eyedropper *eye, int mx, int my)
{
	if(RNA_property_type(eye->prop) == PROP_FLOAT) {
		const int color_manage = CTX_data_scene(C)->r.color_mgt_flag & R_COLOR_MANAGEMENT;
		float col[4];
	
		RNA_property_float_get_array(&eye->ptr, eye->prop, col);
		
		glReadBuffer(GL_FRONT);
		glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, col);
		glReadBuffer(GL_BACK);
	
		if (RNA_property_array_length(&eye->ptr, eye->prop) < 3) return;

		/* convert from screen (srgb) space to linear rgb space */
		if (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR)
			srgb_to_linearrgb_v3_v3(col, col);
		
		RNA_property_float_set_array(&eye->ptr, eye->prop, col);
		
		RNA_property_update(C, &eye->ptr, eye->prop);
	}
}
Exemple #3
0
/* update rectangular section of the brush image */
static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
                                       int origx, int origy, int w, int h, int xt, int yt)
{
    Scene *scene = painter->scene;
    Brush *brush = painter->brush;

    rctf tex_mapping = painter->tex_mapping;
    rctf mask_mapping = painter->mask_mapping;
    struct ImagePool *pool = painter->pool;

    bool use_masking = painter->cache.use_masking;
    bool use_color_correction = painter->cache.use_color_correction;
    bool use_float = painter->cache.use_float;
    bool is_texbrush = painter->cache.is_texbrush;
    bool is_maskbrush = painter->cache.is_maskbrush;
    bool use_texture_old = (oldtexibuf != NULL);

    int x, y, thread = 0;
    float brush_rgb[3];

    ImBuf *ibuf = painter->cache.ibuf;
    ImBuf *texibuf = painter->cache.texibuf;
    unsigned short *mask = painter->cache.mask;

    /* get brush color */
    if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
        copy_v3_v3(brush_rgb, brush->rgb);

        if (use_color_correction)
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
    }
    else {
        brush_rgb[0] = 1.0f;
        brush_rgb[1] = 1.0f;
        brush_rgb[2] = 1.0f;
    }

    /* fill pixes */
    for (y = origy; y < h; y++) {
        for (x = origx; x < w; x++) {
            /* sample texture and multiply with brush color */
            float texco[3], rgba[4];

            if (!use_texture_old) {
                if (is_texbrush) {
                    brush_imbuf_tex_co(&tex_mapping, x, y, texco);
                    BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
                    /* TODO(sergey): Support texture paint color space. */
                    if (!use_float) {
                        linearrgb_to_srgb_v3_v3(rgba, rgba);
                    }
                    mul_v3_v3(rgba, brush_rgb);
                }
                else {
                    copy_v3_v3(rgba, brush_rgb);
                    rgba[3] = 1.0f;
                }

                if (is_maskbrush) {
                    brush_imbuf_tex_co(&mask_mapping, x, y, texco);
                    rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
                }
            }

            if (use_float) {
                /* handle float pixel */
                float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4;
                float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4;

                /* read from old texture buffer */
                if (use_texture_old) {
                    float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
                    copy_v4_v4(rgba, otf);
                }

                /* write to new texture buffer */
                copy_v4_v4(tf, rgba);

                /* if not using masking, multiply in the mask now */
                if (!use_masking) {
                    unsigned short *m = mask + (y * ibuf->x + x);
                    rgba[3] *= *m * (1.0f / 65535.0f);
                }

                /* output premultiplied float image, mf was already premultiplied */
                mul_v3_v3fl(bf, rgba, rgba[3]);
                bf[3] = rgba[3];
            }
            else {
                unsigned char crgba[4];

                /* handle byte pixel */
                unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4;
                unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4;

                /* read from old texture buffer */
                if (use_texture_old) {
                    unsigned char *ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
                    crgba[0] = ot[0];
                    crgba[1] = ot[1];
                    crgba[2] = ot[2];
                    crgba[3] = ot[3];
                }
                else
                    rgba_float_to_uchar(crgba, rgba);

                /* write to new texture buffer */
                t[0] = crgba[0];
                t[1] = crgba[1];
                t[2] = crgba[2];
                t[3] = crgba[3];

                /* if not using masking, multiply in the mask now */
                if (!use_masking) {
                    unsigned short *m = mask + (y * ibuf->x + x);
                    crgba[3] = (crgba[3] * (*m)) / 65535;
                }

                /* write to brush image buffer */
                b[0] = crgba[0];
                b[1] = crgba[1];
                b[2] = crgba[2];
                b[3] = crgba[3];
            }
        }
    }
}
Exemple #4
0
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
{
    Scene *scene = painter->scene;
    Brush *brush = painter->brush;

    rctf tex_mapping = painter->tex_mapping;
    rctf mask_mapping = painter->mask_mapping;
    struct ImagePool *pool = painter->pool;

    bool use_masking = painter->cache.use_masking;
    bool use_color_correction = painter->cache.use_color_correction;
    bool use_float = painter->cache.use_float;
    bool is_texbrush = painter->cache.is_texbrush;
    bool is_maskbrush = painter->cache.is_maskbrush;

    float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
    int radius = BKE_brush_size_get(scene, brush);
    int xoff = -size * 0.5f + 0.5f;
    int yoff = -size * 0.5f + 0.5f;

    int x, y, thread = 0;
    float brush_rgb[3];

    /* allocate image buffer */
    ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);

    /* get brush color */
    if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
        copy_v3_v3(brush_rgb, brush->rgb);

        if (use_color_correction)
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
    }
    else {
        brush_rgb[0] = 1.0f;
        brush_rgb[1] = 1.0f;
        brush_rgb[2] = 1.0f;
    }

    /* fill image buffer */
    for (y = 0; y < size; y++) {
        for (x = 0; x < size; x++) {
            /* sample texture and multiply with brush color */
            float texco[3], rgba[4];

            if (is_texbrush) {
                brush_imbuf_tex_co(&tex_mapping, x, y, texco);
                BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
                /* TODO(sergey): Support texture paint color space. */
                if (!use_float) {
                    linearrgb_to_srgb_v3_v3(rgba, rgba);
                }
                mul_v3_v3(rgba, brush_rgb);
            }
            else {
                copy_v3_v3(rgba, brush_rgb);
                rgba[3] = 1.0f;
            }

            if (is_maskbrush) {
                brush_imbuf_tex_co(&mask_mapping, x, y, texco);
                rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
            }

            /* when not using masking, multiply in falloff and strength */
            if (!use_masking) {
                float xy[2] = {x + xoff, y + yoff};
                float len = len_v2(xy);

                rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
            }

            if (use_float) {
                /* write to float pixel */
                float *dstf = ibuf->rect_float + (y * size + x) * 4;
                mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
                dstf[3] = rgba[3];
            }
            else {
                /* write to byte pixel */
                unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;

                rgb_float_to_uchar(dst, rgba);
                dst[3] = FTOCHAR(rgba[3]);
            }
        }
    }

    return ibuf;
}
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
{
	srgb_to_linearrgb_v3_v3(linear, srgb);
	linear[3] = srgb[3];
}
Exemple #6
0
/* float to float pixels, output 4-channel RGBA */
void IMB_buffer_float_from_float(float *rect_to,
                                 const float *rect_from,
                                 int channels_from,
                                 int profile_to,
                                 int profile_from,
                                 bool predivide,
                                 int width,
                                 int height,
                                 int stride_to,
                                 int stride_from)
{
  int x, y;

  /* we need valid profiles */
  BLI_assert(profile_to != IB_PROFILE_NONE);
  BLI_assert(profile_from != IB_PROFILE_NONE);

  if (channels_from == 1) {
    /* single channel input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      for (x = 0; x < width; x++, from++, to += 4) {
        to[0] = to[1] = to[2] = to[3] = from[0];
      }
    }
  }
  else if (channels_from == 3) {
    /* RGB input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y * 3;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* no color space conversion */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          copy_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          srgb_to_linearrgb_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          linearrgb_to_srgb_v3_v3(to, from);
          to[3] = 1.0f;
        }
      }
    }
  }
  else if (channels_from == 4) {
    /* RGBA input */
    for (y = 0; y < height; y++) {
      const float *from = rect_from + ((size_t)stride_from) * y * 4;
      float *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* same profile, copy */
        memcpy(to, from, sizeof(float) * ((size_t)4) * width);
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert to sRGB to linear */
        if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(to, from);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(to, from);
          }
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_predivide_v4(to, from);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_v4(to, from);
          }
        }
      }
    }
  }
}
Exemple #7
0
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to,
                                const float *rect_from,
                                int channels_from,
                                float dither,
                                int profile_to,
                                int profile_from,
                                bool predivide,
                                int width,
                                int height,
                                int stride_to,
                                int stride_from)
{
  float tmp[4];
  int x, y;
  DitherContext *di = NULL;
  float inv_width = 1.0f / width;
  float inv_height = 1.0f / height;

  /* we need valid profiles */
  BLI_assert(profile_to != IB_PROFILE_NONE);
  BLI_assert(profile_from != IB_PROFILE_NONE);

  if (dither) {
    di = create_dither_context(dither);
  }

  for (y = 0; y < height; y++) {
    float t = y * inv_height;

    if (channels_from == 1) {
      /* single channel input */
      const float *from = rect_from + ((size_t)stride_from) * y;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      for (x = 0; x < width; x++, from++, to += 4) {
        to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
      }
    }
    else if (channels_from == 3) {
      /* RGB input */
      const float *from = rect_from + ((size_t)stride_from) * y * 3;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        /* no color space conversion */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          rgb_float_to_uchar(to, from);
          to[3] = 255;
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          linearrgb_to_srgb_v3_v3(tmp, from);
          rgb_float_to_uchar(to, tmp);
          to[3] = 255;
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        for (x = 0; x < width; x++, from += 3, to += 4) {
          srgb_to_linearrgb_v3_v3(tmp, from);
          rgb_float_to_uchar(to, tmp);
          to[3] = 255;
        }
      }
    }
    else if (channels_from == 4) {
      /* RGBA input */
      const float *from = rect_from + ((size_t)stride_from) * y * 4;
      uchar *to = rect_to + ((size_t)stride_to) * y * 4;

      if (profile_to == profile_from) {
        float straight[4];

        /* no color space conversion */
        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            rgba_float_to_uchar(to, straight);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            rgba_float_to_uchar(to, from);
          }
        }
      }
      else if (profile_to == IB_PROFILE_SRGB) {
        /* convert from linear to sRGB */
        unsigned short us[4];
        float straight[4];

        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            premul_to_straight_v4_v4(straight, from);
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_v4(to, us);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            linearrgb_to_srgb_ushort4(us, from);
            ushort_to_byte_v4(to, us);
          }
        }
      }
      else if (profile_to == IB_PROFILE_LINEAR_RGB) {
        /* convert from sRGB to linear */
        if (dither && predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(tmp, from);
            float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
          }
        }
        else if (dither) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(tmp, from);
            float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
          }
        }
        else if (predivide) {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_predivide_v4(tmp, from);
            rgba_float_to_uchar(to, tmp);
          }
        }
        else {
          for (x = 0; x < width; x++, from += 4, to += 4) {
            srgb_to_linearrgb_v4(tmp, from);
            rgba_float_to_uchar(to, tmp);
          }
        }
      }
    }
  }

  if (dither) {
    clear_dither_context(di);
  }
}
Exemple #8
0
void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
	ImBuf *ibuf;
	float xy[2], dist, rgba[4], *dstf;
	int x, y, rowbytes, xoff, yoff, imbflag;
	const int radius= brush_size(brush);
	char *dst, crgb[3];
	const float alpha= brush_alpha(brush);
	float brush_rgb[3];
    
	imbflag= (flt)? IB_rectfloat: IB_rect;
	xoff = -bufsize/2.0f + 0.5f;
	yoff = -bufsize/2.0f + 0.5f;
	rowbytes= bufsize*4;

	if (*outbuf)
		ibuf= *outbuf;
	else
		ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

	if (flt) {
		copy_v3_v3(brush_rgb, brush->rgb);
		if(use_color_correction){
			srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
		}

		for (y=0; y < ibuf->y; y++) {
			dstf = ibuf->rect_float + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dstf+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					copy_v3_v3(dstf, brush_rgb);
					dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, dstf, 0);
				}
				else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					mul_v3_v3v3(dstf, rgba, brush_rgb);
					dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
			}
		}
	}
	else {
		crgb[0]= FTOCHAR(brush->rgb[0]);
		crgb[1]= FTOCHAR(brush->rgb[1]);
		crgb[2]= FTOCHAR(brush->rgb[2]);

		for (y=0; y < ibuf->y; y++) {
			dst = (char*)ibuf->rect + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dst+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= FTOCHAR(rgba[0]);
					dst[1]= FTOCHAR(rgba[1]);
					dst[2]= FTOCHAR(rgba[2]);
					dst[3]= FTOCHAR(rgba[3]);
				}
				else if (texfall == 2) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
					dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
					dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				} else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				}
			}
		}
	}

	*outbuf= ibuf;
}
Exemple #9
0
/* TODO, use define for 'texfall' arg */
void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
    ImBuf *ibuf;
    float xy[2], rgba[4], *dstf;
    int x, y, rowbytes, xoff, yoff, imbflag;
    const int radius = BKE_brush_size_get(scene, brush);
    unsigned char *dst, crgb[3];
    const float alpha = BKE_brush_alpha_get(scene, brush);
    float brush_rgb[3];

    imbflag = (flt) ? IB_rectfloat : IB_rect;
    xoff = -bufsize / 2.0f + 0.5f;
    yoff = -bufsize / 2.0f + 0.5f;
    rowbytes = bufsize * 4;

    if (*outbuf)
        ibuf = *outbuf;
    else
        ibuf = IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

    if (flt) {
        copy_v3_v3(brush_rgb, brush->rgb);
        if (use_color_correction) {
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
        }

        for (y = 0; y < ibuf->y; y++) {
            dstf = ibuf->rect_float + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dstf += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    copy_v3_v3(dstf, brush_rgb);
                    dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, dstf, 0);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3v3(dstf, rgba, brush_rgb);
                    dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
            }
        }
    }
    else {
        float alpha_f; /* final float alpha to convert to char */
        rgb_float_to_uchar(crgb, brush->rgb);

        for (y = 0; y < ibuf->y; y++) {
            dst = (unsigned char *)ibuf->rect + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dst += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    alpha_f = alpha * BKE_brush_curve_strength(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    rgba_float_to_uchar(dst, rgba);
                }
                else if (texfall == 2) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3(rgba, brush->rgb);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    rgb_float_to_uchar(dst, rgba);

                    dst[3] = FTOCHAR(alpha_f);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
            }
        }
    }

    *outbuf = ibuf;
}