27
25
* ***** END GPL/BL DUAL LICENSE BLOCK *****
28
/** \file blender/blenkernel/intern/colortools.c
30
33
#include <string.h>
32
35
#include <stdlib.h>
39
38
#include "MEM_guardedalloc.h"
41
40
#include "DNA_color_types.h"
42
41
#include "DNA_curve_types.h"
43
#include "BLI_blenlib.h"
45
#include "BLI_utildefines.h"
44
47
#include "BKE_colortools.h"
45
48
#include "BKE_curve.h"
47
#include "BKE_utildefines.h"
49
#include "BKE_fcurve.h"
49
#include "BLI_blenlib.h"
52
52
#include "IMB_imbuf.h"
53
53
#include "IMB_imbuf_types.h"
56
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
61
unsigned char *rc= rectc;
63
for(y=y1; y<y2; y++) {
64
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
65
srgb[0]= linearrgb_to_srgb(rf[0]);
66
srgb[1]= linearrgb_to_srgb(rf[1]);
67
srgb[2]= linearrgb_to_srgb(rf[2]);
69
rc[0]= FTOCHAR(srgb[0]);
70
rc[1]= FTOCHAR(srgb[1]);
71
rc[2]= FTOCHAR(srgb[2]);
72
rc[3]= FTOCHAR(rf[3]);
77
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
81
unsigned char *rc= rectc;
83
for(y=y1; y<y2; y++) {
84
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
85
rc[0]= FTOCHAR(rf[0]);
86
rc[1]= FTOCHAR(rf[1]);
87
rc[2]= FTOCHAR(rf[2]);
88
rc[3]= FTOCHAR(rf[3]);
94
55
/* ********************************* color curve ********************* */
96
57
/* ***************** operations on full struct ************* */
168
void curvemapping_set_black_white(CurveMapping *cumap, float *black, float *white)
129
void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3])
173
VECCOPY(cumap->white, white);
175
VECCOPY(cumap->black, black);
134
copy_v3_v3(cumap->white, white);
136
copy_v3_v3(cumap->black, black);
178
if(cumap->white[a]==cumap->black[a])
138
for (a=0; a<3; a++) {
139
if (cumap->white[a]==cumap->black[a])
179
140
cumap->bwmul[a]= 0.0f;
181
142
cumap->bwmul[a]= 1.0f/(cumap->white[a] - cumap->black[a]);
342
317
/* *********************** Making the tables and display ************** */
344
319
/* reduced copy of garbled calchandleNurb() code in curve.c */
345
static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
320
static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode))
347
322
float *p1,*p2,*p3,pt[3];
348
float dx1,dy1, dx,dy, vx,vy, len,len1,len2;
350
if(bezt->h1==0 && bezt->h2==0) return;
323
float len,len_a, len_b;
324
float dvec_a[2], dvec_b[2];
326
if (bezt->h1==0 && bezt->h2==0) {
352
330
p2= bezt->vec[1];
355
333
p3= next->vec[1];
356
pt[0]= 2*p2[0]- p3[0];
357
pt[1]= 2*p2[1]- p3[1];
334
pt[0]= 2.0f*p2[0] - p3[0];
335
pt[1]= 2.0f*p2[1] - p3[1];
360
else p1= prev->vec[1];
363
343
p1= prev->vec[1];
364
pt[0]= 2*p2[0]- p1[0];
365
pt[1]= 2*p2[1]- p1[1];
344
pt[0]= 2.0f*p2[0] - p1[0];
345
pt[1]= 2.0f*p2[1] - p1[1];
368
else p3= next->vec[1];
373
len1= (float)sqrt(dx*dx+dy*dy);
378
len2= (float)sqrt(dx1*dx1+dy1*dy1);
380
if(len1==0.0f) len1=1.0f;
381
if(len2==0.0f) len2=1.0f;
383
if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
384
vx= dx1/len2 + dx/len1;
385
vy= dy1/len2 + dy/len1;
387
len= 2.5614f*(float)sqrt(vx*vx + vy*vy);
352
sub_v2_v2v2(dvec_a, p2, p1);
353
sub_v2_v2v2(dvec_b, p3, p2);
355
len_a= len_v2(dvec_a);
356
len_b= len_v2(dvec_b);
358
if (len_a==0.0f) len_a=1.0f;
359
if (len_b==0.0f) len_b=1.0f;
361
if (bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
363
tvec[0]= dvec_b[0]/len_b + dvec_a[0]/len_a;
364
tvec[1]= dvec_b[1]/len_b + dvec_a[1]/len_a;
366
len= len_v2(tvec) * 2.5614f;
390
if(bezt->h1==HD_AUTO) {
392
*(p2-3)= *p2-vx*len1;
393
*(p2-2)= *(p2+1)-vy*len1;
369
if (bezt->h1==HD_AUTO) {
371
madd_v2_v2v2fl(p2-3, p2, tvec, -len_a);
395
if(bezt->h2==HD_AUTO) {
397
*(p2+3)= *p2+vx*len2;
398
*(p2+4)= *(p2+1)+vy*len2;
373
if (bezt->h2==HD_AUTO) {
375
madd_v2_v2v2fl(p2+3, p2, tvec, len_b);
403
if(bezt->h1==HD_VECT) { /* vector */
380
if (bezt->h1==HD_VECT) { /* vector */
381
madd_v2_v2v2fl(p2-3, p2, dvec_a, -1.0f/3.0f);
409
if(bezt->h2==HD_VECT) {
413
*(p2+4)= *(p2+1)+dy1;
383
if (bezt->h2==HD_VECT) {
384
madd_v2_v2v2fl(p2+3, p2, dvec_b, 1.0f/3.0f);
418
X is presumed to be outside first or last */
419
static float curvemap_calc_extend(CurveMap *cuma, float x, float *first, float *last)
389
* X is presumed to be outside first or last */
390
static float curvemap_calc_extend(CurveMap *cuma, float x, const float first[2], const float last[2])
422
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
393
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
423
394
/* no extrapolate */
427
if(cuma->ext_in[0]==0.0f)
398
if (cuma->ext_in[0]==0.0f)
428
399
return first[1] + cuma->ext_in[1]*10000.0f;
430
401
return first[1] + cuma->ext_in[1]*(x - first[0])/cuma->ext_in[0];
433
else if(x >= last[0]) {
434
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
404
else if (x >= last[0]) {
405
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
435
406
/* no extrapolate */
439
if(cuma->ext_out[0]==0.0f)
410
if (cuma->ext_out[0]==0.0f)
440
411
return last[1] - cuma->ext_out[1]*10000.0f;
442
413
return last[1] + cuma->ext_out[1]*(x - last[0])/cuma->ext_out[0];
462
433
/* hrmf... we now rely on blender ipo beziers, these are more advanced */
463
434
bezt= MEM_callocN(cuma->totpoint*sizeof(BezTriple), "beztarr");
465
for(a=0; a<cuma->totpoint; a++) {
436
for (a=0; a<cuma->totpoint; a++) {
466
437
cuma->mintable= MIN2(cuma->mintable, cmp[a].x);
467
438
cuma->maxtable= MAX2(cuma->maxtable, cmp[a].x);
468
439
bezt[a].vec[1][0]= cmp[a].x;
469
440
bezt[a].vec[1][1]= cmp[a].y;
470
if(cmp[a].flag & CUMA_VECTOR)
441
if (cmp[a].flag & CUMA_VECTOR)
471
442
bezt[a].h1= bezt[a].h2= HD_VECT;
473
444
bezt[a].h1= bezt[a].h2= HD_AUTO;
476
for(a=0; a<cuma->totpoint; a++) {
447
for (a=0; a<cuma->totpoint; a++) {
478
449
calchandle_curvemap(bezt, NULL, bezt+1, 0);
479
else if(a==cuma->totpoint-1)
450
else if (a==cuma->totpoint-1)
480
451
calchandle_curvemap(bezt+a, bezt+a-1, NULL, 0);
482
453
calchandle_curvemap(bezt+a, bezt+a-1, bezt+a+1, 0);
485
456
/* first and last handle need correction, instead of pointing to center of next/prev,
486
we let it point to the closest handle */
487
if(cuma->totpoint>2) {
457
* we let it point to the closest handle */
458
if (cuma->totpoint>2) {
488
459
float hlen, nlen, vec[3];
490
if(bezt[0].h2==HD_AUTO) {
461
if (bezt[0].h2==HD_AUTO) {
492
463
hlen= len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
493
464
/* clip handle point */
494
VECCOPY(vec, bezt[1].vec[0]);
495
if(vec[0] < bezt[0].vec[1][0])
465
copy_v3_v3(vec, bezt[1].vec[0]);
466
if (vec[0] < bezt[0].vec[1][0])
496
467
vec[0]= bezt[0].vec[1][0];
498
469
sub_v3_v3(vec, bezt[0].vec[1]);
499
470
nlen= len_v3(vec);
500
if(nlen>FLT_EPSILON) {
471
if (nlen>FLT_EPSILON) {
501
472
mul_v3_fl(vec, hlen/nlen);
502
473
add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
503
474
sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
506
477
a= cuma->totpoint-1;
507
if(bezt[a].h2==HD_AUTO) {
478
if (bezt[a].h2==HD_AUTO) {
509
480
hlen= len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
510
481
/* clip handle point */
511
VECCOPY(vec, bezt[a-1].vec[2]);
512
if(vec[0] > bezt[a].vec[1][0])
482
copy_v3_v3(vec, bezt[a-1].vec[2]);
483
if (vec[0] > bezt[a].vec[1][0])
513
484
vec[0]= bezt[a].vec[1][0];
515
486
sub_v3_v3(vec, bezt[a].vec[1]);
516
487
nlen= len_v3(vec);
517
if(nlen>FLT_EPSILON) {
488
if (nlen>FLT_EPSILON) {
518
489
mul_v3_fl(vec, hlen/nlen);
519
490
add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
520
491
sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
524
495
/* make the bezier curve */
526
497
MEM_freeN(cuma->table);
527
498
totpoint= (cuma->totpoint-1)*CM_RESOL;
528
499
fp= allpoints= MEM_callocN(totpoint*2*sizeof(float), "table");
530
for(a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) {
501
for (a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) {
531
502
correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]);
532
503
forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2*sizeof(float));
533
504
forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2*sizeof(float));
558
529
lastpoint= allpoints + 2*(totpoint-1);
559
530
cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table");
561
for(a=0; a<=CM_TABLE; a++) {
532
for (a=0; a<=CM_TABLE; a++) {
562
533
curf= cuma->mintable + range*(float)a;
565
536
/* get the first x coordinate larger than curf */
566
while(curf >= fp[0] && fp!=lastpoint) {
537
while (curf >= fp[0] && fp!=lastpoint) {
569
if(fp==allpoints || (curf >= fp[0] && fp==lastpoint))
540
if (fp==allpoints || (curf >= fp[0] && fp==lastpoint))
570
541
cmp[a].y= curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
572
543
float fac1= fp[0] - fp[-2];
573
544
float fac2= fp[0] - curf;
574
if(fac1 > FLT_EPSILON)
545
if (fac1 > FLT_EPSILON)
604
if((cumap->flag & CUMA_PREMULLED)==0) {
575
if ((cumap->flag & CUMA_PREMULLED)==0) {
605
576
/* verify and copy */
607
if(cumap->cm[a].table==NULL)
577
for (a=0; a<3; a++) {
578
if (cumap->cm[a].table==NULL)
608
579
curvemap_make_table(cumap->cm+a, &cumap->clipr);
609
580
cumap->cm[a].premultable= cumap->cm[a].table;
610
581
cumap->cm[a].table= MEM_mallocN((CM_TABLE+1)*sizeof(CurveMapPoint), "premul table");
611
582
memcpy(cumap->cm[a].table, cumap->cm[a].premultable, (CM_TABLE+1)*sizeof(CurveMapPoint));
614
if(cumap->cm[3].table==NULL)
585
if (cumap->cm[3].table==NULL)
615
586
curvemap_make_table(cumap->cm+3, &cumap->clipr);
589
for (a=0; a<3; a++) {
620
for(b=0; b<=CM_TABLE; b++) {
591
for (b=0; b<=CM_TABLE; b++) {
621
592
cumap->cm[a].table[b].y= curvemap_evaluateF(cumap->cm+3, cumap->cm[a].table[b].y);
651
622
cumap->changed_timestamp++;
653
624
/* clamp with clip */
654
if(cumap->flag & CUMA_DO_CLIP) {
655
for(a=0; a<cuma->totpoint; a++) {
656
if(cmp[a].flag & CUMA_SELECT) {
657
if(cmp[a].x < clipr->xmin)
625
if (cumap->flag & CUMA_DO_CLIP) {
626
for (a=0; a<cuma->totpoint; a++) {
627
if (cmp[a].flag & CUMA_SELECT) {
628
if (cmp[a].x < clipr->xmin)
658
629
dx= MIN2(dx, cmp[a].x - clipr->xmin);
659
else if(cmp[a].x > clipr->xmax)
630
else if (cmp[a].x > clipr->xmax)
660
631
dx= MAX2(dx, cmp[a].x - clipr->xmax);
661
if(cmp[a].y < clipr->ymin)
632
if (cmp[a].y < clipr->ymin)
662
633
dy= MIN2(dy, cmp[a].y - clipr->ymin);
663
else if(cmp[a].y > clipr->ymax)
634
else if (cmp[a].y > clipr->ymax)
664
635
dy= MAX2(dy, cmp[a].y - clipr->ymax);
667
for(a=0; a<cuma->totpoint; a++) {
668
if(cmp[a].flag & CUMA_SELECT) {
638
for (a=0; a<cuma->totpoint; a++) {
639
if (cmp[a].flag & CUMA_SELECT) {
676
647
qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints);
678
649
/* remove doubles, threshold set on 1% of default range */
679
if(rem_doubles && cuma->totpoint>2) {
680
for(a=0; a<cuma->totpoint-1; a++) {
650
if (rem_doubles && cuma->totpoint>2) {
651
for (a=0; a<cuma->totpoint-1; a++) {
681
652
dx= cmp[a].x - cmp[a+1].x;
682
653
dy= cmp[a].y - cmp[a+1].y;
683
if( sqrt(dx*dx + dy*dy) < thresh ) {
654
if ( sqrtf(dx*dx + dy*dy) < thresh ) {
685
656
cmp[a+1].flag|= 2;
686
if(cmp[a+1].flag & CUMA_SELECT)
657
if (cmp[a+1].flag & CUMA_SELECT)
687
658
cmp[a].flag |= CUMA_SELECT;
691
if(cmp[a].flag & CUMA_SELECT)
662
if (cmp[a].flag & CUMA_SELECT)
692
663
cmp[a+1].flag |= CUMA_SELECT;
694
665
break; /* we assume 1 deletion per edit is ok */
697
if(a != cuma->totpoint-1)
668
if (a != cuma->totpoint-1)
698
669
curvemap_remove(cuma, 2);
700
671
curvemap_make_table(cuma, clipr);
713
684
/* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
714
if(fi<0.0f || fi>CM_TABLE)
685
if (fi<0.0f || fi>CM_TABLE)
715
686
return curvemap_calc_extend(cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x);
717
if(i<0) return cuma->table[0].y;
718
if(i>=CM_TABLE) return cuma->table[CM_TABLE].y;
688
if (i<0) return cuma->table[0].y;
689
if (i>=CM_TABLE) return cuma->table[CM_TABLE].y;
721
692
return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y;
728
699
CurveMap *cuma= cumap->cm+cur;
730
701
/* allocate or bail out */
731
if(cuma->table==NULL) {
702
if (cuma->table==NULL) {
732
703
curvemap_make_table(cuma, &cumap->clipr);
733
if(cuma->table==NULL)
704
if (cuma->table==NULL)
734
705
return 1.0f-value;
736
707
return curvemap_evaluateF(cuma, value);
739
710
/* vector case */
740
void curvemapping_evaluate3F(CurveMapping *cumap, float *vecout, const float *vecin)
711
void curvemapping_evaluate3F(CurveMapping *cumap, float vecout[3], const float vecin[3])
742
713
vecout[0]= curvemapping_evaluateF(cumap, 0, vecin[0]);
743
714
vecout[1]= curvemapping_evaluateF(cumap, 1, vecin[1]);
747
718
/* RGB case, no black/white points, no premult */
748
void curvemapping_evaluateRGBF(CurveMapping *cumap, float *vecout, const float *vecin)
719
void curvemapping_evaluateRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3])
750
721
vecout[0]= curvemapping_evaluateF(cumap, 0, curvemapping_evaluateF(cumap, 3, vecin[0]));
751
722
vecout[1]= curvemapping_evaluateF(cumap, 1, curvemapping_evaluateF(cumap, 3, vecin[1]));
768
739
vecout[2]= curvemap_evaluateF(cumap->cm+2, fac);
771
void colorcorrection_do_ibuf(ImBuf *ibuf, const char *profile)
773
if (ibuf->crect == NULL)
776
cmsHPROFILE imageProfile, proofingProfile;
777
cmsHTRANSFORM hTransform;
779
ibuf->crect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(int), "imbuf crect");
781
imageProfile = cmsCreate_sRGBProfile();
782
proofingProfile = cmsOpenProfileFromFile(profile, "r");
784
cmsErrorAction(LCMS_ERROR_SHOW);
786
hTransform = cmsCreateProofingTransform(imageProfile, TYPE_RGBA_8, imageProfile, TYPE_RGBA_8,
788
INTENT_ABSOLUTE_COLORIMETRIC,
789
INTENT_ABSOLUTE_COLORIMETRIC,
790
cmsFLAGS_SOFTPROOFING);
792
cmsDoTransform(hTransform, ibuf->rect, ibuf->crect, ibuf->x * ibuf->y);
794
cmsDeleteTransform(hTransform);
795
cmsCloseProfile(imageProfile);
796
cmsCloseProfile(proofingProfile);
798
ibuf->crect = ibuf->rect;
803
743
/* only used for image editor curves */
804
744
void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf)
864
if(cumap->black[0]!=0.0f) return 1;
865
if(cumap->black[1]!=0.0f) return 1;
866
if(cumap->black[2]!=0.0f) return 1;
867
if(cumap->white[0]!=1.0f) return 1;
868
if(cumap->white[1]!=1.0f) return 1;
869
if(cumap->white[2]!=1.0f) return 1;
804
if (cumap->black[0]!=0.0f) return 1;
805
if (cumap->black[1]!=0.0f) return 1;
806
if (cumap->black[2]!=0.0f) return 1;
807
if (cumap->white[0]!=1.0f) return 1;
808
if (cumap->white[1]!=1.0f) return 1;
809
if (cumap->white[2]!=1.0f) return 1;
871
for(a=0; a<CM_TOT; a++) {
872
if(cumap->cm[a].curve) {
873
if(cumap->cm[a].totpoint!=2) return 1;
811
for (a=0; a<CM_TOT; a++) {
812
if (cumap->cm[a].curve) {
813
if (cumap->cm[a].totpoint!=2) return 1;
875
if(cumap->cm[a].curve[0].x != 0.0f) return 1;
876
if(cumap->cm[a].curve[0].y != 0.0f) return 1;
877
if(cumap->cm[a].curve[1].x != 1.0f) return 1;
878
if(cumap->cm[a].curve[1].y != 1.0f) return 1;
815
if (cumap->cm[a].curve[0].x != 0.0f) return 1;
816
if (cumap->cm[a].curve[0].y != 0.0f) return 1;
817
if (cumap->cm[a].curve[1].x != 1.0f) return 1;
818
if (cumap->cm[a].curve[1].y != 1.0f) return 1;
920
860
DO_INLINE int get_bin_float(float f)
922
int bin= (int)(f*255);
862
int bin= (int)((f*255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */
924
864
/* note: clamp integer instead of float to avoid problems with NaN */
925
865
CLAMP(bin, 0, 255);
927
//return (int) (((f + 0.25) / 1.5) * 255);
932
DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, float *rgb, float *ycc)
870
DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, const float rgb[3], const float ycc[3])
1036
979
scopes->waveform_3= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
1037
980
scopes->vecscope= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
1039
if (ibuf->rect_float)
1040
983
rf = ibuf->rect_float;
1041
else if (ibuf->rect)
1042
985
rc = (unsigned char *)ibuf->rect;
1044
987
for (y = 0; y < ibuf->y; y++) {
1045
988
if (savedlines<scopes->sample_lines && y>=((savedlines)*ibuf->y)/(scopes->sample_lines+1)) {
1048
994
for (x = 0; x < ibuf->x; x++) {
1050
if (ibuf->rect_float) {
1051
997
if (use_color_management)
1052
998
linearrgb_to_srgb_v3_v3(rgb, rf);
1054
1000
copy_v3_v3(rgb, rf);
1056
else if (ibuf->rect) {
1057
1003
for (c=0; c<3; c++)
1058
1004
rgb[c] = rc[c] * INV_255;
1061
1007
/* we still need luma for histogram */
1062
luma = 0.299*rgb[0] + 0.587*rgb[1] + 0.114 * rgb[2];
1008
luma = rgb_to_luma(rgb);
1064
1010
/* check for min max */
1065
if(ycc_mode == -1 ) {
1011
if (ycc_mode == -1 ) {
1066
1012
for (c=0; c<3; c++) {
1067
1013
if (rgb[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgb[c];
1068
1014
if (rgb[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgb[c];