Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 00021 * The Original Code is: some of this file. 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 * */ 00025 00031 #include <assert.h> 00032 00033 #include "MEM_guardedalloc.h" 00034 00035 #include "BLI_math.h" 00036 #include "BLI_rand.h" 00037 #include "BLI_utildefines.h" 00038 00039 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b) 00040 { 00041 int i; 00042 float f, p, q, t; 00043 00044 if(s==0.0f) { 00045 *r = v; 00046 *g = v; 00047 *b = v; 00048 } 00049 else { 00050 h= (h - floorf(h))*6.0f; 00051 00052 i = (int)floorf(h); 00053 f = h - i; 00054 p = v*(1.0f-s); 00055 q = v*(1.0f-(s*f)); 00056 t = v*(1.0f-(s*(1.0f-f))); 00057 00058 switch (i) { 00059 case 0 : 00060 *r = v; 00061 *g = t; 00062 *b = p; 00063 break; 00064 case 1 : 00065 *r = q; 00066 *g = v; 00067 *b = p; 00068 break; 00069 case 2 : 00070 *r = p; 00071 *g = v; 00072 *b = t; 00073 break; 00074 case 3 : 00075 *r = p; 00076 *g = q; 00077 *b = v; 00078 break; 00079 case 4 : 00080 *r = t; 00081 *g = p; 00082 *b = v; 00083 break; 00084 case 5 : 00085 *r = v; 00086 *g = p; 00087 *b = q; 00088 break; 00089 } 00090 } 00091 } 00092 00093 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv) 00094 { 00095 float y, u, v; 00096 y= 0.299f*r + 0.587f*g + 0.114f*b; 00097 u=-0.147f*r - 0.289f*g + 0.436f*b; 00098 v= 0.615f*r - 0.515f*g - 0.100f*b; 00099 00100 *ly=y; 00101 *lu=u; 00102 *lv=v; 00103 } 00104 00105 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb) 00106 { 00107 float r, g, b; 00108 r=y+1.140f*v; 00109 g=y-0.394f*u - 0.581f*v; 00110 b=y+2.032f*u; 00111 00112 *lr=r; 00113 *lg=g; 00114 *lb=b; 00115 } 00116 00117 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */ 00118 /* Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */ 00119 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace) 00120 { 00121 float sr,sg, sb; 00122 float y = 128.f, cr = 128.f, cb = 128.f; 00123 00124 sr=255.0f*r; 00125 sg=255.0f*g; 00126 sb=255.0f*b; 00127 00128 switch (colorspace) { 00129 case BLI_YCC_ITU_BT601 : 00130 y=(0.257f*sr)+(0.504f*sg)+(0.098f*sb)+16.0f; 00131 cb=(-0.148f*sr)-(0.291f*sg)+(0.439f*sb)+128.0f; 00132 cr=(0.439f*sr)-(0.368f*sg)-(0.071f*sb)+128.0f; 00133 break; 00134 case BLI_YCC_ITU_BT709 : 00135 y=(0.183f*sr)+(0.614f*sg)+(0.062f*sb)+16.0f; 00136 cb=(-0.101f*sr)-(0.338f*sg)+(0.439f*sb)+128.0f; 00137 cr=(0.439f*sr)-(0.399f*sg)-(0.040f*sb)+128.0f; 00138 break; 00139 case BLI_YCC_JFIF_0_255 : 00140 y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb); 00141 cb=(-0.16874f*sr)-(0.33126f*sg)+(0.5f*sb)+128.0f; 00142 cr=(0.5f*sr)-(0.41869f*sg)-(0.08131f*sb)+128.0f; 00143 break; 00144 default: 00145 assert(!"invalid colorspace"); 00146 } 00147 00148 *ly=y; 00149 *lcb=cb; 00150 *lcr=cr; 00151 } 00152 00153 00154 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */ 00155 /* RGB outputs are in the range 0 - 1.0f */ 00156 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */ 00157 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace) 00158 { 00159 float r = 128.f, g = 128.f, b = 128.f; 00160 00161 switch (colorspace) { 00162 case BLI_YCC_ITU_BT601 : 00163 r=1.164f*(y-16.0f)+1.596f*(cr-128.0f); 00164 g=1.164f*(y-16.0f)-0.813f*(cr-128.0f)-0.392f*(cb-128.0f); 00165 b=1.164f*(y-16.0f)+2.017f*(cb-128.0f); 00166 break; 00167 case BLI_YCC_ITU_BT709 : 00168 r=1.164f*(y-16.0f)+1.793f*(cr-128.0f); 00169 g=1.164f*(y-16.0f)-0.534f*(cr-128.0f)-0.213f*(cb-128.0f); 00170 b=1.164f*(y-16.0f)+2.115f*(cb-128.0f); 00171 break; 00172 case BLI_YCC_JFIF_0_255 : 00173 r=y+1.402f*cr - 179.456f; 00174 g=y-0.34414f*cb - 0.71414f*cr + 135.45984f; 00175 b=y+1.772f*cb - 226.816f; 00176 break; 00177 default: 00178 assert(!"invalid colorspace"); 00179 } 00180 *lr=r/255.0f; 00181 *lg=g/255.0f; 00182 *lb=b/255.0f; 00183 } 00184 00185 void hex_to_rgb(char *hexcol, float *r, float *g, float *b) 00186 { 00187 unsigned int ri, gi, bi; 00188 00189 if (hexcol[0] == '#') hexcol++; 00190 00191 if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi)==3) { 00192 *r = ri / 255.0f; 00193 *g = gi / 255.0f; 00194 *b = bi / 255.0f; 00195 CLAMP(*r, 0.0f, 1.0f); 00196 CLAMP(*g, 0.0f, 1.0f); 00197 CLAMP(*b, 0.0f, 1.0f); 00198 } 00199 else { 00200 /* avoid using un-initialized vars */ 00201 *r= *g= *b= 0.0f; 00202 } 00203 } 00204 00205 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) 00206 { 00207 float h, s, v; 00208 float cmax, cmin, cdelta; 00209 float rc, gc, bc; 00210 00211 cmax = r; 00212 cmin = r; 00213 cmax = (g>cmax ? g:cmax); 00214 cmin = (g<cmin ? g:cmin); 00215 cmax = (b>cmax ? b:cmax); 00216 cmin = (b<cmin ? b:cmin); 00217 00218 v = cmax; /* value */ 00219 if (cmax != 0.0f) 00220 s = (cmax - cmin)/cmax; 00221 else { 00222 s = 0.0f; 00223 } 00224 if (s == 0.0f) 00225 h = -1.0f; 00226 else { 00227 cdelta = cmax-cmin; 00228 rc = (cmax-r)/cdelta; 00229 gc = (cmax-g)/cdelta; 00230 bc = (cmax-b)/cdelta; 00231 if (r==cmax) 00232 h = bc-gc; 00233 else 00234 if (g==cmax) 00235 h = 2.0f+rc-bc; 00236 else 00237 h = 4.0f+gc-rc; 00238 h = h*60.0f; 00239 if (h < 0.0f) 00240 h += 360.0f; 00241 } 00242 00243 *ls = s; 00244 *lh = h / 360.0f; 00245 if(*lh < 0.0f) *lh= 0.0f; 00246 *lv = v; 00247 } 00248 00249 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv) 00250 { 00251 float orig_h= *lh; 00252 float orig_s= *ls; 00253 00254 rgb_to_hsv(r, g, b, lh, ls, lv); 00255 00256 if(*lv <= 0.0f) { 00257 *lh= orig_h; 00258 *ls= orig_s; 00259 } 00260 else if (*ls <= 0.0f) { 00261 *lh= orig_h; 00262 } 00263 00264 if(*lh==0.0f && orig_h >= 1.0f) { 00265 *lh= 1.0f; 00266 } 00267 } 00268 00269 /*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */ 00270 00271 void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace) 00272 { 00273 switch (colorspace) { 00274 case BLI_XYZ_SMPTE: 00275 *r = (3.50570f * xc) + (-1.73964f * yc) + (-0.544011f * zc); 00276 *g = (-1.06906f * xc) + (1.97781f * yc) + (0.0351720f * zc); 00277 *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f * zc); 00278 break; 00279 case BLI_XYZ_REC709_SRGB: 00280 *r = (3.240476f * xc) + (-1.537150f * yc) + (-0.498535f * zc); 00281 *g = (-0.969256f * xc) + (1.875992f * yc) + (0.041556f * zc); 00282 *b = (0.055648f * xc) + (-0.204043f * yc) + (1.057311f * zc); 00283 break; 00284 case BLI_XYZ_CIE: 00285 *r = (2.28783848734076f * xc) + (-0.833367677835217f * yc) + (-0.454470795871421f * zc); 00286 *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc); 00287 *b = (0.00572040983140966f * xc) + (-0.0159068485104036f * yc) + (1.0101864083734f * zc); 00288 break; 00289 } 00290 } 00291 00292 /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so. 00293 for that reason it is sensitive for endianness... with this function it works correctly 00294 */ 00295 00296 unsigned int hsv_to_cpack(float h, float s, float v) 00297 { 00298 short r, g, b; 00299 float rf, gf, bf; 00300 unsigned int col; 00301 00302 hsv_to_rgb(h, s, v, &rf, &gf, &bf); 00303 00304 r= (short)(rf*255.0f); 00305 g= (short)(gf*255.0f); 00306 b= (short)(bf*255.0f); 00307 00308 col= ( r + (g*256) + (b*256*256) ); 00309 return col; 00310 } 00311 00312 00313 unsigned int rgb_to_cpack(float r, float g, float b) 00314 { 00315 int ir, ig, ib; 00316 00317 ir= (int)floor(255.0f*r); 00318 if(ir<0) ir= 0; else if(ir>255) ir= 255; 00319 ig= (int)floor(255.0f*g); 00320 if(ig<0) ig= 0; else if(ig>255) ig= 255; 00321 ib= (int)floor(255.0f*b); 00322 if(ib<0) ib= 0; else if(ib>255) ib= 255; 00323 00324 return (ir+ (ig*256) + (ib*256*256)); 00325 } 00326 00327 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b) 00328 { 00329 00330 *r= (float)((col)&0xFF); 00331 *r /= 255.0f; 00332 00333 *g= (float)(((col)>>8)&0xFF); 00334 *g /= 255.0f; 00335 00336 *b= (float)(((col)>>16)&0xFF); 00337 *b /= 255.0f; 00338 } 00339 00340 void rgb_byte_to_float(const unsigned char in[3], float out[3]) 00341 { 00342 out[0]= ((float)in[0]) / 255.0f; 00343 out[1]= ((float)in[1]) / 255.0f; 00344 out[2]= ((float)in[2]) / 255.0f; 00345 } 00346 00347 void rgb_float_to_byte(const float in[3], unsigned char out[3]) 00348 { 00349 int r, g, b; 00350 00351 r= (int)(in[0] * 255.0f); 00352 g= (int)(in[1] * 255.0f); 00353 b= (int)(in[2] * 255.0f); 00354 00355 out[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r); 00356 out[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g); 00357 out[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b); 00358 } 00359 00360 /* ********************************* color transforms ********************************* */ 00361 00362 00363 void gamma_correct(float *c, float gamma) 00364 { 00365 *c = powf((*c), gamma); 00366 } 00367 00368 float rec709_to_linearrgb(float c) 00369 { 00370 if (c < 0.081f) 00371 return (c < 0.0f)? 0.0f: c * (1.0f/4.5f); 00372 else 00373 return powf((c + 0.099f)*(1.0f/1.099f), (1.0f/0.45f)); 00374 } 00375 00376 float linearrgb_to_rec709(float c) 00377 { 00378 if (c < 0.018f) 00379 return (c < 0.0f)? 0.0f: c * 4.5f; 00380 else 00381 return 1.099f * powf(c, 0.45f) - 0.099f; 00382 } 00383 00384 float srgb_to_linearrgb(float c) 00385 { 00386 if (c < 0.04045f) 00387 return (c < 0.0f)? 0.0f: c * (1.0f/12.92f); 00388 else 00389 return powf((c + 0.055f)*(1.0f/1.055f), 2.4f); 00390 } 00391 00392 float linearrgb_to_srgb(float c) 00393 { 00394 if (c < 0.0031308f) 00395 return (c < 0.0f)? 0.0f: c * 12.92f; 00396 else 00397 return 1.055f * powf(c, 1.0f/2.4f) - 0.055f; 00398 } 00399 00400 void minmax_rgb(short c[]) 00401 { 00402 if(c[0]>255) c[0]=255; 00403 else if(c[0]<0) c[0]=0; 00404 if(c[1]>255) c[1]=255; 00405 else if(c[1]<0) c[1]=0; 00406 if(c[2]>255) c[2]=255; 00407 else if(c[2]<0) c[2]=0; 00408 } 00409 00410 /*If the requested RGB shade contains a negative weight for 00411 one of the primaries, it lies outside the color gamut 00412 accessible from the given triple of primaries. Desaturate 00413 it by adding white, equal quantities of R, G, and B, enough 00414 to make RGB all positive. The function returns 1 if the 00415 components were modified, zero otherwise.*/ 00416 int constrain_rgb(float *r, float *g, float *b) 00417 { 00418 float w; 00419 00420 /* Amount of white needed is w = - min(0, *r, *g, *b) */ 00421 00422 w = (0 < *r) ? 0 : *r; 00423 w = (w < *g) ? w : *g; 00424 w = (w < *b) ? w : *b; 00425 w = -w; 00426 00427 /* Add just enough white to make r, g, b all positive. */ 00428 00429 if (w > 0) { 00430 *r += w; *g += w; *b += w; 00431 return 1; /* Color modified to fit RGB gamut */ 00432 } 00433 00434 return 0; /* Color within RGB gamut */ 00435 } 00436 00437 float rgb_to_grayscale(const float rgb[3]) 00438 { 00439 return 0.3f*rgb[0] + 0.58f*rgb[1] + 0.12f*rgb[2]; 00440 } 00441 00442 unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]) 00443 { 00444 return (76*(unsigned short)rgb[0] + 148*(unsigned short)rgb[1] + 31*(unsigned short)rgb[2]) / 255; 00445 } 00446 00447 float rgb_to_luma(const float rgb[3]) 00448 { 00449 return 0.299f*rgb[0] + 0.587f*rgb[1] + 0.114f*rgb[2]; 00450 } 00451 00452 unsigned char rgb_to_luma_byte(const unsigned char rgb[3]) 00453 { 00454 return (76*(unsigned short)rgb[0] + 150*(unsigned short)rgb[1] + 29*(unsigned short)rgb[2]) / 255; 00455 } 00456 00457 /* ********************************* lift/gamma/gain / ASC-CDL conversion ********************************* */ 00458 00459 void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power) 00460 { 00461 int c; 00462 for(c=0; c<3; c++) { 00463 offset[c]= lift[c]*gain[c]; 00464 slope[c]= gain[c]*(1.0f-lift[c]); 00465 if(gamma[c] == 0) 00466 power[c]= FLT_MAX; 00467 else 00468 power[c]= 1.0f/gamma[c]; 00469 } 00470 } 00471 00472 /* ******************************************** other ************************************************* */ 00473 00474 /* Applies an hue offset to a float rgb color */ 00475 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset) 00476 { 00477 float hsv[3]; 00478 00479 rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); 00480 00481 hsv[0]+= hue_offset; 00482 if(hsv[0] > 1.0f) hsv[0] -= 1.0f; 00483 else if(hsv[0] < 0.0f) hsv[0] += 1.0f; 00484 00485 hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); 00486 } 00487 00488 /* Applies an hue offset to a byte rgb color */ 00489 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset) 00490 { 00491 float rgb_float[3]; 00492 00493 rgb_byte_to_float(rgb, rgb_float); 00494 rgb_float_set_hue_float_offset(rgb_float, hue_offset); 00495 rgb_float_to_byte(rgb_float, rgb); 00496 } 00497 00498 00499 /* fast sRGB conversion 00500 * LUT from linear float to 16-bit short 00501 * based on http://mysite.verizon.net/spitzak/conversion/ 00502 */ 00503 00504 float BLI_color_from_srgb_table[256]; 00505 unsigned short BLI_color_to_srgb_table[0x10000]; 00506 00507 static unsigned short hipart(const float f) 00508 { 00509 union { 00510 float f; 00511 unsigned short us[2]; 00512 } tmp; 00513 00514 tmp.f = f; 00515 00516 #ifdef __BIG_ENDIAN__ 00517 return tmp.us[0]; 00518 #else 00519 return tmp.us[1]; 00520 #endif 00521 } 00522 00523 static float index_to_float(const unsigned short i) 00524 { 00525 union { 00526 float f; 00527 unsigned short us[2]; 00528 } tmp; 00529 00530 /* positive and negative zeros, and all gradual underflow, turn into zero: */ 00531 if (i<0x80 || (i >= 0x8000 && i < 0x8080)) return 0; 00532 /* All NaN's and infinity turn into the largest possible legal float: */ 00533 if (i>=0x7f80 && i<0x8000) return FLT_MAX; 00534 if (i>=0xff80) return -FLT_MAX; 00535 00536 #ifdef __BIG_ENDIAN__ 00537 tmp.us[0] = i; 00538 tmp.us[1] = 0x8000; 00539 #else 00540 tmp.us[0] = 0x8000; 00541 tmp.us[1] = i; 00542 #endif 00543 00544 return tmp.f; 00545 } 00546 00547 void BLI_init_srgb_conversion(void) 00548 { 00549 static int initialized= 0; 00550 int i, b; 00551 00552 if (initialized) return; 00553 initialized = 1; 00554 00555 /* Fill in the lookup table to convert floats to bytes: */ 00556 for (i = 0; i < 0x10000; i++) { 00557 float f = linearrgb_to_srgb(index_to_float(i))*255.0f; 00558 if (f <= 0) BLI_color_to_srgb_table[i] = 0; 00559 else if (f < 255) BLI_color_to_srgb_table[i] = (unsigned short)(f*0x100+.5); 00560 else BLI_color_to_srgb_table[i] = 0xff00; 00561 } 00562 00563 /* Fill in the lookup table to convert bytes to float: */ 00564 for (b = 0; b <= 255; b++) { 00565 float f = srgb_to_linearrgb(((float)b)*(1.0f/255.0f)); 00566 BLI_color_from_srgb_table[b] = f; 00567 i = hipart(f); 00568 /* replace entries so byte->float->byte does not change the data: */ 00569 BLI_color_to_srgb_table[i] = b*0x100; 00570 } 00571 } 00572