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:
authorCampbell Barton <ideasman42@gmail.com>2012-01-11 18:14:04 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-01-11 18:14:04 +0400
commitb308e613126f8c89e954705aa512a3ef6a1f551d (patch)
tree4a875450b2ba9766fbdf4914e8cb003e8132497c /source/blender/blenlib/intern
parent98bdf0274b1052efe25b6216f488d2a40fa43d1c (diff)
parentcda5d1769d71832a6b04ed6c91bac101c482e5f7 (diff)
svn merge ^/trunk/blender -r43220:43278 --accept postpone
Diffstat (limited to 'source/blender/blenlib/intern')
-rw-r--r--source/blender/blenlib/intern/math_color.c80
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c75
2 files changed, 155 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 8f5366b6317..3627b38a091 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -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 @@ void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
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;
+ }
+}
+
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index aaaa065f14d..1247632cf79 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -105,5 +105,80 @@ MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]
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 */