Ejemplo n.º 1
0
/* if view_settings, it also applies this to byte buffers */
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);
	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;
	}

	/* 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 *)IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
	}
	
	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 = 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 (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);
	if (cache_handle)
		IMB_display_buffer_release(cache_handle);
	
	scopes->ok = 1;
}
Ejemplo n.º 2
0
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 = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];

			/* 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;
}
Ejemplo n.º 3
0
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;
	}
}