From b9ff5840a617ec836f2d09bb0f04d60e5c3b8f67 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 28 Dec 2011 13:29:33 +0000 Subject: Code refactoring: add unified image buffer functions for doing float => byte, byte => float, float => float, byte => byte conversions with profile, dither and predivide. Previously code for this was spread out too much. There should be no functional changes, this is so the predivide/table/dither patches can work correctly. --- source/blender/blenkernel/BKE_colortools.h | 3 - source/blender/blenkernel/intern/colortools.c | 39 -- source/blender/blenlib/BLI_math_color.h | 29 +- source/blender/blenlib/intern/math_color.c | 51 -- source/blender/blenlib/intern/math_color_inline.c | 109 +++ source/blender/editors/render/render_internal.c | 57 +- source/blender/editors/render/render_opengl.c | 11 +- source/blender/editors/screen/glutil.c | 13 +- source/blender/imbuf/IMB_imbuf.h | 14 + source/blender/imbuf/intern/divers.c | 750 +++++++++++++-------- .../blender/nodes/composite/node_composite_util.c | 11 +- .../nodes/composite/nodes/node_composite_image.c | 13 +- source/blender/render/intern/source/pipeline.c | 55 +- 13 files changed, 650 insertions(+), 505 deletions(-) create mode 100644 source/blender/blenlib/intern/math_color_inline.c diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index fd3a3fea2bb..b358209a0f4 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -45,9 +45,6 @@ struct rctf; # define DO_INLINE static inline #endif -void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); -void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); - struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free(struct CurveMapping *cumap); struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 2f568aa01eb..67bd6a22348 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -52,45 +52,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" - -void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w)) -{ - int x, y; - float *rf= rectf; - float srgb[3]; - unsigned char *rc= rectc; - - for(y=y1; y255) c[0]=255; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c new file mode 100644 index 00000000000..aaaa065f14d --- /dev/null +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -0,0 +1,109 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: some of this file. + * + * ***** END GPL LICENSE BLOCK ***** + * */ + +/** \file blender/blenlib/intern/math_color_inline.c + * \ingroup bli + */ + + +#include "BLI_math_color.h" +#include "BLI_utildefines.h" + +#ifndef BLI_MATH_COLOR_INLINE_H +#define BLI_MATH_COLOR_INLINE_H + +/******************************** Color Space ********************************/ + +MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]) +{ + linear[0] = srgb_to_linearrgb(srgb[0]); + linear[1] = srgb_to_linearrgb(srgb[1]); + linear[2] = srgb_to_linearrgb(srgb[2]); +} + +MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]) +{ + srgb[0] = linearrgb_to_srgb(linear[0]); + srgb[1] = linearrgb_to_srgb(linear[1]); + srgb[2] = linearrgb_to_srgb(linear[2]); +} + +MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]) +{ + srgb_to_linearrgb_v3_v3(linear, srgb); + linear[3] = srgb[3]; +} + +MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]) +{ + linearrgb_to_srgb_v3_v3(srgb, linear); + srgb[3] = linear[3]; +} + +/* predivide versions to work on associated/premultipled alpha. if this should + be done or not depends on the background the image will be composited over, + ideally you would never do color space conversion on an image with alpha + because it is ill defined */ + +MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]) +{ + float alpha, inv_alpha; + + if(srgb[3] == 1.0f || srgb[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = srgb[3]; + inv_alpha = 1.0f/alpha; + } + + linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha; + linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha; + linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha; + linear[3] = srgb[3]; +} + +MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]) +{ + float alpha, inv_alpha; + + if(linear[3] == 1.0f || linear[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = linear[3]; + inv_alpha = 1.0f/alpha; + } + + srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha; + srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha; + srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha; + srgb[3] = linear[3]; +} + +#endif /* BLI_MATH_COLOR_INLINE_H */ + diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8a580627da3..bff93fea067 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -76,10 +76,10 @@ /* called inside thread! */ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect) { - float x1, y1, *rectf= NULL; + float *rectf= NULL; int ymin, ymax, xmin, xmax; - int rymin, rxmin, do_color_management; - char *rectc; + int rymin, rxmin, predivide, profile_from; + unsigned char *rectc; /* if renrect argument, we only refresh scanlines */ if(renrect) { @@ -136,50 +136,17 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat imb_addrectImBuf(ibuf); rectf+= 4*(rr->rectx*ymin + xmin); - rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin); + rectc= (unsigned char*)(ibuf->rect + ibuf->x*rymin + rxmin); - do_color_management = (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)); - - /* XXX make nice consistent functions for this */ - for(y1= 0; y1dither / 255.0f; - - /* XXX temp. because crop offset */ - if(rectc >= (char *)(ibuf->rect)) { - for(x1= 0; x1r.color_mgt_flag & R_COLOR_MANAGEMENT)) + profile_from= IB_PROFILE_LINEAR_RGB; + else + profile_from= IB_PROFILE_SRGB; + predivide= 0; - rectf += 4*rr->rectx; - rectc += 4*ibuf->x; - } + IMB_buffer_byte_from_float(rectc, rectf, + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + xmax, ymax, ibuf->x, rr->rectx); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 35b21c626ed..be4d54ae2e8 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -206,14 +206,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender) * float buffer. */ if(oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - float *rctf = rr->rectf; - int i; + int predivide= 0; /* no alpha */ - for (i = oglrender->sizex * oglrender->sizey; i > 0; i--, rctf+=4) { - rctf[0]= srgb_to_linearrgb(rctf[0]); - rctf[1]= srgb_to_linearrgb(rctf[1]); - rctf[2]= srgb_to_linearrgb(rctf[2]); - } + IMB_buffer_float_from_float(rr->rectf, rr->rectf, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } RE_ReleaseResult(oglrender->re); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 0bba9838005..8f04940efd6 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -45,6 +45,9 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif @@ -563,17 +566,17 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void * void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int UNUSED(row_w), float *rectf, int do_gamma_correct) { unsigned char *rect32; + int profile_from= (do_gamma_correct)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; /* copy imgw-imgh to a temporal 32 bits rect */ if(img_w<1 || img_h<1) return; rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits"); - if (do_gamma_correct) { - floatbuf_to_srgb_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); - } else { - floatbuf_to_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); - } + IMB_buffer_byte_from_float(rect32, rectf, + 4, 0, IB_PROFILE_SRGB, profile_from, predivide, + img_w, img_h, img_w, img_w); glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 39282335f46..7f99fc3ffc7 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -378,6 +378,20 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile); float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc); void IMB_color_to_bw(struct ImBuf *ibuf); +/* converting pixel buffers */ +void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from, + int channels_from, int dither, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, + int channels_from, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); + /** * Change the ordering of the color bytes pointed to by rect from * rgba to abgr. size * 4 color bytes are reordered. diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 8c5f2dcafd6..8a3f6358c5b 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -42,10 +42,10 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" -#include "BKE_colortools.h" - #include "MEM_guardedalloc.h" +/**************************** Interlace/Deinterlace **************************/ + void IMB_de_interlace(struct ImBuf *ibuf) { struct ImBuf * tbuf1, * tbuf2; @@ -100,347 +100,498 @@ void IMB_interlace(struct ImBuf *ibuf) } } +/************************* Generic Buffer Conversion *************************/ -/* assume converting from linear float to sRGB byte */ -void IMB_rect_from_float(struct ImBuf *ibuf) +MINLINE void byte_to_float_v4(float f[4], const uchar b[4]) { - /* quick method to convert floatbuf to byte */ - float *tof = (float *)ibuf->rect_float; -// int do_dither = ibuf->dither != 0.f; - float dither= ibuf->dither / 255.0f; - float srgb[4]; - int i, channels= ibuf->channels; - short profile= ibuf->profile; - unsigned char *to = (unsigned char *) ibuf->rect; - - if(tof==NULL) return; - if(to==NULL) { - imb_addrectImBuf(ibuf); - to = (unsigned char *) ibuf->rect; - } - - if(channels==1) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) - to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); + f[0] = b[0] * (1.0f/255.0f); + f[1] = b[1] * (1.0f/255.0f); + f[2] = b[2] * (1.0f/255.0f); + f[3] = b[3] * (1.0f/255.0f); +} + +MINLINE void float_to_byte_v4(uchar b[4], const float f[4]) +{ + F4TOCHAR4(f, b); +} + +MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], float dither) +{ + float tmp[4] = {f[0]+dither, f[1]+dither, f[2]+dither, f[3]+dither}; + float_to_byte_v4(b, tmp); +} + +/* float to byte pixels, output 4-channel RGBA */ +void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, + int channels_from, int dither, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + float dither_fac = dither/255.0f; + 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 + stride_from*y; + uchar *to = rect_to + stride_to*y*4; + + for(x = 0; x < width; x++, from++, to+=4) + to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]); + } } - else if (profile == IB_PROFILE_LINEAR_RGB) { - if(channels == 3) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { - srgb[0]= linearrgb_to_srgb(tof[0]); - srgb[1]= linearrgb_to_srgb(tof[1]); - srgb[2]= linearrgb_to_srgb(tof[2]); - - to[0] = FTOCHAR(srgb[0]); - to[1] = FTOCHAR(srgb[1]); - to[2] = FTOCHAR(srgb[2]); - to[3] = 255; + else if(channels_from == 3) { + /* RGB input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*3; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + for(x = 0; x < width; x++, from+=3, to+=4) { + F3TOCHAR3(from, to); + 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); + F3TOCHAR3(tmp, to); + 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); + F3TOCHAR3(tmp, to); + to[3] = 255; + } } } - else if (channels == 4) { - if (dither != 0.f) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - const float d = (BLI_frand()-0.5f)*dither; - - srgb[0]= d + linearrgb_to_srgb(tof[0]); - srgb[1]= d + linearrgb_to_srgb(tof[1]); - srgb[2]= d + linearrgb_to_srgb(tof[2]); - srgb[3]= d + tof[3]; - - to[0] = FTOCHAR(srgb[0]); - to[1] = FTOCHAR(srgb[1]); - to[2] = FTOCHAR(srgb[2]); - to[3] = FTOCHAR(srgb[3]); + } + else if(channels_from == 4) { + /* RGBA input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*4; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + if(dither) { + for(x = 0; x < width; x++, from+=4, to+=4) + float_to_byte_dither_v4(to, from, (BLI_frand()-0.5f)*dither_fac); + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) + float_to_byte_v4(to, from); + } + } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if(dither && predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_predivide_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(dither) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_predivide_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + } + 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, (BLI_frand()-0.5f)*dither_fac); + } + } + 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, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_predivide_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_v4(tmp, from); + float_to_byte_v4(to, tmp); + } } - } else { - floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); } } } - else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { - if(channels==3) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = 255; +} + +/* byte to float pixels, input and output 4-channel RGBA */ +void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* RGBA input */ + for(y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from*y*4; + float *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + for(x = 0; x < width; x++, from+=4, to+=4) + byte_to_float_v4(to, from); + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert sRGB to linear */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_predivide_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_v4(to, tmp); + } } } - else { - if (dither != 0.f) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - const float d = (BLI_frand()-0.5f)*dither; - float col[4]; - - col[0]= d + tof[0]; - col[1]= d + tof[1]; - col[2]= d + tof[2]; - col[3]= d + tof[3]; - - to[0] = FTOCHAR(col[0]); - to[1] = FTOCHAR(col[1]); - to[2] = FTOCHAR(col[2]); - to[3] = FTOCHAR(col[3]); + else if(profile_to == IB_PROFILE_SRGB) { + /* convert linear to sRGB */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_predivide_v4(to, tmp); } - } else { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = FTOCHAR(tof[3]); + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_v4(to, tmp); } } } } - /* ensure user flag is reset */ - 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) +/* 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, int predivide, + int width, int height, int stride_to, int stride_from) { - /* 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; + 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 + stride_from*y; + float *to = rect_to + stride_to*y*4; + + for(x = 0; x < width; x++, from++, to+=4) + to[0] = to[1] = to[2] = to[3] = from[0]; + } } - 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(channels_from == 3) { + /* RGB input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*3; + float *to = rect_to + 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 == 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(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 == 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 if(channels_from == 4) { + /* RGBA input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*4; + float *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(float)*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 (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 { + 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); } } } } - 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; +} + +/* byte to byte pixels, input and output 4-channel RGBA */ +void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* always RGBA input */ + for(y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from*y*4; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(uchar)*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) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_predivide_v4(tmp, tmp); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } } } - 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 if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_predivide_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } - } 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); - } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } } } } +} + +/****************************** ImBuf Conversion *****************************/ + +void IMB_rect_from_float(struct ImBuf *ibuf) +{ + int predivide= 0, profile_from; + + /* verify we have a float buffer */ + if(ibuf->rect_float==NULL) + return; + + /* create byte rect if it didn't exist yet */ + if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); + + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + IMB_buffer_byte_from_float((uchar*)ibuf->rect, ibuf->rect_float, + ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; } -static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf) +/* 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) { - float *tof = fbuf; - int i; - unsigned char *to = (unsigned char *) ibuf->rect; - - for (i = ibuf->x * ibuf->y; i > 0; i--) - { - tof[0] = ((float)to[0])*(1.0f/255.0f); - tof[1] = ((float)to[1])*(1.0f/255.0f); - tof[2] = ((float)to[2])*(1.0f/255.0f); - tof[3] = ((float)to[3])*(1.0f/255.0f); - to += 4; - tof += 4; - } -} + float *rect_float; + uchar *rect_byte; + int predivide= 0, profile_from; + + /* verify we have a float buffer */ + if(ibuf->rect_float==NULL || buffer==NULL) + return; + /* create byte rect if it didn't exist yet */ + if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); -static void imb_float_from_rect_linear(struct ImBuf *ibuf, float *fbuf) -{ - float *tof = fbuf; - int i; - unsigned char *to = (unsigned char *) ibuf->rect; - - for (i = ibuf->x * ibuf->y; i > 0; i--) - { - tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f)); - tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f)); - tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f)); - tof[3] = ((float)to[3])*(1.0f/255.0f); - to += 4; - tof += 4; - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + rect_float= ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels; + rect_byte= (uchar*)ibuf->rect + (x + y*ibuf->x)*4; + + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); + + IMB_buffer_byte_from_float(rect_byte, buffer, + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); + + /* ensure user flag is reset */ + ibuf->userflags &= ~IB_RECT_INVALID; } void IMB_float_from_rect(struct ImBuf *ibuf) { - /* quick method to convert byte to floatbuf */ - if(ibuf->rect==NULL) return; - if(ibuf->rect_float==NULL) { - if (imb_addrectfloatImBuf(ibuf) == 0) return; - } + int predivide= 0, profile_from; + + /* verify if we byte and float buffers */ + if(ibuf->rect==NULL) + return; + + if(ibuf->rect_float==NULL) + if(imb_addrectfloatImBuf(ibuf) == 0) + return; - /* Float bufs should be stored linear */ - - if (ibuf->profile != IB_PROFILE_NONE) { - /* if the image has been given a profile then we're working - * with color management in mind, so convert it to linear space */ - imb_float_from_rect_linear(ibuf, ibuf->rect_float); - } else { - imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float); - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_NONE) + profile_from = IB_PROFILE_LINEAR_RGB; + else + profile_from = IB_PROFILE_SRGB; + + /* do conversion */ + IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect, + IB_PROFILE_LINEAR_RGB, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } /* no profile conversion */ void IMB_float_from_rect_simple(struct ImBuf *ibuf) { + int predivide= 0; + if(ibuf->rect_float==NULL) imb_addrectfloatImBuf(ibuf); - imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float); + + IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } void IMB_convert_profile(struct ImBuf *ibuf, int profile) { - int ok= FALSE; - int i; - - unsigned char *rct= (unsigned char *)ibuf->rect; - float *rctf= ibuf->rect_float; + int predivide= 0, profile_from, profile_to; if(ibuf->profile == profile) return; - if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */ - if(profile == IB_PROFILE_LINEAR_RGB) { /* to */ - if(ibuf->rect_float) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { - rctf[0]= srgb_to_linearrgb(rctf[0]); - rctf[1]= srgb_to_linearrgb(rctf[1]); - rctf[2]= srgb_to_linearrgb(rctf[2]); - } - } - if(ibuf->rect) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f); - rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f); - rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f); - } - } - ok= TRUE; - } - } - else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */ - if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */ - if(ibuf->rect_float) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { - rctf[0]= linearrgb_to_srgb(rctf[0]); - rctf[1]= linearrgb_to_srgb(rctf[1]); - rctf[2]= linearrgb_to_srgb(rctf[2]); - } - } - if(ibuf->rect) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f); - rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f); - rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f); - } - } - ok= TRUE; - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + if(profile == IB_PROFILE_LINEAR_RGB) + profile_to = IB_PROFILE_LINEAR_RGB; + else if(ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_to = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + if(ibuf->rect_float) { + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } - if(ok==FALSE){ - printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile); - return; + if(ibuf->rect) { + IMB_buffer_byte_from_byte((uchar*)ibuf->rect, (uchar*)ibuf->rect, + profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } + /* set new profile */ ibuf->profile= profile; } @@ -448,18 +599,25 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile) * if the return */ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc) { - /* stupid but it works like this everywhere now */ - const short is_lin_from= (ibuf->profile != IB_PROFILE_NONE); - const short is_lin_to= (profile != IB_PROFILE_NONE); - + int predivide= 0, profile_from, profile_to; + + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_NONE) + profile_from = IB_PROFILE_LINEAR_RGB; + else + profile_from = IB_PROFILE_SRGB; + + if(profile == IB_PROFILE_NONE) + profile_to = IB_PROFILE_LINEAR_RGB; + else + profile_to = IB_PROFILE_SRGB; - if(is_lin_from == is_lin_to) { + if(profile_from == profile_to) { + /* simple case, just allocate the buffer and return */ *alloc= 0; - /* simple case, just allocate the buffer and return */ - if(ibuf->rect_float == NULL) { + if(ibuf->rect_float == NULL) IMB_float_from_rect(ibuf); - } return ibuf->rect_float; } @@ -469,42 +627,36 @@ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc) *alloc= 1; if(ibuf->rect_float == NULL) { - if(is_lin_to) { - imb_float_from_rect_linear(ibuf, fbuf); - } - else { - imb_float_from_rect_nonlinear(ibuf, fbuf); - } + IMB_buffer_float_from_byte(fbuf, (uchar*)ibuf->rect, + profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { - if(is_lin_to) { /* lin -> nonlin */ - linearrgb_to_srgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y); - } - else { /* nonlin -> lin */ - srgb_to_linearrgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y); - } + IMB_buffer_float_from_float(fbuf, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } return fbuf; } } +/**************************** Color to Grayscale *****************************/ /* no profile conversion */ void IMB_color_to_bw(struct ImBuf *ibuf) { float *rctf= ibuf->rect_float; - unsigned char *rct= (unsigned char *)ibuf->rect; + uchar *rct= (uchar*)ibuf->rect; int i; + if(rctf) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { + for(i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) rctf[0]= rctf[1]= rctf[2]= rgb_to_grayscale(rctf); - } } if(rct) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { + for(i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) rct[0]= rct[1]= rct[2]= rgb_to_grayscale_byte(rct); - } } } diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 99a36691b10..8aaf1771b68 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -606,7 +606,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf) RenderData *rd= data; bNodePreview *preview= node->preview; int xsize, ysize; - int color_manage= rd->color_mgt_flag & R_COLOR_MANAGEMENT; + int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + int dither= 0; unsigned char *rect; if(preview && stackbuf) { @@ -633,10 +635,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf) /* convert to byte for preview */ rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect"); - if(color_manage) - floatbuf_to_srgb_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); - else - floatbuf_to_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); + IMB_buffer_byte_from_float(rect, cbuf->rect, + 4, dither, IB_PROFILE_SRGB, profile_from, predivide, + xsize, ysize, xsize, xsize); free_compbuf(cbuf); if(stackbuf_use!=stackbuf) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 9920cdab039..fd7c87adea2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -62,6 +62,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= { float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) { float *rect; + int predivide= 0; *alloc= FALSE; @@ -71,7 +72,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } else { rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); + + IMB_buffer_float_from_float(rect, ibuf->rect_float, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + *alloc= TRUE; } } @@ -81,7 +86,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } else { rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); + + IMB_buffer_float_from_float(rect, ibuf->rect_float, + 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + *alloc= TRUE; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index d82cff16496..0a481629ee8 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1149,32 +1149,17 @@ void RE_ResultGet32(Render *re, unsigned int *rect) RE_AcquireResultImage(re, &rres); - if(rres.rect32) + if(rres.rect32) { memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty); + } else if(rres.rectf) { - float *fp= rres.rectf; - int tot= rres.rectx*rres.recty; - char *cp= (char *)rect; - - if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - /* Finally convert back to sRGB rendered image */ - for(;tot>0; tot--, cp+=4, fp+=4) { - cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0])); - cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1])); - cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2])); - cp[3] = FTOCHAR(fp[3]); - } - } - else { - /* Color management is off : no conversion necessary */ - for(;tot>0; tot--, cp+=4, fp+=4) { - cp[0] = FTOCHAR(fp[0]); - cp[1] = FTOCHAR(fp[1]); - cp[2] = FTOCHAR(fp[2]); - cp[3] = FTOCHAR(fp[3]); - } - } + int profile_from= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + int dither= 0; + IMB_buffer_byte_from_float((unsigned char*)rect, rres.rectf, + 4, dither, IB_PROFILE_SRGB, profile_from, predivide, + rres.rectx, rres.recty, rres.rectx, rres.rectx); } else /* else fill with black */ @@ -2567,24 +2552,18 @@ static void do_render_seq(Render * re) if(ibuf) { if(ibuf->rect_float) { + /* color management: when off ensure rectf is non-lin, since thats what the internal + * render engine delivers */ + int profile_to= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + if (!rr->rectf) rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); - /* color management: when off ensure rectf is non-lin, since thats what the internal - * render engine delivers */ - if(re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - if(ibuf->profile == IB_PROFILE_LINEAR_RGB) - memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); - else - srgb_to_linearrgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); - - } - else { - if(ibuf->profile != IB_PROFILE_LINEAR_RGB) - memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); - else - linearrgb_to_srgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); - } + IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + rr->rectx, rr->recty, rr->rectx, rr->rectx); /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 can hang around when sequence render has rendered a 32 bits one before */ -- cgit v1.2.3