MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
{
	float alpha, inv_alpha;

	if (linear[3] == 1.0f || linear[3] == 0.0f) {
		alpha = 1.0f;
		inv_alpha = 1.0f;
	}
	else {
		alpha = linear[3];
		inv_alpha = 1.0f / alpha;
	}

	srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha;
	srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha;
	srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha;
	srgb[3] = linear[3];
}
Exemple #2
0
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
	int x, y;
	float *rf= rectf;
	float srgb[3];
	unsigned char *rc= rectc;
	
	for(y=y1; y<y2; y++) {
		for(x=x1; x<x2; x++, rf+=4, rc+=4) {
			srgb[0]= linearrgb_to_srgb(rf[0]);
			srgb[1]= linearrgb_to_srgb(rf[1]);
			srgb[2]= linearrgb_to_srgb(rf[2]);

			rc[0]= FTOCHAR(srgb[0]);
			rc[1]= FTOCHAR(srgb[1]);
			rc[2]= FTOCHAR(srgb[2]);
			rc[3]= FTOCHAR(rf[3]);
		}
	}
}
Exemple #3
0
/* note: lift_lgg is just 2-lift, gamma_inv is 1.0/gamma */
DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain)
{
	/* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty
	 * but best keep it this way, sice testing for durian shows a similar calculation
	 * without lin/srgb conversions gives bad results (over-saturated shadows) with colors
	 * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */
	float x= (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain;

	/* prevent NaN */
	if (x < 0.f) x = 0.f;

	return powf(srgb_to_linearrgb(x), gamma_inv);
}
Exemple #4
0
void IMB_convert_profile(struct ImBuf *ibuf, int profile)
{
	int ok= FALSE;
	int i;

	unsigned char *rct= (unsigned char *)ibuf->rect;
	float *rctf= ibuf->rect_float;

	if(ibuf->profile == profile)
		return;

	if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */
		if(profile == IB_PROFILE_LINEAR_RGB) { /* to */
			if(ibuf->rect_float) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
					rctf[0]= srgb_to_linearrgb(rctf[0]);
					rctf[1]= srgb_to_linearrgb(rctf[1]);
					rctf[2]= srgb_to_linearrgb(rctf[2]);
				}
			}
			if(ibuf->rect) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
					rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
					rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
					rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
				}
			}
			ok= TRUE;
		}
	}
	else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */
		if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */
			if(ibuf->rect_float) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
					rctf[0]= linearrgb_to_srgb(rctf[0]);
					rctf[1]= linearrgb_to_srgb(rctf[1]);
					rctf[2]= linearrgb_to_srgb(rctf[2]);
				}
			}
			if(ibuf->rect) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
					rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
					rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
					rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
				}
			}
			ok= TRUE;
		}
	}

	if(ok==FALSE){
		printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile);
		return;
	}

	ibuf->profile= profile;
}
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
{
	srgb[0] = linearrgb_to_srgb(linear[0]);
	srgb[1] = linearrgb_to_srgb(linear[1]);
	srgb[2] = linearrgb_to_srgb(linear[2]);
}
Exemple #6
0
static void fill_bins(bNode* node, CompBuf* in, int* bins, int colorcor)
{
	float value[4];
	int ivalue=0;
	int x,y;

	/*fill bins */
	for(y=0; y<in->y; y++) {
		for(x=0; x<in->x; x++) {

			/* get the pixel */
			qd_getPixel(in, x, y, value);

			if(value[3] > 0.0) { /* don't count transparent pixels */
				switch(node->custom1) {
					case 1: { /* all colors */
						if(colorcor)
							linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
						rgb_tobw(value[0],value[1],value[2], &value[0]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
					case 2: { /* red channel */
						if(colorcor)
							value[0]=linearrgb_to_srgb(value[0]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
					case 3:  { /* green channel */
						if(colorcor)
							value[1]=linearrgb_to_srgb(value[1]);
						value[1]=value[1]*255; /* scale to 0-255 range */
						ivalue=(int)value[1];
						break;
					}
					case 4: /*blue channel */
					{
						if(colorcor)
							value[2]=linearrgb_to_srgb(value[2]);
						value[2]=value[2]*255; /* scale to 0-255 range */
						ivalue=(int)value[2];
						break;
					}
					case 5: /* luminence */
					{
						if(colorcor)
							linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
						rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]);
						value[0]=value[0]*255; /* scale to 0-255 range */
						ivalue=(int)value[0];
						break;
					}
				} /*end switch */

				/*clip*/
				if(ivalue<0) ivalue=0;
				if(ivalue>255) ivalue=255;

				/*put in the correct bin*/
				bins[ivalue]+=1;
			} /*end if alpha */
		}
	}	
}
Exemple #7
0
/* called inside thread! */
void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
{
	float x1, y1, *rectf= NULL;
	int ymin, ymax, xmin, xmax;
	int rymin, rxmin, do_color_management;
	char *rectc;

	/* if renrect argument, we only refresh scanlines */
	if(renrect) {
		/* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
		if(rr->renlay==NULL || renrect->ymax>=rr->recty)
			return;

		/* xmin here is first subrect x coord, xmax defines subrect width */
		xmin = renrect->xmin + rr->crop;
		xmax = renrect->xmax - xmin + rr->crop;
		if(xmax<2)
			return;

		ymin= renrect->ymin + rr->crop;
		ymax= renrect->ymax - ymin + rr->crop;
		if(ymax<2)
			return;
		renrect->ymin= renrect->ymax;

	}
	else {
		xmin = ymin = rr->crop;
		xmax = rr->rectx - 2*rr->crop;
		ymax = rr->recty - 2*rr->crop;
	}

	/* xmin ymin is in tile coords. transform to ibuf */
	rxmin= rr->tilerect.xmin + xmin;
	if(rxmin >= ibuf->x) return;
	rymin= rr->tilerect.ymin + ymin;
	if(rymin >= ibuf->y) return;

	if(rxmin + xmax > ibuf->x)
		xmax= ibuf->x - rxmin;
	if(rymin + ymax > ibuf->y)
		ymax= ibuf->y - rymin;

	if(xmax < 1 || ymax < 1) return;

	/* find current float rect for display, first case is after composit... still weak */
	if(rr->rectf)
		rectf= rr->rectf;
	else {
		if(rr->rect32)
			return;
		else {
			if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
			rectf= rr->renlay->rectf;
		}
	}
	if(rectf==NULL) return;

	if(ibuf->rect==NULL)
		imb_addrectImBuf(ibuf);
	
	rectf+= 4*(rr->rectx*ymin + xmin);
	rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);

	do_color_management = (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT));
	
	/* XXX make nice consistent functions for this */
	for(y1= 0; y1<ymax; y1++) {
		float *rf= rectf;
		float srgb[3];
		char *rc= rectc;
		const float dither = ibuf->dither / 255.0f;

		/* XXX temp. because crop offset */
		if(rectc >= (char *)(ibuf->rect)) {
			for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
				/* color management */
				if(do_color_management) {
					srgb[0]= linearrgb_to_srgb(rf[0]);
					srgb[1]= linearrgb_to_srgb(rf[1]);
					srgb[2]= linearrgb_to_srgb(rf[2]);
				}
				else {
					copy_v3_v3(srgb, rf);
				}

				/* dither */
				if(dither != 0.0f) {
					const float d = (BLI_frand()-0.5f)*dither;

					srgb[0] += d;
					srgb[1] += d;
					srgb[2] += d;
				}

				/* write */
				rc[0]= FTOCHAR(srgb[0]);
				rc[1]= FTOCHAR(srgb[1]);
				rc[2]= FTOCHAR(srgb[2]);
				rc[3]= FTOCHAR(rf[3]);
			}
		}

		rectf += 4*rr->rectx;
		rectc += 4*ibuf->x;
	}
}
Exemple #8
0
/* assume converting from linear float to sRGB byte */
void IMB_rect_from_float(struct ImBuf *ibuf)
{
	/* quick method to convert floatbuf to byte */
	float *tof = (float *)ibuf->rect_float;
//	int do_dither = ibuf->dither != 0.f;
	float dither= ibuf->dither / 255.0f;
	float srgb[4];
	int i, channels= ibuf->channels;
	short profile= ibuf->profile;
	unsigned char *to = (unsigned char *) ibuf->rect;
	
	if(tof==NULL) return;
	if(to==NULL) {
		imb_addrectImBuf(ibuf);
		to = (unsigned char *) ibuf->rect;
	}
	
	if(channels==1) {
		for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++)
			to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]);
	}
	else if (profile == IB_PROFILE_LINEAR_RGB) {
		if(channels == 3) {
			for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
				srgb[0]= linearrgb_to_srgb(tof[0]);
				srgb[1]= linearrgb_to_srgb(tof[1]);
				srgb[2]= linearrgb_to_srgb(tof[2]);

				to[0] = FTOCHAR(srgb[0]);
				to[1] = FTOCHAR(srgb[1]);
				to[2] = FTOCHAR(srgb[2]);
				to[3] = 255;
			}
		}
		else if (channels == 4) {
			if (dither != 0.f) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
					const float d = (BLI_frand()-0.5f)*dither;
					
					srgb[0]= d + linearrgb_to_srgb(tof[0]);
					srgb[1]= d + linearrgb_to_srgb(tof[1]);
					srgb[2]= d + linearrgb_to_srgb(tof[2]);
					srgb[3]= d + tof[3]; 
					
					to[0] = FTOCHAR(srgb[0]);
					to[1] = FTOCHAR(srgb[1]);
					to[2] = FTOCHAR(srgb[2]);
					to[3] = FTOCHAR(srgb[3]);
				}
			} else {
				floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x);
			}
		}
	}
	else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
		if(channels==3) {
			for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
				to[0] = FTOCHAR(tof[0]);
				to[1] = FTOCHAR(tof[1]);
				to[2] = FTOCHAR(tof[2]);
				to[3] = 255;
			}
		}
		else {
			if (dither != 0.f) {
				for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
					const float d = (BLI_frand()-0.5f)*dither;
					float col[4];

					col[0]= d + tof[0];
					col[1]= d + tof[1];
					col[2]= d + tof[2];
					col[3]= d + tof[3];

					to[0] = FTOCHAR(col[0]);
					to[1] = FTOCHAR(col[1]);
					to[2] = FTOCHAR(col[2]);
					to[3] = FTOCHAR(col[3]);
				}
			} else {
				for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
					to[0] = FTOCHAR(tof[0]);
					to[1] = FTOCHAR(tof[1]);
					to[2] = FTOCHAR(tof[2]);
					to[3] = FTOCHAR(tof[3]);
				}
			}
		}
	}
	/* ensure user flag is reset */
	ibuf->userflags &= ~IB_RECT_INVALID;
}
Exemple #9
0
MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
{
	float alpha, inv_alpha, t;
	int i;

	if (linear[3] == 1.0f || linear[3] == 0.0f) {
		linearrgb_to_srgb_ushort4(srgb, linear);
		return;
	}

	alpha = linear[3];
	inv_alpha = 1.0f / alpha;

	for (i = 0; i < 3; ++i) {
		t = linear[i] * inv_alpha;
		srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha);
	}

	srgb[3] = FTOUSHORT(linear[3]);
}