Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_brush.h4
-rw-r--r--source/blender/blenkernel/intern/brush.c33
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/BLI_utildefines.h6
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c15
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c31
-rw-r--r--source/blender/gpu/intern/gpu_draw.c22
-rw-r--r--source/blender/imbuf/IMB_imbuf.h5
-rw-r--r--source/blender/imbuf/intern/divers.c129
9 files changed, 218 insertions, 29 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index ad736cd07bf..ebb9714cd1b 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -71,7 +71,7 @@ float brush_curve_strength(struct Brush *br, float p, const float len); /* used
/* sampling */
void brush_sample_tex(struct Brush *brush, float *xy, float *rgba, const int thread);
void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size,
- struct ImBuf **imbuf);
+ struct ImBuf **imbuf, int use_color_correction);
/* painting */
struct BrushPainter;
@@ -82,7 +82,7 @@ BrushPainter *brush_painter_new(struct Brush *brush);
void brush_painter_require_imbuf(BrushPainter *painter, short flt,
short texonly, int size);
int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos,
- double time, float pressure, void *user);
+ double time, float pressure, void *user, int use_color_correction);
void brush_painter_break_stroke(BrushPainter *painter);
void brush_painter_free(BrushPainter *painter);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 25b60fef6dd..a4ceb62ab55 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -521,7 +521,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread)
}
-void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf)
+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;
@@ -529,7 +529,8 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
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;
@@ -541,6 +542,11 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
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;
@@ -551,7 +557,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
if (texfall == 0) {
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
- VECCOPY(dstf, brush->rgb);
+ VECCOPY(dstf, brush_rgb);
dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
}
else if (texfall == 1) {
@@ -561,10 +567,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
brush_sample_tex(brush, xy, rgba, 0);
-
- dstf[0] = rgba[0]*brush->rgb[0];
- dstf[1] = rgba[1]*brush->rgb[1];
- dstf[2] = rgba[2]*brush->rgb[2];
+ mul_v3_v3v3(dstf, rgba, brush_rgb);
dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
}
}
@@ -862,7 +865,7 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float
brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
}
-static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
+static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction)
{
Brush *brush= painter->brush;
BrushPainterCache *cache= &painter->cache;
@@ -889,11 +892,11 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
size= (cache->size)? cache->size: diameter;
if (brush->flag & BRUSH_FIXED_TEX) {
- brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf);
+ brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf, use_color_correction);
brush_painter_fixed_tex_partial_update(painter, pos);
}
else
- brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
+ brush_imbuf_new(brush, flt, 2, size, &cache->ibuf, use_color_correction);
cache->lastsize= diameter;
cache->lastalpha= alpha;
@@ -952,7 +955,7 @@ void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
}
}
-int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
+int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction)
{
Brush *brush= painter->brush;
int totpaintops= 0;
@@ -970,7 +973,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
brush_apply_pressure(painter, brush, pressure);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, pos);
+ brush_painter_refresh_cache(painter, pos, use_color_correction);
totpaintops += func(user, painter->cache.ibuf, pos, pos);
painter->lasttime= time;
@@ -1043,7 +1046,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
brush_jitter_pos(brush, paintpos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos);
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
totpaintops +=
func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
@@ -1057,7 +1060,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
brush_jitter_pos(brush, pos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos);
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
@@ -1085,7 +1088,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
brush_jitter_pos(brush, pos, finalpos);
if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos);
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
totpaintops +=
func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 5f26bff0ad9..decfa22c3e6 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -58,6 +58,8 @@ MINLINE void swap_v4_v4(float a[4], float b[4]);
/********************************* Arithmetic ********************************/
+MINLINE void add_v3_fl(float r[3], float f);
+MINLINE void add_v4_fl(float r[4], float f);
MINLINE void add_v2_v2(float r[2], const float a[2]);
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]);
MINLINE void add_v3_v3(float r[3], const float a[3]);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index a376d048412..9af55601ff7 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -103,6 +103,12 @@
#define FTOCHAR(val) ((val)<=0.0f)? 0 : (((val)>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*(val))+0.5f))
#define FTOUSHORT(val) ((val >= 1.0f-0.5f/65535)? 65535: (val <= 0.0f)? 0: (unsigned short)(val*65535.0f + 0.5f))
+#define F3TOCHAR3(v2,v1) (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2]))
+#define F3TOCHAR4(v2,v1) { (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2])); \
+ (v1)[3]=FTOCHAR((v2[3])); (v1)[3] = 255; }
+#define F4TOCHAR4(v2,v1) { (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2])); \
+ (v1)[3]=FTOCHAR((v2[3])); (v1)[3]=FTOCHAR((v2[3])); }
+
#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
#define VECCOPY2D(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1);}
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 9f6a8afe2d5..e2b7c770356 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -102,6 +102,21 @@ MINLINE void swap_v4_v4(float a[4], float b[4])
/********************************* Arithmetic ********************************/
+MINLINE void add_v3_fl(float r[3], float f)
+{
+ r[0] += f;
+ r[1] += f;
+ r[2] += f;
+}
+
+MINLINE void add_v4_fl(float r[4], float f)
+{
+ r[0] += f;
+ r[1] += f;
+ r[2] += f;
+ r[3] += f;
+}
+
MINLINE void add_v2_v2(float *r, const float *a)
{
r[0] += a[0];
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index d7e8d3be66f..83ba35a2e5c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -3692,14 +3692,26 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, float
}
}
-static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) {
+static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, int use_color_correction) {
if (ps->is_texbrush) {
- rgba[0] *= ps->brush->rgb[0];
- rgba[1] *= ps->brush->rgb[1];
- rgba[2] *= ps->brush->rgb[2];
+ /* rgba already holds a texture result here from higher level function */
+ float rgba_br[3];
+ if(use_color_correction){
+ srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb);
+ mul_v3_v3(rgba, rgba_br);
+ }
+ else{
+ mul_v3_v3(rgba, ps->brush->rgb);
+ }
}
else {
- VECCOPY(rgba, ps->brush->rgb);
+ if(use_color_correction){
+ srgb_to_linearrgb_v3_v3(rgba, rgba);
+ }
+ else {
+ VECCOPY(rgba, ps->brush->rgb);
+ }
+ rgba[3] = 1.0;
}
if (ps->is_airbrush==0 && mask < 1.0f) {
@@ -3736,6 +3748,7 @@ static void *do_projectpaint_thread(void *ph_v)
float falloff;
int bucket_index;
int is_floatbuf = 0;
+ int use_color_correction = 0;
const short tool = ps->tool;
rctf bucket_bounds;
@@ -3841,6 +3854,7 @@ static void *do_projectpaint_thread(void *ph_v)
last_projIma->touch = 1;
is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
+ use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0;
}
last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
@@ -3871,7 +3885,7 @@ static void *do_projectpaint_thread(void *ph_v)
else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co);
break;
default:
- if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask);
+ if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction);
else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask);
break;
}
@@ -3987,7 +4001,7 @@ static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, c
// we may want to use this later
// brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
- if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps)) {
+ if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) {
return 1;
}
else return 0;
@@ -4058,7 +4072,6 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w,
static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
{
if(ibuf->rect_float)
- /* TODO - should just update a portion from imapaintpartial! */
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
if(ibuf->mipmap[0])
@@ -4409,7 +4422,7 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
- if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s)) {
+ if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) {
if (update)
imapaint_image_update(s->sima, image, ibuf, texpaint);
return 1;
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 0e7df43bd34..7dfbc52819e 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -687,9 +687,25 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
- if ((ibuf->rect==NULL) && ibuf->rect_float)
- IMB_rect_from_float(ibuf);
-
+ if (ibuf->rect_float){
+ /*This case needs a whole new buffer*/
+ if(ibuf->rect==NULL) {
+ IMB_rect_from_float(ibuf);
+ }
+ else {
+ /* Do partial drawing. 'buffer' holds only the changed part. Needed for color corrected result */
+ float *buffer = (float *)MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf");
+ IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h);
+ glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
+ GL_FLOAT, buffer);
+ MEM_freeN(buffer);
+ if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
+ ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+ return;
+ }
+ }
+
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 1eefc58d4de..5d61452e149 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -327,7 +327,12 @@ int imb_get_anim_type(const char *name);
*/
void IMB_de_interlace(struct ImBuf *ibuf);
void IMB_interlace(struct ImBuf *ibuf);
+
+/* create char buffer, color corrected if necessary, for ImBufs that lack one */
void IMB_rect_from_float(struct ImBuf *ibuf);
+/* create char buffer for part of the image, color corrected if necessary,
+ Changed part will be stored in buffer. This is expected to be used for texture painting updates */
+void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h);
void IMB_float_from_rect(struct ImBuf *ibuf);
void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
/* note, check that the conversion exists, only some are supported */
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 6b35d7df397..90ee2692cf0 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -197,6 +197,135 @@ void IMB_rect_from_float(struct ImBuf *ibuf)
ibuf->userflags &= ~IB_RECT_INVALID;
}
+
+
+/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
+void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h)
+{
+ /* indices to source and destination image pixels */
+ float *srcFloatPxl;
+ unsigned char *dstBytePxl;
+ /* buffer index will fill buffer */
+ float *bufferIndex;
+
+ /* convenience pointers to start of image buffers */
+ float *init_srcFloatPxl = (float *)ibuf->rect_float;
+ unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect;
+
+ /* Dithering factor */
+ float dither= ibuf->dither / 255.0f;
+ /* respective attributes of image */
+ short profile= ibuf->profile;
+ int channels= ibuf->channels;
+
+ int i, j;
+
+ /*
+ if called -only- from GPU_paint_update_image this test will never fail
+ but leaving it here for better or worse
+ */
+ if(init_srcFloatPxl==NULL || (buffer == NULL)){
+ return;
+ }
+ if(init_dstBytePxl==NULL) {
+ imb_addrectImBuf(ibuf);
+ init_dstBytePxl = (unsigned char *) ibuf->rect;
+ }
+ if(channels==1) {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x);
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) {
+ dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]);
+ bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0];
+ }
+ }
+ }
+ else if (profile == IB_PROFILE_LINEAR_RGB) {
+ if(channels == 3) {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) {
+ linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
+ F3TOCHAR4(bufferIndex, dstBytePxl);
+ bufferIndex[3]= 1.0;
+ }
+ }
+ }
+ else if (channels == 4) {
+ if (dither != 0.f) {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
+ const float d = (BLI_frand()-0.5f)*dither;
+ linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
+ bufferIndex[3] = srcFloatPxl[3];
+ add_v4_fl(bufferIndex, d);
+ F4TOCHAR4(bufferIndex, dstBytePxl);
+ }
+ }
+ } else {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
+ linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
+ bufferIndex[3]= srcFloatPxl[3];
+ F4TOCHAR4(bufferIndex, dstBytePxl);
+ }
+ }
+ }
+ }
+ }
+ else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
+ if(channels==3) {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) {
+ copy_v3_v3(bufferIndex, srcFloatPxl);
+ F3TOCHAR4(bufferIndex, dstBytePxl);
+ bufferIndex[3] = 1.0;
+ }
+ }
+ }
+ else {
+ if (dither != 0.f) {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
+ const float d = (BLI_frand()-0.5f)*dither;
+ copy_v4_v4(bufferIndex, srcFloatPxl);
+ add_v4_fl(bufferIndex,d);
+ F4TOCHAR4(bufferIndex, dstBytePxl);
+ }
+ }
+ } else {
+ for (j = 0; j < h; j++){
+ bufferIndex = buffer + w*j*4;
+ dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
+ srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
+ for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
+ copy_v4_v4(bufferIndex, srcFloatPxl);
+ F4TOCHAR4(bufferIndex, dstBytePxl);
+ }
+ }
+ }
+ }
+ }
+ /* ensure user flag is reset */
+ ibuf->userflags &= ~IB_RECT_INVALID;
+}
+
static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf)
{
float *tof = fbuf;