[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [43222] trunk/blender/source/blender: Color:

Campbell Barton ideasman42 at gmail.com
Tue Jan 10 11:39:33 CET 2012


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
<brechtvanlommel at 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-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs



-- 
- Campbell


More information about the Bf-committers mailing list