/** same as #curvemapping_evaluate_premulRGBF * but black/bwmul are passed as args for the compositor * where they can change per pixel. * * Use in conjunction with #curvemapping_set_black_white_ex * * \param black Use instead of cumap->black * \param bwmul Use instead of cumap->bwmul */ void curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, float vecout[3], const float vecin[3], const float black[3], const float bwmul[3]) { vecout[0] = curvemap_evaluateF(&cumap->cm[0], (vecin[0] - black[0]) * bwmul[0]); vecout[1] = curvemap_evaluateF(&cumap->cm[1], (vecin[1] - black[1]) * bwmul[1]); vecout[2] = curvemap_evaluateF(&cumap->cm[2], (vecin[2] - black[2]) * bwmul[2]); }
/* RGB with black/white points and premult. tables are checked */ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3]) { float fac; fac = (vecin[0] - cumap->black[0]) * cumap->bwmul[0]; vecout[0] = curvemap_evaluateF(cumap->cm, fac); fac = (vecin[1] - cumap->black[1]) * cumap->bwmul[1]; vecout[1] = curvemap_evaluateF(cumap->cm + 1, fac); fac = (vecin[2] - cumap->black[2]) * cumap->bwmul[2]; vecout[2] = curvemap_evaluateF(cumap->cm + 2, fac); }
/* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */ static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value) { if (!cuma->table) { BKE_report(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap"); return 0.0f; } return curvemap_evaluateF(cuma, value); }
/* only used for image editor curves */ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { ImBuf *tmpbuf; int pixel; float *pix_in; float col[3]; int stride = 4; float *pix_out; if (ibuf == NULL) return; if (ibuf->rect_float == NULL) IMB_float_from_rect(ibuf); else if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); if (!ibuf->rect || !ibuf->rect_float) return; /* work on a temp buffer, so can color manage afterwards. * No worse off memory wise than comp nodes */ tmpbuf = IMB_dupImBuf(ibuf); curvemapping_premultiply(cumap, 0); pix_in = ibuf->rect_float; pix_out = tmpbuf->rect_float; if (ibuf->channels) stride = ibuf->channels; for (pixel = ibuf->x * ibuf->y; pixel > 0; pixel--, pix_in += stride, pix_out += stride) { if (stride < 3) { col[0] = curvemap_evaluateF(cumap->cm, *pix_in); pix_out[1] = pix_out[2] = pix_out[3] = pix_out[0] = col[0]; } else { curvemapping_evaluate_premulRGBF(cumap, col, pix_in); pix_out[0] = col[0]; pix_out[1] = col[1]; pix_out[2] = col[2]; if (stride > 3) pix_out[3] = pix_in[3]; else pix_out[3] = 1.f; } } IMB_rect_from_float(tmpbuf); SWAP(unsigned int *, tmpbuf->rect, ibuf->rect); IMB_freeImBuf(tmpbuf); curvemapping_premultiply(cumap, 1); }
/* works with curve 'cur' */ float curvemapping_evaluateF(CurveMapping *cumap, int cur, float value) { CurveMap *cuma = cumap->cm + cur; /* allocate or bail out */ if (cuma->table == NULL) { curvemap_make_table(cuma, &cumap->clipr); if (cuma->table == NULL) return 1.0f - value; } return curvemap_evaluateF(cuma, value); }
/* it uses a flag to prevent premul or free to happen twice */ void curvemapping_premultiply(CurveMapping *cumap, int restore) { int a; if (restore) { if (cumap->flag & CUMA_PREMULLED) { for (a = 0; a < 3; a++) { MEM_freeN(cumap->cm[a].table); cumap->cm[a].table = cumap->cm[a].premultable; cumap->cm[a].premultable = NULL; copy_v2_v2(cumap->cm[a].ext_in, cumap->cm[a].premul_ext_in); copy_v2_v2(cumap->cm[a].ext_out, cumap->cm[a].premul_ext_out); zero_v2(cumap->cm[a].premul_ext_in); zero_v2(cumap->cm[a].premul_ext_out); } cumap->flag &= ~CUMA_PREMULLED; } } else { if ((cumap->flag & CUMA_PREMULLED) == 0) { /* verify and copy */ for (a = 0; a < 3; a++) { if (cumap->cm[a].table == NULL) curvemap_make_table(cumap->cm + a, &cumap->clipr); cumap->cm[a].premultable = cumap->cm[a].table; cumap->cm[a].table = MEM_mallocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "premul table"); memcpy(cumap->cm[a].table, cumap->cm[a].premultable, (CM_TABLE + 1) * sizeof(CurveMapPoint)); } if (cumap->cm[3].table == NULL) curvemap_make_table(cumap->cm + 3, &cumap->clipr); /* premul */ for (a = 0; a < 3; a++) { int b; for (b = 0; b <= CM_TABLE; b++) { cumap->cm[a].table[b].y = curvemap_evaluateF(cumap->cm + 3, cumap->cm[a].table[b].y); } copy_v2_v2(cumap->cm[a].premul_ext_in, cumap->cm[a].ext_in); copy_v2_v2(cumap->cm[a].premul_ext_out, cumap->cm[a].ext_out); mul_v2_v2(cumap->cm[a].ext_in, cumap->cm[3].ext_in); mul_v2_v2(cumap->cm[a].ext_out, cumap->cm[3].ext_out); } cumap->flag |= CUMA_PREMULLED; } } }
/* works with curve 'cur' */ float curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value) { const CurveMap *cuma = cumap->cm + cur; float val = curvemap_evaluateF(cuma, value); /* account for clipping */ if (cumap->flag & CUMA_DO_CLIP) { if (val < cumap->curr.ymin) val = cumap->curr.ymin; else if (val > cumap->curr.ymax) val = cumap->curr.ymax; } return val; }
/* RGB case, no black/white points, no premult */ void curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { vecout[0] = curvemap_evaluateF(&cumap->cm[0], curvemap_evaluateF(&cumap->cm[3], vecin[0])); vecout[1] = curvemap_evaluateF(&cumap->cm[1], curvemap_evaluateF(&cumap->cm[3], vecin[1])); vecout[2] = curvemap_evaluateF(&cumap->cm[2], curvemap_evaluateF(&cumap->cm[3], vecin[2])); }
/* works with curve 'cur' */ float curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value) { const CurveMap *cuma = cumap->cm + cur; return curvemap_evaluateF(cuma, value); }