static void do_chroma_distance_matte(bNode *node, float *out, float *in) { NodeChroma *c= (NodeChroma *)node->storage; float tolerance=c->t1; float fper=c->t2; /* get falloff amount over tolerance size */ float falloff=(1.0f-fper) * tolerance; float y_key, cb_key, cr_key; float y_pix, cb_pix, cr_pix; float distance; float alpha; /*convert key to chroma colorspace */ rgb_to_ycc(c->key[0], c->key[1], c->key[2], &y_key, &cb_key, &cr_key, BLI_YCC_JFIF_0_255); /* normalize the values */ cb_key=cb_key/255.0f; cr_key=cr_key/255.0f; /*convert pixel to chroma colorspace */ rgb_to_ycc(in[0], in[1], in[2], &y_pix, &cb_pix, &cr_pix, BLI_YCC_JFIF_0_255); /*normalize the values */ cb_pix=cb_pix/255.0f; cr_pix=cr_pix/255.0f; distance=sqrt((cb_key-cb_pix)*(cb_key-cb_pix) + (cr_key-cr_pix)*(cr_key-cr_pix)); copy_v3_v3(out, in); if (distance <= tolerance) { if (distance <= falloff) { alpha = 0.0f; } else { /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/ alpha=(distance-falloff)/(tolerance-falloff); } /*only change if more transparent than before */ if (alpha < in[3]) { /*clamp*/ if (alpha < 0.0f) alpha = 0.0f; if (alpha > 1.0f) alpha = 1.0f; out[3]=alpha; } else { /* leave as before */ out[3]=in[3]; } } }
static void do_rgba_to_ycca_normalized(bNode *node, float *out, float *in) { /*normalize to the range -1.0 to 1.0) */ rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]); out[0]=((out[0])-16)/255.0; out[1]=((out[1])-128)/255.0; out[2]=((out[2])-128)/255.0; out[3]=in[3]; }
static void do_sepycca_jfif(bNode *UNUSED(node), float *out, float *in) { float y, cb, cr; rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); /*divided by 255 to normalize for viewing in */ out[0]= y/255.0; out[1]= cb/255.0; out[2]= cr/255.0; out[3]= in[3]; }
void ConvertRGBToYCCOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { float inputColor[4]; float color[3]; this->m_inputOperation->read(inputColor, x, y, sampler); rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode); /* divided by 255 to normalize for viewing in */ /* R,G,B --> Y,Cb,Cr */ mul_v3_v3fl(output, color, 1.0f / 255.0f); output[3] = inputColor[3]; }
static void do_rgba_to_ycca_normalized(bNode *UNUSED(node), float *out, float *in) { rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); //normalize to 0..1.0 out[0]=out[0]/255.0; out[1]=out[1]/255.0; out[2]=out[2]/255.0; //rescale to -1.0..1.0 out[0]=(out[0]*2.0)-1.0; out[1]=(out[1]*2.0)-1.0; out[2]=(out[2]*2.0)-1.0; // out[0]=((out[0])-16)/255.0; // out[1]=((out[1])-128)/255.0; // out[2]=((out[2])-128)/255.0; out[3]=in[3]; }
void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) { int x, y, c; unsigned int n, nl; double div, divl; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_r, *bin_g, *bin_b, *bin_lum; int savedlines, saveline; float rgb[3], ycc[3], luma; int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (scopes->ok == 1) return; if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f; /* hmmmm */ if (!(ELEM(ibuf->channels, 3, 4))) return; scopes->hist.channels = 3; scopes->hist.x_resolution = 256; switch (scopes->wavefrm_mode) { case SCOPES_WAVEFRM_RGB: ycc_mode = -1; break; case SCOPES_WAVEFRM_LUMA: case SCOPES_WAVEFRM_YCC_JPEG: ycc_mode = BLI_YCC_JFIF_0_255; break; case SCOPES_WAVEFRM_YCC_601: ycc_mode = BLI_YCC_ITU_BT601; break; case SCOPES_WAVEFRM_YCC_709: ycc_mode = BLI_YCC_ITU_BT709; break; } /* temp table to count pix value for histo */ bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); /* convert to number of lines with logarithmic scale */ scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y; if (scopes->sample_full) scopes->sample_lines = ibuf->y; /* scan the image */ savedlines = 0; for (c = 0; c < 3; c++) { scopes->minmax[c][0] = 25500.0f; scopes->minmax[c][1] = -25500.0f; } scopes->waveform_tot = ibuf->x * scopes->sample_lines; if (scopes->waveform_1) MEM_freeN(scopes->waveform_1); if (scopes->waveform_2) MEM_freeN(scopes->waveform_2); if (scopes->waveform_3) MEM_freeN(scopes->waveform_3); if (scopes->vecscope) MEM_freeN(scopes->vecscope); scopes->waveform_1 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1"); scopes->waveform_2 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2"); scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3"); scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel"); if (is_float) rf = ibuf->rect_float; else rc = (unsigned char *)ibuf->rect; for (y = 0; y < ibuf->y; y++) { if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) { saveline = 1; } else { saveline = 0; } for (x = 0; x < ibuf->x; x++) { if (is_float) { if (use_color_management) linearrgb_to_srgb_v3_v3(rgb, rf); else copy_v3_v3(rgb, rf); } else { for (c = 0; c < 3; c++) rgb[c] = rc[c] * INV_255; } /* we still need luma for histogram */ luma = rgb_to_luma(rgb); /* check for min max */ if (ycc_mode == -1) { for (c = 0; c < 3; c++) { if (rgb[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgb[c]; if (rgb[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgb[c]; } } else { rgb_to_ycc(rgb[0], rgb[1], rgb[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode); for (c = 0; c < 3; c++) { ycc[c] *= INV_255; if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c]; if (ycc[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = ycc[c]; } } /* increment count for histo*/ bin_r[get_bin_float(rgb[0])] += 1; bin_g[get_bin_float(rgb[1])] += 1; bin_b[get_bin_float(rgb[2])] += 1; bin_lum[get_bin_float(luma)] += 1; /* save sample if needed */ if (saveline) { const float fx = (float)x / (float)ibuf->x; const int idx = 2 * (ibuf->x * savedlines + x); save_sample_line(scopes, idx, fx, rgb, ycc); } rf += ibuf->channels; rc += ibuf->channels; } if (saveline) savedlines += 1; } /* convert hist data to float (proportional to max count) */ n = 0; nl = 0; for (x = 0; x < 256; x++) { if (bin_r[x] > n) n = bin_r[x]; if (bin_g[x] > n) n = bin_g[x]; if (bin_b[x] > n) n = bin_b[x]; if (bin_lum[x] > nl) nl = bin_lum[x]; } div = 1.0 / (double)n; divl = 1.0 / (double)nl; for (x = 0; x < 256; x++) { scopes->hist.data_r[x] = bin_r[x] * div; scopes->hist.data_g[x] = bin_g[x] * div; scopes->hist.data_b[x] = bin_b[x] * div; scopes->hist.data_luma[x] = bin_lum[x] * divl; } MEM_freeN(bin_r); MEM_freeN(bin_g); MEM_freeN(bin_b); MEM_freeN(bin_lum); scopes->ok = 1; }
static void node_composit_exec_sepycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* input no image? then only color operation */ if(in[0]->data==NULL) { float y, cb, cr; switch(node->custom1) { case 1: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT709); break; case 2: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); break; case 0: default: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT601); break; } /*divided by 255 to normalize for viewing in */ out[0]->vec[0] = y/255.0; out[1]->vec[0] = cb/255.0; out[2]->vec[0] = cr/255.0; out[3]->vec[0] = in[0]->vec[3]; } else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) { /* make copy of buffer so input buffer doesn't get corrupted */ CompBuf *cbuf= dupalloc_compbuf(in[0]->data); CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA); /* convert the RGB stackbuf to an HSV representation */ switch(node->custom1) { case 1: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_709, CB_RGBA); break; case 2: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_jfif, CB_RGBA); break; case 0: default: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_601, CB_RGBA); break; } /* separate each of those channels */ if(out[0]->hasoutput) out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R); if(out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G); if(out[2]->hasoutput) out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B); if(out[3]->hasoutput) out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A); /*not used anymore */ if(cbuf2!=cbuf) free_compbuf(cbuf2); free_compbuf(cbuf); } }
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { int x, y, c; unsigned int nl, na, nr, ng, nb; double divl, diva, divr, divg, divb; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; int savedlines, saveline; float rgba[4], ycc[3], luma; int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); struct ColormanageProcessor *cm_processor = NULL; if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (scopes->ok == 1) return; if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f; /* hmmmm */ if (!(ELEM(ibuf->channels, 3, 4))) return; scopes->hist.channels = 3; scopes->hist.x_resolution = 256; switch (scopes->wavefrm_mode) { case SCOPES_WAVEFRM_RGB: ycc_mode = -1; break; case SCOPES_WAVEFRM_LUMA: case SCOPES_WAVEFRM_YCC_JPEG: ycc_mode = BLI_YCC_JFIF_0_255; break; case SCOPES_WAVEFRM_YCC_601: ycc_mode = BLI_YCC_ITU_BT601; break; case SCOPES_WAVEFRM_YCC_709: ycc_mode = BLI_YCC_ITU_BT709; break; } /* temp table to count pix value for histogram */ bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_a = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); /* convert to number of lines with logarithmic scale */ scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y; if (scopes->sample_full) scopes->sample_lines = ibuf->y; /* scan the image */ savedlines = 0; for (c = 0; c < 3; c++) { scopes->minmax[c][0] = 25500.0f; scopes->minmax[c][1] = -25500.0f; } scopes->waveform_tot = ibuf->x * scopes->sample_lines; if (scopes->waveform_1) MEM_freeN(scopes->waveform_1); if (scopes->waveform_2) MEM_freeN(scopes->waveform_2); if (scopes->waveform_3) MEM_freeN(scopes->waveform_3); if (scopes->vecscope) MEM_freeN(scopes->vecscope); scopes->waveform_1 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1"); scopes->waveform_2 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2"); scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3"); scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel"); if (is_float) rf = ibuf->rect_float; else rc = (unsigned char *)ibuf->rect; if (ibuf->rect_float) cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); for (y = 0; y < ibuf->y; y++) { if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) { saveline = 1; } else { saveline = 0; } for (x = 0; x < ibuf->x; x++) { if (is_float) { copy_v4_v4(rgba, rf); IMB_colormanagement_processor_apply_v4(cm_processor, rgba); } else { for (c = 0; c < 4; c++) rgba[c] = rc[c] * INV_255; } /* we still need luma for histogram */ luma = rgb_to_luma(rgba); /* check for min max */ if (ycc_mode == -1) { for (c = 0; c < 3; c++) { if (rgba[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgba[c]; if (rgba[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgba[c]; } } else { rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode); for (c = 0; c < 3; c++) { ycc[c] *= INV_255; if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c]; if (ycc[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = ycc[c]; } } /* increment count for histo*/ bin_lum[get_bin_float(luma)] += 1; bin_r[get_bin_float(rgba[0])] += 1; bin_g[get_bin_float(rgba[1])] += 1; bin_b[get_bin_float(rgba[2])] += 1; bin_a[get_bin_float(rgba[3])] += 1; /* save sample if needed */ if (saveline) { const float fx = (float)x / (float)ibuf->x; const int idx = 2 * (ibuf->x * savedlines + x); save_sample_line(scopes, idx, fx, rgba, ycc); } rf += ibuf->channels; rc += ibuf->channels; } if (saveline) savedlines += 1; } /* test for nicer distribution even - non standard, leave it out for a while */ #if 0 for (x = 0; x < 256; x++) { bin_lum[x] = sqrt (bin_lum[x]); bin_r[x] = sqrt(bin_r[x]); bin_g[x] = sqrt(bin_g[x]); bin_b[x] = sqrt(bin_b[x]); bin_a[x] = sqrt(bin_a[x]); } #endif /* convert hist data to float (proportional to max count) */ nl = na = nr = nb = ng = 0; for (x = 0; x < 256; x++) { if (bin_lum[x] > nl) nl = bin_lum[x]; if (bin_r[x] > nr) nr = bin_r[x]; if (bin_g[x] > ng) ng = bin_g[x]; if (bin_b[x] > nb) nb = bin_b[x]; if (bin_a[x] > na) na = bin_a[x]; } divl = 1.0 / (double)nl; diva = 1.0 / (double)na; divr = 1.0 / (double)nr; divg = 1.0 / (double)ng; divb = 1.0 / (double)nb; for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; scopes->hist.data_r[x] = bin_r[x] * divr; scopes->hist.data_g[x] = bin_g[x] * divg; scopes->hist.data_b[x] = bin_b[x] * divb; scopes->hist.data_a[x] = bin_a[x] * diva; } MEM_freeN(bin_lum); MEM_freeN(bin_r); MEM_freeN(bin_g); MEM_freeN(bin_b); MEM_freeN(bin_a); if (cm_processor) IMB_colormanagement_processor_free(cm_processor); scopes->ok = 1; }
static void scopes_update_cb(void *userdata, void *userdata_chunk, const int y, const int UNUSED(threadid)) { const ScopesUpdateData *data = userdata; Scopes *scopes = data->scopes; const ImBuf *ibuf = data->ibuf; struct ColormanageProcessor *cm_processor = data->cm_processor; const unsigned char *display_buffer = data->display_buffer; const int ycc_mode = data->ycc_mode; ScopesUpdateDataChunk *data_chunk = userdata_chunk; unsigned int *bin_lum = data_chunk->bin_lum; unsigned int *bin_r = data_chunk->bin_r; unsigned int *bin_g = data_chunk->bin_g; unsigned int *bin_b = data_chunk->bin_b; unsigned int *bin_a = data_chunk->bin_a; float *min = data_chunk->min; float *max = data_chunk->max; const float *rf = NULL; const unsigned char *rc = NULL; const int rows_per_sample_line = ibuf->y / scopes->sample_lines; const int savedlines = y / rows_per_sample_line; const bool do_sample_line = (savedlines < scopes->sample_lines) && (y % rows_per_sample_line) == 0; const bool is_float = (ibuf->rect_float != NULL); if (is_float) rf = ibuf->rect_float + ((size_t)y) * ibuf->x * ibuf->channels; else { rc = display_buffer + ((size_t)y) * ibuf->x * ibuf->channels; } for (int x = 0; x < ibuf->x; x++) { float rgba[4], ycc[3], luma; if (is_float) { switch (ibuf->channels) { case 4: copy_v4_v4(rgba, rf); IMB_colormanagement_processor_apply_v4(cm_processor, rgba); break; case 3: copy_v3_v3(rgba, rf); IMB_colormanagement_processor_apply_v3(cm_processor, rgba); rgba[3] = 1.0f; break; case 2: copy_v3_fl(rgba, rf[0]); rgba[3] = rf[1]; break; case 1: copy_v3_fl(rgba, rf[0]); rgba[3] = 1.0f; break; default: BLI_assert(0); } } else { for (int c = 4; c--;) rgba[c] = rc[c] * INV_255; } /* we still need luma for histogram */ luma = IMB_colormanagement_get_luminance(rgba); /* check for min max */ if (ycc_mode == -1) { minmax_v3v3_v3(min, max, rgba); } else { rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode); mul_v3_fl(ycc, INV_255); minmax_v3v3_v3(min, max, ycc); } /* increment count for histo*/ bin_lum[get_bin_float(luma)]++; bin_r[get_bin_float(rgba[0])]++; bin_g[get_bin_float(rgba[1])]++; bin_b[get_bin_float(rgba[2])]++; bin_a[get_bin_float(rgba[3])]++; /* save sample if needed */ if (do_sample_line) { const float fx = (float)x / (float)ibuf->x; const int idx = 2 * (ibuf->x * savedlines + x); save_sample_line(scopes, idx, fx, rgba, ycc); } rf += ibuf->channels; rc += ibuf->channels; } }