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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-12-28 17:29:33 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-12-28 17:29:33 +0400
commitb9ff5840a617ec836f2d09bb0f04d60e5c3b8f67 (patch)
tree8a196777f4ee32e3ee089c12b667caa2c82dec75
parent1f02209957fc8afde957b48f1be41fc399a725b0 (diff)
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.
-rw-r--r--source/blender/blenkernel/BKE_colortools.h3
-rw-r--r--source/blender/blenkernel/intern/colortools.c39
-rw-r--r--source/blender/blenlib/BLI_math_color.h29
-rw-r--r--source/blender/blenlib/intern/math_color.c51
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c109
-rw-r--r--source/blender/editors/render/render_internal.c57
-rw-r--r--source/blender/editors/render/render_opengl.c11
-rw-r--r--source/blender/editors/screen/glutil.c13
-rw-r--r--source/blender/imbuf/IMB_imbuf.h14
-rw-r--r--source/blender/imbuf/intern/divers.c750
-rw-r--r--source/blender/nodes/composite/node_composite_util.c11
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c13
-rw-r--r--source/blender/render/intern/source/pipeline.c55
13 files changed, 650 insertions, 505 deletions
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; y<y2; y++) {
- for(x=x1; x<x2; x++, rf+=4, rc+=4) {
- srgb[0]= linearrgb_to_srgb(rf[0]);
- srgb[1]= linearrgb_to_srgb(rf[1]);
- srgb[2]= linearrgb_to_srgb(rf[2]);
-
- rc[0]= FTOCHAR(srgb[0]);
- rc[1]= FTOCHAR(srgb[1]);
- rc[2]= FTOCHAR(srgb[2]);
- rc[3]= FTOCHAR(rf[3]);
- }
- }
-}
-
-void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
-{
- int x, y;
- float *rf= rectf;
- unsigned char *rc= rectc;
-
- for(y=y1; y<y2; y++) {
- for(x=x1; x<x2; x++, rf+=4, rc+=4) {
- rc[0]= FTOCHAR(rf[0]);
- rc[1]= FTOCHAR(rf[1]);
- rc[2]= FTOCHAR(rf[2]);
- rc[3]= FTOCHAR(rf[3]);
- }
- }
-}
-
-
/* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 0e33ee2be3f..7fbb4680b6d 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -34,6 +34,8 @@
extern "C" {
#endif
+#include "BLI_math_inline.h"
+
/* primaries */
#define BLI_XYZ_SMPTE 0
#define BLI_XYZ_REC709_SRGB 1
@@ -48,7 +50,7 @@ extern "C" {
#define BLI_YCC_ITU_BT601 0
#define BLI_YCC_ITU_BT709 1
#define BLI_YCC_JFIF_0_255 2
-
+
/******************* Conversion to RGB ********************/
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
@@ -70,22 +72,23 @@ unsigned int hsv_to_cpack(float h, float s, float v);
float rgb_to_grayscale(float rgb[3]);
unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]);
-/***************** Profile Transformations ********************/
+/**************** Profile Transformations *****************/
void gamma_correct(float *c, float gamma);
float rec709_to_linearrgb(float c);
float linearrgb_to_rec709(float c);
float srgb_to_linearrgb(float c);
float linearrgb_to_srgb(float c);
-void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from);
-void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
-
-/* rgba buffer convenience functions */
-void srgb_to_linearrgb_rgba_buf(float *col, int tot);
-void linearrgb_to_srgb_rgba_buf(float *col, int tot);
-void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
-void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
-
+
+MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]);
+MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]);
+
+MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]);
+MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]);
+
+MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]);
+MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]);
+
/************************** Other *************************/
int constrain_rgb(float *r, float *g, float *b);
@@ -101,6 +104,10 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o
void rgb_byte_to_float(const unsigned char *in, float *out);
void rgb_float_to_byte(const float *in, unsigned char *out);
+#ifdef BLI_MATH_INLINE_H
+#include "intern/math_color_inline.c"
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 2ef29c1ce94..8f5366b6317 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -393,57 +393,6 @@ float linearrgb_to_srgb(float c)
return 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
}
-void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from)
-{
- col_to[0] = srgb_to_linearrgb(col_from[0]);
- col_to[1] = srgb_to_linearrgb(col_from[1]);
- col_to[2] = srgb_to_linearrgb(col_from[2]);
-}
-
-void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
-{
- col_to[0] = linearrgb_to_srgb(col_from[0]);
- col_to[1] = linearrgb_to_srgb(col_from[1]);
- col_to[2] = linearrgb_to_srgb(col_from[2]);
-}
-
-/* todo, should these be moved elsewhere?, they dont belong in imbuf */
-void srgb_to_linearrgb_rgba_buf(float *col, int tot)
-{
- while(tot--) {
- srgb_to_linearrgb_v3_v3(col, col);
- col += 4;
- }
-}
-
-void linearrgb_to_srgb_rgba_buf(float *col, int tot)
-{
- while(tot--) {
- linearrgb_to_srgb_v3_v3(col, col);
- col += 4;
- }
-}
-
-void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
-{
- while(tot--) {
- srgb_to_linearrgb_v3_v3(col_to, col_from);
- col_to[3]= col_from[3];
- col_to += 4;
- col_from += 4;
- }
-}
-
-void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
-{
- while(tot--) {
- linearrgb_to_srgb_v3_v3(col_to, col_from);
- col_to[3]= col_from[3];
- col_to += 4;
- col_from += 4;
- }
-}
-
void minmax_rgb(short c[])
{
if(c[0]>255) 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; y1<ymax; y1++) {
- float *rf= rectf;
- float srgb[3];
- char *rc= rectc;
- const float dither = ibuf->dither / 255.0f;
-
- /* XXX temp. because crop offset */
- if(rectc >= (char *)(ibuf->rect)) {
- for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
- /* color management */
- if(do_color_management) {
- srgb[0]= linearrgb_to_srgb(rf[0]);
- srgb[1]= linearrgb_to_srgb(rf[1]);
- srgb[2]= linearrgb_to_srgb(rf[2]);
- }
- else {
- copy_v3_v3(srgb, rf);
- }
-
- /* dither */
- if(dither != 0.0f) {
- const float d = (BLI_frand()-0.5f)*dither;
-
- srgb[0] += d;
- srgb[1] += d;
- srgb[2] += d;
- }
-
- /* write */
- rc[0]= FTOCHAR(srgb[0]);
- rc[1]= FTOCHAR(srgb[1]);
- rc[2]= FTOCHAR(srgb[2]);
- rc[3]= FTOCHAR(rf[3]);
- }
- }
+ if(scene && (scene->r.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 */