This commit has a problem with converting alpha with opengl rendering (color seems to work ok).
This #define is the cause; #define USHORTTOUCHAR(val) ((unsigned char)(((val)+0x80)>>8)) An alpha of 1.0 converts with FTOUSHORT --> 65535. But (65535+0x80)>>8 == 256, which wraps back to 0 for unsigned chars. While I found this with opengl render I expect this could be an issue for any use of IMB_buffer_byte_from_float The line this happens on is source/blender/imbuf/intern/divers.c:298, calling ushort_to_byte_v4 On Mon, Jan 9, 2012 at 12:56 AM, Brecht Van Lommel <brechtvanlom...@pandora.be> wrote: > Revision: 43222 > > http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=43222 > Author: blendix > Date: 2012-01-08 13:55:53 +0000 (Sun, 08 Jan 2012) > Log Message: > ----------- > Color: > > * Accelerated sRGB <=> linear conversion using lookup table, this can speed up > loading of images in the compositor and simple renders quite a bit. > * Dithering now uses the Floyd-Steinberg algorithm. Previously it would simply > randomize each pixel slightly, adding noise, now that should be reduced. > > Patch #29309 by David M. > > Modified Paths: > -------------- > trunk/blender/source/blender/blenlib/BLI_math_color.h > trunk/blender/source/blender/blenlib/BLI_utildefines.h > trunk/blender/source/blender/blenlib/intern/math_color.c > trunk/blender/source/blender/blenlib/intern/math_color_inline.c > trunk/blender/source/blender/imbuf/intern/divers.c > > Modified: trunk/blender/source/blender/blenlib/BLI_math_color.h > =================================================================== > --- trunk/blender/source/blender/blenlib/BLI_math_color.h 2012-01-08 > 13:09:09 UTC (rev 43221) > +++ trunk/blender/source/blender/blenlib/BLI_math_color.h 2012-01-08 > 13:55:53 UTC (rev 43222) > @@ -89,6 +89,8 @@ > 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]); > > +void BLI_init_srgb_conversion(void); > + > /************************** Other *************************/ > > int constrain_rgb(float *r, float *g, float *b); > @@ -97,13 +99,13 @@ > void rgb_float_set_hue_float_offset(float * rgb, float hue_offset); > void rgb_byte_set_hue_float_offset(unsigned char * rgb, float hue_offset); > > +void rgb_byte_to_float(const unsigned char *in, float *out); > +void rgb_float_to_byte(const float *in, unsigned char *out); > + > /***************** lift/gamma/gain / ASC-CDL conversion *****************/ > > void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, > float *offset, float *slope, float *power); > > -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 > > Modified: trunk/blender/source/blender/blenlib/BLI_utildefines.h > =================================================================== > --- trunk/blender/source/blender/blenlib/BLI_utildefines.h 2012-01-08 > 13:09:09 UTC (rev 43221) > +++ trunk/blender/source/blender/blenlib/BLI_utildefines.h 2012-01-08 > 13:55:53 UTC (rev 43222) > @@ -108,6 +108,7 @@ > > #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 USHORTTOUCHAR(val) ((unsigned char)(((val)+0x80)>>8)) > #define F3TOCHAR3(v2, v1) { > \ > (v1)[0]= FTOCHAR((v2[0])); > \ > (v1)[1]= FTOCHAR((v2[1])); > \ > > Modified: trunk/blender/source/blender/blenlib/intern/math_color.c > =================================================================== > --- trunk/blender/source/blender/blenlib/intern/math_color.c 2012-01-08 > 13:09:09 UTC (rev 43221) > +++ trunk/blender/source/blender/blenlib/intern/math_color.c 2012-01-08 > 13:55:53 UTC (rev 43222) > @@ -30,7 +30,11 @@ > > #include <assert.h> > > +#include "MEM_guardedalloc.h" > + > #include "BLI_math.h" > +#include "BLI_rand.h" > +#include "BLI_utildefines.h" > > void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b) > { > @@ -480,3 +484,79 @@ > rgb_float_set_hue_float_offset(rgb_float, hue_offset); > rgb_float_to_byte(rgb_float, rgb); > } > + > + > +/* fast sRGB conversion > + * LUT from linear float to 16-bit short > + * based on http://mysite.verizon.net/spitzak/conversion/ > + */ > + > +float BLI_color_from_srgb_table[256]; > +unsigned short BLI_color_to_srgb_table[0x10000]; > + > +static unsigned short hipart(const float f) > +{ > + union { > + float f; > + unsigned short us[2]; > + } tmp; > + > + tmp.f = f; > + > +#ifdef __BIG_ENDIAN__ > + return tmp.us[0]; > +#else > + return tmp.us[1]; > +#endif > +} > + > +static float index_to_float(const unsigned short i) > +{ > + union { > + float f; > + unsigned short us[2]; > + } tmp; > + > + /* positive and negative zeros, and all gradual underflow, turn into > zero: */ > + if (i<0x80 || (i >= 0x8000 && i < 0x8080)) return 0; > + /* All NaN's and infinity turn into the largest possible legal float: > */ > + if (i>=0x7f80 && i<0x8000) return FLT_MAX; > + if (i>=0xff80) return -FLT_MAX; > + > +#ifdef __BIG_ENDIAN__ > + tmp.us[0] = i; > + tmp.us[1] = 0x8000; > +#else > + tmp.us[0] = 0x8000; > + tmp.us[1] = i; > +#endif > + > + return tmp.f; > +} > + > +void BLI_init_srgb_conversion(void) > +{ > + static int initialized= 0; > + int i, b; > + > + if (initialized) return; > + initialized = 1; > + > + /* Fill in the lookup table to convert floats to bytes: */ > + for (i = 0; i < 0x10000; i++) { > + float f = linearrgb_to_srgb(index_to_float(i))*255.0f; > + if (f <= 0) BLI_color_to_srgb_table[i] = 0; > + else if (f < 255) BLI_color_to_srgb_table[i] = (unsigned > short)(f*0x100+.5); > + else BLI_color_to_srgb_table[i] = 0xff00; > + } > + > + /* Fill in the lookup table to convert bytes to float: */ > + for (b = 0; b <= 255; b++) { > + float f = srgb_to_linearrgb(((float)b)*(1.0f/255.0f)); > + BLI_color_from_srgb_table[b] = f; > + i = hipart(f); > + /* replace entries so byte->float->byte does not change the > data: */ > + BLI_color_to_srgb_table[i] = b*0x100; > + } > +} > + > > Modified: trunk/blender/source/blender/blenlib/intern/math_color_inline.c > =================================================================== > --- trunk/blender/source/blender/blenlib/intern/math_color_inline.c > 2012-01-08 13:09:09 UTC (rev 43221) > +++ trunk/blender/source/blender/blenlib/intern/math_color_inline.c > 2012-01-08 13:55:53 UTC (rev 43222) > @@ -105,5 +105,80 @@ > srgb[3] = linear[3]; > } > > +/* LUT accelerated conversions */ > + > +extern float BLI_color_from_srgb_table[256]; > +extern unsigned short BLI_color_to_srgb_table[0x10000]; > + > +MINLINE unsigned short to_srgb_table_lookup(const float f) > +{ > + union { > + float f; > + unsigned short us[2]; > + } tmp; > + tmp.f = f; > +#ifdef __BIG_ENDIAN__ > + return BLI_color_to_srgb_table[tmp.us[0]]; > +#else > + return BLI_color_to_srgb_table[tmp.us[1]]; > +#endif > +} > + > +MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float > linear[4]) > +{ > + srgb[0] = to_srgb_table_lookup(linear[0]); > + srgb[1] = to_srgb_table_lookup(linear[1]); > + srgb[2] = to_srgb_table_lookup(linear[2]); > + srgb[3] = FTOUSHORT(linear[3]); > +} > + > +MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], > const float linear[4]) > +{ > + float alpha, inv_alpha, t; > + int i; > + > + if(linear[3] == 1.0f || linear[3] == 0.0f) { > + linearrgb_to_srgb_ushort4(srgb, linear); > + return; > + } > + > + alpha = linear[3]; > + inv_alpha = 1.0f/alpha; > + > + for(i=0; i<3; ++i) { > + t = linear[i] * inv_alpha; > + srgb[i] = (t < 1.0f)? to_srgb_table_lookup(t) * alpha : > FTOUSHORT(linearrgb_to_srgb(t) * alpha); > + } > + > + srgb[3] = FTOUSHORT(linear[3]); > +} > + > +MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char > srgb[4]) > +{ > + linear[0] = BLI_color_from_srgb_table[srgb[0]]; > + linear[1] = BLI_color_from_srgb_table[srgb[1]]; > + linear[2] = BLI_color_from_srgb_table[srgb[2]]; > + linear[3] = srgb[3] * (1.0f/255.0f); > +} > + > +MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const > unsigned char srgb[4]) > +{ > + float alpha, inv_alpha; > + int i; > + > + if(srgb[3] == 255 || srgb[3] == 0) { > + srgb_to_linearrgb_uchar4(linear, srgb); > + return; > + } > + > + alpha = srgb[3] * (1.0f/255.0f); > + inv_alpha = 1.0f/alpha; > + > + for(i=0; i<3; ++i) > + linear[i] = linearrgb_to_srgb(srgb[i] * inv_alpha) * alpha; > + > + linear[3] = alpha; > +} > + > #endif /* BLI_MATH_COLOR_INLINE_H */ > > > Modified: trunk/blender/source/blender/imbuf/intern/divers.c > =================================================================== > --- trunk/blender/source/blender/imbuf/intern/divers.c 2012-01-08 13:09:09 > UTC (rev 43221) > +++ trunk/blender/source/blender/imbuf/intern/divers.c 2012-01-08 13:55:53 > UTC (rev 43222) > @@ -46,9 +46,9 @@ > > /**************************** Interlace/Deinterlace > **************************/ > > -void IMB_de_interlace(struct ImBuf *ibuf) > +void IMB_de_interlace(ImBuf *ibuf) > { > - struct ImBuf * tbuf1, * tbuf2; > + ImBuf * tbuf1, * tbuf2; > > if (ibuf == NULL) return; > if (ibuf->flags & IB_fields) return; > @@ -73,9 +73,9 @@ > ibuf->y /= 2; > } > > -void IMB_interlace(struct ImBuf *ibuf) > +void IMB_interlace(ImBuf *ibuf) > { > - struct ImBuf * tbuf1, * tbuf2; > + ImBuf * tbuf1, * tbuf2; > > if (ibuf == NULL) return; > ibuf->flags &= ~IB_fields; > @@ -100,14 +100,76 @@ > } > } > > +/************************* Floyd-Steinberg dithering > *************************/ > + > +typedef struct DitherContext { > + int *error_buf, *e; > + int v[4], v0[4], v1[4]; > + float f; > +} DitherContext; > + > +DitherContext *create_dither_context(int w, float factor) > +{ > + DitherContext *di; > + int i; > + > + di= MEM_callocN(sizeof(DitherContext), "dithering context"); > + di->f= factor / 16.0f; > + di->error_buf= MEM_callocN(4*(w+1)*sizeof(int), "dithering error"); > + di->e= di->error_buf; > + > + for(i=0; i<4; ++i) > + di->v[i]= di->v0[i]= di->v1[i]= 1024.0f*(BLI_frand()-0.5f); > + > + return di; > +} > + > +static void clear_dither_context(DitherContext *di) > +{ > + MEM_freeN(di->error_buf); > + MEM_freeN(di); > +} > + > +static void dither_finish_row(DitherContext *di) > +{ > + int i; > + > + for(i=0; i<4; i++) > + di->v[i]= di->v0[i]= di->v1[i] = 0; > + > + di->e= di->error_buf; > +} > + > +MINLINE unsigned char dither_value(unsigned short v_in, DitherContext *di, > int i) > +{ > + int dv, d2; > + unsigned char v_out; > + > + di->v[i] = v_in + (2*di->v[i] + di->e[4]) * di->f; > + CLAMP(di->v[i], 0, 0xFF00); > + v_out = USHORTTOUCHAR(di->v[i]); > + di->v[i] -= v_out<<8; > + dv = di->v[i]; > + d2 = di->v[i]<<1; > + di->v[i] += d2; > + *(di->e++) = di->v[i] + di->v0[i]; > + di->v[i] += d2; > + > + di->v0[i] = di->v[i] + di->v1[i]; > + di->v1[i] = dv; > + di->v[i] += d2; > + > + return v_out; > +} > + > /************************* Generic Buffer Conversion > *************************/ > > MINLINE void byte_to_float_v4(float f[4], const uchar b[4]) > { > - 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); > + 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]) > @@ -115,38 +177,56 @@ > F4TOCHAR4(f, b); > } > > -MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], float > dither) > +MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4]) > { > - float tmp[4] = {f[0]+dither, f[1]+dither, f[2]+dither, f[3]+dither}; > - float_to_byte_v4(b, tmp); > + b[0]= USHORTTOUCHAR(us[0]); > + b[1]= USHORTTOUCHAR(us[1]); > + b[2]= USHORTTOUCHAR(us[2]); > + b[3]= USHORTTOUCHAR(us[3]); > } > > +MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short > us[4], DitherContext *di) > +{ > + b[0]= dither_value(us[0], di, 0); > + b[1]= dither_value(us[0], di, 1); > + b[2]= dither_value(us[0], di, 2); > + b[3]= dither_value(us[0], di, 3); > +} > + > +MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], > DitherContext *di) > +{ > + unsigned short us[4] = {FTOUSHORT(f[0]), FTOUSHORT(f[1]), > FTOUSHORT(f[2]), FTOUSHORT(f[3])}; > + ushort_to_byte_dither_v4(b, us, di); > +} > + > /* float to byte pixels, output 4-channel RGBA */ > > @@ Diff output truncated at 10240 characters. @@ > _______________________________________________ > Bf-blender-cvs mailing list > bf-blender-...@blender.org > http://lists.blender.org/mailman/listinfo/bf-blender-cvs -- - Campbell _______________________________________________ Bf-committers mailing list Bf-committers@blender.org http://lists.blender.org/mailman/listinfo/bf-committers