void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber) { int offset; float color[4]; struct ColormanageProcessor *cm_processor; cm_processor = IMB_colormanagement_display_processor_new(this->m_viewSettings, this->m_displaySettings); for (int y = rect->ymin; y < rect->ymax; y++) { offset = (y * getWidth() + rect->xmin) * 4; for (int x = rect->xmin; x < rect->xmax; x++) { float rx = floor(x / this->m_divider); float ry = floor(y / this->m_divider); color[0] = 0.0f; color[1] = 0.0f; color[2] = 0.0f; color[3] = 1.0f; this->m_input->readSampled(color, rx, ry, COM_PS_NEAREST); IMB_colormanagement_processor_apply_v4(cm_processor, color); F4TOCHAR4(color, this->m_outputBuffer + offset); offset += 4; } } IMB_colormanagement_processor_free(cm_processor); }
void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { int i, x, y; float *fp; float rgb[3]; unsigned char *cp; int x1 = 0.5f + hist->co[0][0] * ibuf->x; int x2 = 0.5f + hist->co[1][0] * ibuf->x; int y1 = 0.5f + hist->co[0][1] * ibuf->y; int y2 = 0.5f + hist->co[1][1] * ibuf->y; struct ColormanageProcessor *cm_processor = NULL; hist->channels = 3; hist->x_resolution = 256; hist->xmax = 1.0f; /* hist->ymax = 1.0f; */ /* now do this on the operator _only_ */ if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (ibuf->rect_float) cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); for (i = 0; i < 256; i++) { x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f); y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f); if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) { hist->data_luma[i] = hist->data_r[i] = hist->data_g[i] = hist->data_b[i] = hist->data_a[i] = 0.0f; } else { if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); copy_v3_v3(rgb, fp); IMB_colormanagement_processor_apply_v3(cm_processor, rgb); hist->data_luma[i] = rgb_to_luma(rgb); hist->data_r[i] = rgb[0]; hist->data_g[i] = rgb[1]; hist->data_b[i] = rgb[2]; hist->data_a[i] = fp[3]; } else if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f; hist->data_r[i] = (float)cp[0] / 255.0f; hist->data_g[i] = (float)cp[1] / 255.0f; hist->data_b[i] = (float)cp[2] / 255.0f; hist->data_a[i] = (float)cp[3] / 255.0f; } } } if (cm_processor) IMB_colormanagement_processor_free(cm_processor); }
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; }
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { int a; unsigned int nl, na, nr, ng, nb; double divl, diva, divr, divg, divb; const unsigned char *display_buffer = NULL; unsigned int bin_lum[256] = {0}, bin_r[256] = {0}, bin_g[256] = {0}, bin_b[256] = {0}, bin_a[256] = {0}; int ycc_mode = -1; void *cache_handle = 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; } /* convert to number of lines with logarithmic scale */ scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y; CLAMP_MIN(scopes->sample_lines, 1); if (scopes->sample_full) scopes->sample_lines = ibuf->y; /* scan the image */ for (a = 0; a < 3; a++) { scopes->minmax[a][0] = 25500.0f; scopes->minmax[a][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 (ibuf->rect_float) { cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); } else { display_buffer = (const unsigned char *)IMB_display_buffer_acquire( ibuf, view_settings, display_settings, &cache_handle); } /* Keep number of threads in sync with the merge parts below. */ ScopesUpdateData data = { .scopes = scopes, . ibuf = ibuf, .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode, .bin_lum = bin_lum, .bin_r = bin_r, .bin_g = bin_g, .bin_b = bin_b, .bin_a = bin_a, }; ScopesUpdateDataChunk data_chunk = {0}; INIT_MINMAX(data_chunk.min, data_chunk.max); BLI_task_parallel_range_finalize(0, ibuf->y, &data, &data_chunk, sizeof(data_chunk), scopes_update_cb, scopes_update_finalize, ibuf->y > 256, false); /* test for nicer distribution even - non standard, leave it out for a while */ #if 0 for (a = 0; a < 256; a++) { bin_lum[a] = sqrt (bin_lum[a]); bin_r[a] = sqrt(bin_r[a]); bin_g[a] = sqrt(bin_g[a]); bin_b[a] = sqrt(bin_b[a]); bin_a[a] = sqrt(bin_a[a]); } #endif /* convert hist data to float (proportional to max count) */ nl = na = nr = nb = ng = 0; for (a = 0; a < 256; a++) { if (bin_lum[a] > nl) nl = bin_lum[a]; if (bin_r[a] > nr) nr = bin_r[a]; if (bin_g[a] > ng) ng = bin_g[a]; if (bin_b[a] > nb) nb = bin_b[a]; if (bin_a[a] > na) na = bin_a[a]; } divl = nl ? 1.0 / (double)nl : 1.0; diva = na ? 1.0 / (double)na : 1.0; divr = nr ? 1.0 / (double)nr : 1.0; divg = ng ? 1.0 / (double)ng : 1.0; divb = nb ? 1.0 / (double)nb : 1.0; for (a = 0; a < 256; a++) { scopes->hist.data_luma[a] = bin_lum[a] * divl; scopes->hist.data_r[a] = bin_r[a] * divr; scopes->hist.data_g[a] = bin_g[a] * divg; scopes->hist.data_b[a] = bin_b[a] * divb; scopes->hist.data_a[a] = bin_a[a] * diva; } if (cm_processor) IMB_colormanagement_processor_free(cm_processor); if (cache_handle) IMB_display_buffer_release(cache_handle); scopes->ok = 1; }