static void draw_zebra_float(ImBuf *src, ImBuf *ibuf, float perc)
{
	float limit = perc / 100.0f;
	const float *p = src->rect_float;
	unsigned char *o = (unsigned char *) ibuf->rect;
	int x;
	int y;

	for (y = 0; y < ibuf->y; y++) {
		for (x = 0; x < ibuf->x; x++) {
			float r = *p++;
			float g = *p++;
			float b = *p++;
			float a = *p++;

			if (r >= limit || g >= limit || b >= limit) {
				if (((x + y) & 0x08) != 0) {
					r = -r;
					g = -g;
					b = -b;
				}
			}

			*o++ = FTOCHAR(r);
			*o++ = FTOCHAR(g);
			*o++ = FTOCHAR(b);
			*o++ = FTOCHAR(a);
		}
	}
}
예제 #2
0
/* MultiresBake callback for normals' baking
   general idea:
     - find coord and normal of point with specified UV in hi-res mesh
     - multiply it by tangmat
     - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *UNUSED(bake_data),
                                   const int face_index, const int lvl, const float st[2],
                                   float tangmat[3][3], const int x, const int y)
{
	MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;
	Image *ima= mtface[face_index].tpage;
	ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
	float uv[2], *st0, *st1, *st2, *st3;
	int pixel= ibuf->x*y + x;
	float n[3], vec[3], tmp[3]= {0.5, 0.5, 0.5};

	lores_dm->getFace(lores_dm, face_index, &mface);

	st0= mtface[face_index].uv[0];
	st1= mtface[face_index].uv[1];
	st2= mtface[face_index].uv[2];

	if(mface.v4) {
		st3= mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	} else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm, lvl, face_index, uv[0], uv[1], NULL, n);

	mul_v3_m3v3(vec, tangmat, n);
	normalize_v3(vec);
	mul_v3_fl(vec, 0.5);
	add_v3_v3(vec, tmp);

	if(ibuf->rect_float) {
		float *rrgbf= ibuf->rect_float + pixel*4;
		rrgbf[0]= vec[0];
		rrgbf[1]= vec[1];
		rrgbf[2]= vec[2];
		rrgbf[3]= 1.0f;

		ibuf->userflags= IB_RECT_INVALID;
	} else {
		char *rrgb= (char*)ibuf->rect + pixel*4;
		rrgb[0]= FTOCHAR(vec[0]);
		rrgb[1]= FTOCHAR(vec[1]);
		rrgb[2]= FTOCHAR(vec[2]);
		rrgb[3]= 255;
	}
}
예제 #3
0
/* same as above, byte version */
void curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3])
{
	float vecin[3], vecout[3];

	vecin[0] = (float) vecin_byte[0] / 255.0f;
	vecin[1] = (float) vecin_byte[1] / 255.0f;
	vecin[2] = (float) vecin_byte[2] / 255.0f;

	curvemapping_evaluate_premulRGBF(cumap, vecout, vecin);

	vecout_byte[0] = FTOCHAR(vecout[0]);
	vecout_byte[1] = FTOCHAR(vecout[1]);
	vecout_byte[2] = FTOCHAR(vecout[2]);
}
예제 #4
0
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
	int x, y;
	float *rf= rectf;
	unsigned char *rc= rectc;
	
	for(y=y1; y<y2; y++) {
		for(x=x1; x<x2; x++, rf+=4, rc+=4) {
			rc[0]= FTOCHAR(rf[0]);
			rc[1]= FTOCHAR(rf[1]);
			rc[2]= FTOCHAR(rf[2]);
			rc[3]= FTOCHAR(rf[3]);
		}
	}
}
예제 #5
0
static void apply_heights_data(void *bake_data)
{
	MHeightBakeData *height_data= (MHeightBakeData*)bake_data;
	ImBuf *ibuf= BKE_image_get_ibuf(height_data->ima, NULL);
	int x, y, i;
	float height, *heights= height_data->heights;
	float min= height_data->height_min, max= height_data->height_max;

	for(x= 0; x<ibuf->x; x++) {
		for(y =0; y<ibuf->y; y++) {
			i= ibuf->x*y + x;

			if(((char*)ibuf->userdata)[i] != FILTER_MASK_USED)
				continue;

			if(ibuf->rect_float) {
				float *rrgbf= ibuf->rect_float + i*4;

				if(max-min > 1e-5f) height= (heights[i]-min)/(max-min);
				else height= 0;

				rrgbf[0]=rrgbf[1]=rrgbf[2]= height;
			} else {
				char *rrgb= (char*)ibuf->rect + i*4;

				if(max-min > 1e-5f) height= (heights[i]-min)/(max-min);
				else height= 0;

				rrgb[0]=rrgb[1]=rrgb[2]= FTOCHAR(height);
			}
		}
	}

	ibuf->userflags= IB_RECT_INVALID;
}
예제 #6
0
static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
{
	Image *ima = ptr->id.data;
	ImBuf *ibuf;
	void *lock;
	int i, size;

	ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);

	if (ibuf) {
		size = ibuf->x * ibuf->y * ibuf->channels;

		if (ibuf->rect_float) {
			memcpy(ibuf->rect_float, values, sizeof(float) * size);
		}
		else {
			for (i = 0; i < size; i++)
				((unsigned char *)ibuf->rect)[i] = FTOCHAR(values[i]);
		}

		ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
	}

	BKE_image_release_ibuf(ima, ibuf, lock);
}
예제 #7
0
void TextMarker_color_set(PointerRNA *ptr, const float values[4])
{
	TextMarker *data= (TextMarker*)(ptr->data);
	int i;

	for(i=0; i<4; i++) {
		data->color[i]= FTOCHAR(values[i]);
	}
}
예제 #8
0
MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di, float s, float t)
{
	float dither_value = dither_random_value(s, t) * 0.005f * di->dither;

	b[0] = ftochar(dither_value + f[0]);
	b[1] = ftochar(dither_value + f[1]);
	b[2] = ftochar(dither_value + f[2]);
	b[3] = FTOCHAR(f[3]);
}
/* Byte equivalent of IMB_colormanagement_get_luminance(). */
unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3])
{
	float rgbf[3];
	float val;

	rgb_uchar_to_float(rgbf, rgb);
	val = dot_v3v3(imbuf_luma_coefficients, rgbf);

	return FTOCHAR(val);
}
예제 #10
0
void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
{
	int stride = mVData->getStride(0);
	if (stride == 0) stride = 3;

	switch (mVData->getType()) {
		case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
		{
			COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
			if (values->empty() || values->getCount() <= (v_index * stride + 2)) return;  // xxx need to create an eror instead

			mloopcol->r = FTOCHAR((*values)[v_index * stride]);
			mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
			mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
		}
		break;

		case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
		{
			COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
			if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an eror instead

			mloopcol->r = FTOCHAR((*values)[v_index * stride]);
			mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
			mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
		}
		break;
		default:
			fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n");
	}

}
예제 #11
0
static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
{
	unsigned char *pixels, *p;
	const float *fp = fpixels;
	const int len = 4 * length;

	p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");

	for (int a = 0; a < len; a++, p++, fp++)
		*p = FTOCHAR((*fp));

	return pixels;
}
예제 #12
0
static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
{
	BakeShade *bs = handle;
	float disp;

	if (R.r.bake_flag & R_BAKE_NORMALIZE) {
		if (R.r.bake_maxdist)
			disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2);  /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
		else
			disp = dist;
	}
	else {
		disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
	}

	if (bs->displacement_buffer) {
		float *displacement = bs->displacement_buffer + (bs->rectx * y + x);
		*displacement = disp;
		bs->displacement_min = min_ff(bs->displacement_min, disp);
		bs->displacement_max = max_ff(bs->displacement_max, disp);
	}

	if (bs->rect_float && !bs->vcol) {
		float *col = bs->rect_float + 4 * (bs->rectx * y + x);
		col[0] = col[1] = col[2] = disp;
		col[3] = 1.0f;
	}
	else {
		/* Target is char (LDR). */
		unsigned char col[4];
		col[0] = col[1] = col[2] = FTOCHAR(disp);
		col[3] = 255;

		if (bs->vcol) {
			/* Vertex color baking. Vcol has no useful alpha channel (it exists
			 * but is used only for vertex painting). */
			bs->vcol->r = col[0];
			bs->vcol->g = col[1];
			bs->vcol->b = col[2];
		}
		else {
			char *imcol = (char *)(bs->rect + bs->rectx * y + x);
			copy_v4_v4_char((char *)imcol, (char *)col);
		}
	}
	if (bs->rect_mask) {
		bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
	}
}
void *AntiAliasOperation::initializeTileData(rcti *rect)
{
	if (this->m_buffer) { return this->m_buffer; }
	lockMutex();
	if (this->m_buffer == NULL) {
		MemoryBuffer *tile = (MemoryBuffer *)this->m_valueReader->initializeTileData(rect);
		int size = tile->getHeight() * tile->getWidth();
		float *input = tile->getBuffer();
		char *valuebuffer = (char *)MEM_mallocN(sizeof(char) * size, __func__);
		for (int i = 0; i < size; i++) {
			float in = input[i * COM_NUMBER_OF_CHANNELS];
			valuebuffer[i] = FTOCHAR(in);
		}
		antialias_tagbuf(tile->getWidth(), tile->getHeight(), valuebuffer);
		this->m_buffer = valuebuffer;
	}
	unlockMutex();
	return this->m_buffer;
}
예제 #14
0
파일: rna_ID.c 프로젝트: pawkoz/dyplom
static void rna_ImagePreview_pixels_float_set(PointerRNA *ptr, const float *values, enum eIconSizes size)
{
	ID *id = ptr->id.data;
	PreviewImage *prv_img = (PreviewImage *)ptr->data;

	unsigned char *data = (unsigned char *)prv_img->rect[size];
	const size_t len = prv_img->w[size] * prv_img->h[size] * 4;
	size_t i;

	BLI_assert(sizeof(unsigned int) == 4);

	if (id != NULL) {
		BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
	}

	for (i = 0; i < len; i++) {
		data[i] = FTOCHAR(values[i]);
	}
	prv_img->flag[size] |= PRV_USER_EDITED;
}
예제 #15
0
void RE_bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max)
{
	int i;
	float *current_displacement = displacement;
	char *current_mask = mask;
	float max_distance;

	max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max));

	for (i = 0; i < ibuf->x * ibuf->y; i++) {
		if (*current_mask == FILTER_MASK_USED) {
			float normalized_displacement;

			if (max_distance > 1e-5f)
				normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2);
			else
				normalized_displacement = 0.5f;

			if (ibuf->rect_float) {
				/* currently baking happens to RGBA only */
				float *fp = ibuf->rect_float + i * 4;
				fp[0] = fp[1] = fp[2] = normalized_displacement;
				fp[3] = 1.0f;
			}

			if (ibuf->rect) {
				unsigned char *cp = (unsigned char *) (ibuf->rect + i);
				cp[0] = cp[1] = cp[2] = FTOCHAR(normalized_displacement);
				cp[3] = 255;
			}
		}

		current_displacement++;
		current_mask++;
	}
}
예제 #16
0
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pressure, float distance)
{
	Scene *scene = painter->scene;
	Brush *brush = painter->brush;

	const char *display_device = scene->display_settings.display_device;
	struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);

	rctf tex_mapping = painter->tex_mapping;
	struct ImagePool *pool = painter->pool;

	bool use_color_correction = painter->cache.use_color_correction;
	bool use_float = painter->cache.use_float;
	bool is_texbrush = painter->cache.is_texbrush;

	int x, y, thread = 0;
	float brush_rgb[3];

	/* allocate image buffer */
	ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);

	/* get brush color */
	if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
		paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, distance, pressure, brush_rgb, display);
	}
	else {
		brush_rgb[0] = 1.0f;
		brush_rgb[1] = 1.0f;
		brush_rgb[2] = 1.0f;
	}

	/* fill image buffer */
	for (y = 0; y < size; y++) {
		for (x = 0; x < size; x++) {
			/* sample texture and multiply with brush color */
			float texco[3], rgba[4];

			if (is_texbrush) {
				brush_imbuf_tex_co(&tex_mapping, x, y, texco);
				BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
				/* TODO(sergey): Support texture paint color space. */
				if (!use_float) {
					IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
				}
				mul_v3_v3(rgba, brush_rgb);
			}
			else {
				copy_v3_v3(rgba, brush_rgb);
				rgba[3] = 1.0f;
			}

			if (use_float) {
				/* write to float pixel */
				float *dstf = ibuf->rect_float + (y * size + x) * 4;
				mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
				dstf[3] = rgba[3];
			}
			else {
				/* write to byte pixel */
				unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;

				rgb_float_to_uchar(dst, rgba);
				dst[3] = FTOCHAR(rgba[3]);
			}
		}
	}

	return ibuf;
}
예제 #17
0
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                                int channels_from, float dither, int profile_to, int profile_from, bool predivide,
                                int width, int height, int stride_to, int stride_from)
{
	float tmp[4];
	int x, y;
	DitherContext *di = NULL;
	float inv_width = 1.0f / width,
	      inv_height = 1.0f / height;

	/* we need valid profiles */
	BLI_assert(profile_to != IB_PROFILE_NONE);
	BLI_assert(profile_from != IB_PROFILE_NONE);

	if (dither)
		di = create_dither_context(dither);

	for (y = 0; y < height; y++) {
		float t = y * inv_height;

		if (channels_from == 1) {
			/* single channel input */
			const float *from = rect_from + stride_from * y;
			uchar *to = rect_to + stride_to * y * 4;

			for (x = 0; x < width; x++, from++, to += 4)
				to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
		}
		else if (channels_from == 3) {
			/* RGB input */
			const float *from = rect_from + stride_from * y * 3;
			uchar *to = rect_to + stride_to * y * 4;

			if (profile_to == profile_from) {
				/* no color space conversion */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					rgb_float_to_uchar(to, from);
					to[3] = 255;
				}
			}
			else if (profile_to == IB_PROFILE_SRGB) {
				/* convert from linear to sRGB */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					linearrgb_to_srgb_v3_v3(tmp, from);
					rgb_float_to_uchar(to, tmp);
					to[3] = 255;
				}
			}
			else if (profile_to == IB_PROFILE_LINEAR_RGB) {
				/* convert from sRGB to linear */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					srgb_to_linearrgb_v3_v3(tmp, from);
					rgb_float_to_uchar(to, tmp);
					to[3] = 255;
				}
			}
		}
		else if (channels_from == 4) {
			/* RGBA input */
			const float *from = rect_from + stride_from * y * 4;
			uchar *to = rect_to + stride_to * y * 4;

			if (profile_to == profile_from) {
				float straight[4];

				/* no color space conversion */
				if (dither && predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						premul_to_straight_v4_v4(straight, from);
						float_to_byte_dither_v4(to, straight, di, (float) x * inv_width, t);
					}
				}
				else if (dither) {
					for (x = 0; x < width; x++, from += 4, to += 4)
						float_to_byte_dither_v4(to, from, di, (float) x * inv_width, t);
				}
				else if (predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						premul_to_straight_v4_v4(straight, from);
						rgba_float_to_uchar(to, straight);
					}
				}
				else {
					for (x = 0; x < width; x++, from += 4, to += 4)
						rgba_float_to_uchar(to, from);
				}
			}
			else if (profile_to == IB_PROFILE_SRGB) {
				/* convert from linear to sRGB */
				unsigned short us[4];
				float straight[4];

				if (dither && predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						premul_to_straight_v4_v4(straight, from);
						linearrgb_to_srgb_ushort4(us, from);
						ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t);
					}
				}
				else if (dither) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						linearrgb_to_srgb_ushort4(us, from);
						ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t);
					}
				}
				else if (predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						premul_to_straight_v4_v4(straight, from);
						linearrgb_to_srgb_ushort4(us, from);
						ushort_to_byte_v4(to, us);
					}
				}
				else {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						linearrgb_to_srgb_ushort4(us, from);
						ushort_to_byte_v4(to, us);
					}
				}
			}
			else if (profile_to == IB_PROFILE_LINEAR_RGB) {
				/* convert from sRGB to linear */
				if (dither && predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						srgb_to_linearrgb_predivide_v4(tmp, from);
						float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t);
					}
				}
				else if (dither) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						srgb_to_linearrgb_v4(tmp, from);
						float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t);
					}
				}
				else if (predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						srgb_to_linearrgb_predivide_v4(tmp, from);
						rgba_float_to_uchar(to, tmp);
					}
				}
				else {
					for (x = 0; x < width; x++, from += 4, to += 4) {
						srgb_to_linearrgb_v4(tmp, from);
						rgba_float_to_uchar(to, tmp);
					}
				}
			}
		}
	}

	if (dither)
		clear_dither_context(di);
}
예제 #18
0
static void update_tface_color_layer(DerivedMesh *dm)
{
	MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE);
	MFace *mface = dm->getTessFaceArray(dm);
	MCol *finalCol;
	int i, j;
	MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
	if (!mcol)
		mcol = dm->getTessFaceDataArray(dm, CD_MCOL);

	if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
		finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
	}
	else {
		finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");

		CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
	}

	for (i = 0; i < dm->getNumTessFaces(dm); i++) {
		Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);

		if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
			if (mcol)
				memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
			else
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
		}
		else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = 255;
				finalCol[i * 4 + j].g = 0;
				finalCol[i * 4 + j].r = 255;
			}
		}
		else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
				finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
				finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
			}
		}
		else if (!mcol) {
			if (tface) {
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
			}
			else {
				float col[3];

				if (ma) {
					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);
					
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = FTOCHAR(col[0]);
						finalCol[i * 4 + j].g = FTOCHAR(col[1]);
						finalCol[i * 4 + j].r = FTOCHAR(col[2]);
					}
				}
				else
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = 255;
						finalCol[i * 4 + j].g = 255;
						finalCol[i * 4 + j].r = 255;
					}
			}
		}
		else {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].r = mcol[i * 4 + j].r;
				finalCol[i * 4 + j].g = mcol[i * 4 + j].g;
				finalCol[i * 4 + j].b = mcol[i * 4 + j].b;
			}
		}
	}
}
예제 #19
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;
	}
}
예제 #20
0
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
                                int channels_from, float dither, bool predivide,
                                int width, int height, int stride_to, int stride_from, char *mask)
{
	int x, y;
	DitherContext *di = NULL;
	float inv_width = 1.0f / width,
	inv_height = 1.0f / height;

	if (dither)
		di = create_dither_context(dither);

	for (y = 0; y < height; y++) {
		float t = y * inv_height;

		if (channels_from == 1) {
			/* single channel input */
			const float *from = rect_from + stride_from * y;
			uchar *to = rect_to + stride_to * y * 4;

			for (x = 0; x < width; x++, from++, to += 4)
				if (*mask++ == FILTER_MASK_USED)
					to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
		}
		else if (channels_from == 3) {
			/* RGB input */
			const float *from = rect_from + stride_from * y * 3;
			uchar *to = rect_to + stride_to * y * 4;

			for (x = 0; x < width; x++, from += 3, to += 4) {
				if (*mask++ == FILTER_MASK_USED) {
					rgb_float_to_uchar(to, from);
					to[3] = 255;
				}
			}
		}
		else if (channels_from == 4) {
			/* RGBA input */
			const float *from = rect_from + stride_from * y * 4;
			uchar *to = rect_to + stride_to * y * 4;

			float straight[4];

			if (dither && predivide) {
				for (x = 0; x < width; x++, from += 4, to += 4) {
					if (*mask++ == FILTER_MASK_USED) {
						premul_to_straight_v4_v4(straight, from);
						float_to_byte_dither_v4(to, straight, di, (float) x * inv_width, t);
					}
				}
			}
			else if (dither) {
				for (x = 0; x < width; x++, from += 4, to += 4)
					if (*mask++ == FILTER_MASK_USED)
						float_to_byte_dither_v4(to, from, di, (float) x * inv_width, t);
			}
			else if (predivide) {
				for (x = 0; x < width; x++, from += 4, to += 4) {
					if (*mask++ == FILTER_MASK_USED) {
						premul_to_straight_v4_v4(straight, from);
						rgba_float_to_uchar(to, straight);
					}
				}
			}
			else {
				for (x = 0; x < width; x++, from += 4, to += 4)
					if (*mask++ == FILTER_MASK_USED)
						rgba_float_to_uchar(to, from);
			}
		}
	}

	if (dither)
		clear_dither_context(di);
}
예제 #21
0
파일: brush.c 프로젝트: mik0001/Blender
void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
	ImBuf *ibuf;
	float xy[2], dist, rgba[4], *dstf;
	int x, y, rowbytes, xoff, yoff, imbflag;
	const int radius= brush_size(brush);
	char *dst, crgb[3];
	const float alpha= brush_alpha(brush);
	float brush_rgb[3];
    
	imbflag= (flt)? IB_rectfloat: IB_rect;
	xoff = -bufsize/2.0f + 0.5f;
	yoff = -bufsize/2.0f + 0.5f;
	rowbytes= bufsize*4;

	if (*outbuf)
		ibuf= *outbuf;
	else
		ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

	if (flt) {
		copy_v3_v3(brush_rgb, brush->rgb);
		if(use_color_correction){
			srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
		}

		for (y=0; y < ibuf->y; y++) {
			dstf = ibuf->rect_float + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dstf+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					copy_v3_v3(dstf, brush_rgb);
					dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, dstf, 0);
				}
				else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					mul_v3_v3v3(dstf, rgba, brush_rgb);
					dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
			}
		}
	}
	else {
		crgb[0]= FTOCHAR(brush->rgb[0]);
		crgb[1]= FTOCHAR(brush->rgb[1]);
		crgb[2]= FTOCHAR(brush->rgb[2]);

		for (y=0; y < ibuf->y; y++) {
			dst = (char*)ibuf->rect + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dst+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= FTOCHAR(rgba[0]);
					dst[1]= FTOCHAR(rgba[1]);
					dst[2]= FTOCHAR(rgba[2]);
					dst[3]= FTOCHAR(rgba[3]);
				}
				else if (texfall == 2) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
					dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
					dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				} else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				}
			}
		}
	}

	*outbuf= ibuf;
}
예제 #22
0
static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
{
	BakeShade *bs = handle;
	ShadeSample *ssamp = &bs->ssamp;
	ShadeResult shr;
	VlakRen *vlr = shi->vlr;

	shade_input_init_material(shi);

	if (bs->type == RE_BAKE_AO) {
		ambient_occlusion(shi);

		if (R.r.bake_flag & R_BAKE_NORMALIZE) {
			copy_v3_v3(shr.combined, shi->ao);
		}
		else {
			zero_v3(shr.combined);
			environment_lighting_apply(shi, &shr);
		}
	}
	else {
		if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
			shi->r = shi->g = shi->b = 1.0f;

		shade_input_set_shade_texco(shi);
		
		/* only do AO for a full bake (and obviously AO bakes)
		 * AO for light bakes is a leftover and might not be needed */
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
			shade_samples_do_AO(ssamp);
		
		if (shi->mat->nodetree && shi->mat->use_nodes) {
			ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
			shi->mat = vlr->mat;  /* shi->mat is being set in nodetree */
		}
		else
			shade_material_loop(shi, &shr);

		if (bs->type == RE_BAKE_NORMALS) {
			float nor[3];

			copy_v3_v3(nor, shi->vn);

			if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
				/* pass */
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
				float mat[3][3], imat[3][3];

				/* bitangent */
				if (tvn && ttang) {
					copy_v3_v3(mat[0], ttang);
					cross_v3_v3v3(mat[1], tvn, ttang);
					mul_v3_fl(mat[1], ttang[3]);
					copy_v3_v3(mat[2], tvn);
				}
				else {
					copy_v3_v3(mat[0], shi->nmaptang);
					cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
					mul_v3_fl(mat[1], shi->nmaptang[3]);
					copy_v3_v3(mat[2], shi->nmapnorm);
				}

				invert_m3_m3(imat, mat);
				mul_m3_v3(imat, nor);
			}
			else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
				mul_mat3_m4_v3(ob->imat_ren, nor);  /* ob->imat_ren includes viewinv! */
			else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
				mul_mat3_m4_v3(R.viewinv, nor);

			normalize_v3(nor); /* in case object has scaling */

			/* The invert of the red channel is to make
			 * the normal map compliant with the outside world.
			 * It needs to be done because in Blender
			 * the normal used in the renderer points inward. It is generated
			 * this way in calc_vertexnormals(). Should this ever change
			 * this negate must be removed. */
			shr.combined[0] = (-nor[0]) / 2.0f + 0.5f;
			shr.combined[1] = nor[1]    / 2.0f + 0.5f;
			shr.combined[2] = nor[2]    / 2.0f + 0.5f;
		}
		else if (bs->type == RE_BAKE_TEXTURE) {
			copy_v3_v3(shr.combined, &shi->r);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SHADOW) {
			copy_v3_v3(shr.combined, shr.shad);
			shr.alpha = shi->alpha;
		}
		else if (bs->type == RE_BAKE_SPEC_COLOR) {
			copy_v3_v3(shr.combined, &shi->specr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_SPEC_INTENSITY) {
			copy_v3_fl(shr.combined, shi->spec);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_COLOR) {
			copy_v3_v3(shr.combined, &shi->mirr);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_MIRROR_INTENSITY) {
			copy_v3_fl(shr.combined, shi->ray_mirror);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_ALPHA) {
			copy_v3_fl(shr.combined, shi->alpha);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_EMIT) {
			copy_v3_fl(shr.combined, shi->emit);
			shr.alpha = 1.0f;
		}
		else if (bs->type == RE_BAKE_VERTEX_COLORS) {
			copy_v3_v3(shr.combined, shi->vcol);
			shr.alpha = shi->vcol[3];
		}
	}
	
	if (bs->rect_float && !bs->vcol) {
		float *col = bs->rect_float + 4 * (bs->rectx * y + x);
		copy_v3_v3(col, shr.combined);
		if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) {
			col[3] = shr.alpha;
		}
		else {
			col[3] = 1.0;
		}
	}
	else {
		/* Target is char (LDR). */
		unsigned char col[4];

		if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
			float rgb[3];

			copy_v3_v3(rgb, shr.combined);
			if (R.scene_color_manage) {
				/* Vertex colors have no way to specify color space, so they
				 * default to sRGB. */
				if (!bs->vcol)
					IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
				else
					linearrgb_to_srgb_v3_v3(rgb, rgb);
			}
			rgb_float_to_uchar(col, rgb);
		}
		else {
			rgb_float_to_uchar(col, shr.combined);
		}
		
		if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
			col[3] = FTOCHAR(shr.alpha);
		}
		else {
			col[3] = 255;
		}

		if (bs->vcol) {
			/* Vertex color baking. Vcol has no useful alpha channel (it exists
			 * but is used only for vertex painting). */
			bs->vcol->r = col[0];
			bs->vcol->g = col[1];
			bs->vcol->b = col[2];
		}
		else {
			unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
			copy_v4_v4_char((char *)imcol, (char *)col);
		}

	}
	
	if (bs->rect_mask) {
		bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
	}

	if (bs->do_update) {
		*bs->do_update = true;
	}
}
예제 #23
0
/* returns user-scale */
float RE_bake_make_derivative(ImBuf *ibuf, float *heights_buffer, const char *mask,
                              const float height_min, const float height_max,
                              const float fmult)
{
	const float delta_height = height_max - height_min;
	const float denom = delta_height > 0.0f ? (8 * delta_height) : 1.0f;
	bool auto_range_fit = fmult <= 0.0f;
	float max_num_deriv = -1.0f;
	int x, y, index;

	/* Need a single margin to calculate good derivatives. */
	add_single_heights_margin(ibuf, mask, heights_buffer);

	if (auto_range_fit) {
		/* If automatic range fitting is enabled. */
		for (y = 0; y < ibuf->y; y++) {
			const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y + 1);
			const int Yc = y;
			const int Yd = y == 0 ? 0 : (y - 1);

			for (x = 0; x < ibuf->x; x++) {
				const int Xl = x == 0 ? 0 : (x - 1);
				const int Xc = x;
				const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1);

				const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl];
				const float Hu  = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl];
				const float Hd  = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl];

				const float Hl  = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl];
				const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc];
				const float Hr  = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr];

				/* This corresponds to using the sobel kernel on the heights buffer
				 * to obtain the derivative multiplied by 8.
				 */
				const float deriv_x = Hu + 2 * Hcy + Hd;
				const float deriv_y = Hr + 2 * Hcx + Hl;

				/* early out */
				index = ibuf->x * y + x;
				if (mask[index] != FILTER_MASK_USED) {
					continue;
				}

				/* Widen bound. */
				if (fabsf(deriv_x) > max_num_deriv) {
					max_num_deriv = fabsf(deriv_x);
				}

				if (fabsf(deriv_y) > max_num_deriv) {
					max_num_deriv = fabsf(deriv_y);
				}
			}
		}
	}

	/* Output derivatives. */
	auto_range_fit &= (max_num_deriv > 0);
	for (y = 0; y < ibuf->y; y++) {
		const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y + 1);
		const int Yc = y;
		const int Yd = y == 0 ? 0 : (y - 1);

		for (x = 0; x < ibuf->x; x++) {
			const int Xl = x == 0 ? 0 : (x - 1);
			const int Xc = x;
			const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1);

			const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl];
			const float Hu  = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl];
			const float Hd  = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl];

			const float Hl  = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl];
			const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc];
			const float Hr  = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr];

			/* This corresponds to using the sobel kernel on the heights buffer
			 * to obtain the derivative multiplied by 8.
			 */
			float deriv_x = Hu + 2 * Hcy + Hd;
			float deriv_y = Hr + 2 * Hcx + Hl;

			/* Early out. */
			index = ibuf->x * y + x;
			if (mask[index] != FILTER_MASK_USED) {
				continue;
			}

			if (auto_range_fit) {
				deriv_x /= max_num_deriv;
				deriv_y /= max_num_deriv;
			}
			else {
				deriv_x *= (fmult / denom);
				deriv_y *= (fmult / denom);
			}

			deriv_x = deriv_x * 0.5f + 0.5f;
			deriv_y = deriv_y * 0.5f + 0.5f;

			/* Clamp. */
			CLAMP(deriv_x, 0.0f, 1.0f);
			CLAMP(deriv_y, 0.0f, 1.0f);

			/* Write out derivatives. */
			if (ibuf->rect_float) {
				float *rrgbf = ibuf->rect_float + index * 4;

				rrgbf[0] = deriv_x;
				rrgbf[1] = deriv_y;
				rrgbf[2] = 0.0f;
				rrgbf[3] = 1.0f;
			}
			else {
				char *rrgb = (char *)ibuf->rect + index * 4;

				rrgb[0] = FTOCHAR(deriv_x);
				rrgb[1] = FTOCHAR(deriv_y);
				rrgb[2] = 0;
				rrgb[3] = 255;
			}
		}
	}

	/* Eeturn user-scale (for rendering). */
	return auto_range_fit ? (max_num_deriv / denom) : (fmult > 0.0f ? (1.0f / fmult) : 0.0f);
}
예제 #24
0
/* TODO, use define for 'texfall' arg */
void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
    ImBuf *ibuf;
    float xy[2], rgba[4], *dstf;
    int x, y, rowbytes, xoff, yoff, imbflag;
    const int radius = BKE_brush_size_get(scene, brush);
    unsigned char *dst, crgb[3];
    const float alpha = BKE_brush_alpha_get(scene, brush);
    float brush_rgb[3];

    imbflag = (flt) ? IB_rectfloat : IB_rect;
    xoff = -bufsize / 2.0f + 0.5f;
    yoff = -bufsize / 2.0f + 0.5f;
    rowbytes = bufsize * 4;

    if (*outbuf)
        ibuf = *outbuf;
    else
        ibuf = IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

    if (flt) {
        copy_v3_v3(brush_rgb, brush->rgb);
        if (use_color_correction) {
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
        }

        for (y = 0; y < ibuf->y; y++) {
            dstf = ibuf->rect_float + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dstf += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    copy_v3_v3(dstf, brush_rgb);
                    dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, dstf, 0);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3v3(dstf, rgba, brush_rgb);
                    dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
            }
        }
    }
    else {
        float alpha_f; /* final float alpha to convert to char */
        rgb_float_to_uchar(crgb, brush->rgb);

        for (y = 0; y < ibuf->y; y++) {
            dst = (unsigned char *)ibuf->rect + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dst += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    alpha_f = alpha * BKE_brush_curve_strength(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    rgba_float_to_uchar(dst, rgba);
                }
                else if (texfall == 2) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3(rgba, brush->rgb);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    rgb_float_to_uchar(dst, rgba);

                    dst[3] = FTOCHAR(alpha_f);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
            }
        }
    }

    *outbuf = ibuf;
}
예제 #25
0
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
{
    Scene *scene = painter->scene;
    Brush *brush = painter->brush;

    rctf tex_mapping = painter->tex_mapping;
    rctf mask_mapping = painter->mask_mapping;
    struct ImagePool *pool = painter->pool;

    bool use_masking = painter->cache.use_masking;
    bool use_color_correction = painter->cache.use_color_correction;
    bool use_float = painter->cache.use_float;
    bool is_texbrush = painter->cache.is_texbrush;
    bool is_maskbrush = painter->cache.is_maskbrush;

    float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
    int radius = BKE_brush_size_get(scene, brush);
    int xoff = -size * 0.5f + 0.5f;
    int yoff = -size * 0.5f + 0.5f;

    int x, y, thread = 0;
    float brush_rgb[3];

    /* allocate image buffer */
    ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);

    /* get brush color */
    if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
        copy_v3_v3(brush_rgb, brush->rgb);

        if (use_color_correction)
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
    }
    else {
        brush_rgb[0] = 1.0f;
        brush_rgb[1] = 1.0f;
        brush_rgb[2] = 1.0f;
    }

    /* fill image buffer */
    for (y = 0; y < size; y++) {
        for (x = 0; x < size; x++) {
            /* sample texture and multiply with brush color */
            float texco[3], rgba[4];

            if (is_texbrush) {
                brush_imbuf_tex_co(&tex_mapping, x, y, texco);
                BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
                /* TODO(sergey): Support texture paint color space. */
                if (!use_float) {
                    linearrgb_to_srgb_v3_v3(rgba, rgba);
                }
                mul_v3_v3(rgba, brush_rgb);
            }
            else {
                copy_v3_v3(rgba, brush_rgb);
                rgba[3] = 1.0f;
            }

            if (is_maskbrush) {
                brush_imbuf_tex_co(&mask_mapping, x, y, texco);
                rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
            }

            /* when not using masking, multiply in falloff and strength */
            if (!use_masking) {
                float xy[2] = {x + xoff, y + yoff};
                float len = len_v2(xy);

                rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
            }

            if (use_float) {
                /* write to float pixel */
                float *dstf = ibuf->rect_float + (y * size + x) * 4;
                mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
                dstf[3] = rgba[3];
            }
            else {
                /* write to byte pixel */
                unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;

                rgb_float_to_uchar(dst, rgba);
                dst[3] = FTOCHAR(rgba[3]);
            }
        }
    }

    return ibuf;
}
예제 #26
0
파일: brush.c 프로젝트: mik0001/Blender
static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos)
{
	Brush *brush= painter->brush;
	ImBuf *ibuf, *maskibuf, *texibuf;
	float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
	char *b, *m, *t, *ot= NULL;
	int dotexold, origx= x, origy= y;
	const int radius= brush_size(brush);

	xoff = -radius + 0.5f;
	yoff = -radius + 0.5f;
	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
	yoff += (int)pos[1] - (int)painter->startpaintpos[1];

	ibuf = painter->cache.ibuf;
	texibuf = painter->cache.texibuf;
	maskibuf = painter->cache.maskibuf;

	dotexold = (oldtexibuf != NULL);

	/* not sure if it's actually needed or it's a mistake in coords/sizes
	   calculation in brush_painter_fixed_tex_partial_update(), but without this
	   limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
	w = MIN2(w, ibuf->x);
	h = MIN2(h, ibuf->y);

	if (painter->cache.flt) {
		for (; y < h; y++) {
			bf = ibuf->rect_float + (y*ibuf->x + origx)*4;
			tf = texibuf->rect_float + (y*texibuf->x + origx)*4;
			mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4;

			if (dotexold)
				otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4;

			for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) {
				if (dotexold) {
					copy_v3_v3(tf, otf);
					tf[3] = otf[3];
					otf += 4;
				}
				else {
					xy[0] = x + xoff;
					xy[1] = y + yoff;

					brush_sample_tex(brush, xy, tf, 0);
				}

				bf[0] = tf[0]*mf[0];
				bf[1] = tf[1]*mf[1];
				bf[2] = tf[2]*mf[2];
				bf[3] = tf[3]*mf[3];
			}
		}
	}
	else {
		for (; y < h; y++) {
			b = (char*)ibuf->rect + (y*ibuf->x + origx)*4;
			t = (char*)texibuf->rect + (y*texibuf->x + origx)*4;
			m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4;

			if (dotexold)
				ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4;

			for (x=origx; x < w; x++, b+=4, m+=4, t+=4) {
				if (dotexold) {
					t[0] = ot[0];
					t[1] = ot[1];
					t[2] = ot[2];
					t[3] = ot[3];
					ot += 4;
				}
				else {
					xy[0] = x + xoff;
					xy[1] = y + yoff;

					brush_sample_tex(brush, xy, rgba, 0);
					t[0]= FTOCHAR(rgba[0]);
					t[1]= FTOCHAR(rgba[1]);
					t[2]= FTOCHAR(rgba[2]);
					t[3]= FTOCHAR(rgba[3]);
				}

				b[0] = t[0]*m[0]/255;
				b[1] = t[1]*m[1]/255;
				b[2] = t[2]*m[2]/255;
				b[3] = t[3]*m[3]/255;
			}
		}
	}
}
예제 #27
0
static void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
                                          unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
	BrightContrastThreadData *data = (BrightContrastThreadData *) data_v;
	int x, y;

	float i;
	int c;
	float a, b, v;
	float brightness = data->bright / 100.0f;
	float contrast = data->contrast;
	float delta = contrast / 200.0f;

	a = 1.0f - delta * 2.0f;
	/*
	 * The algorithm is by Werner D. Streidt
	 * (http://visca.com/ffactory/archives/5-99/msg00021.html)
	 * Extracted of OpenCV demhist.c
	 */
	if (contrast > 0) {
		a = 1.0f / a;
		b = a * (brightness - delta);
	}
	else {
		delta *= -1;
		b = a * (brightness + delta);
	}

	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			int pixel_index = (y * width + x) * 4;

			if (rect) {
				unsigned char *pixel = rect + pixel_index;

				for (c = 0; c < 3; c++) {
					i = (float) pixel[c] / 255.0f;
					v = a * i + b;

					if (mask_rect) {
						unsigned char *m = mask_rect + pixel_index;
						float t = (float) m[c] / 255.0f;

						v = (float) pixel[c] / 255.0f * (1.0f - t) + v * t;
					}

					pixel[c] = FTOCHAR(v);
				}
			}
			else if (rect_float) {
				float *pixel = rect_float + pixel_index;

				for (c = 0; c < 3; c++) {
					i = pixel[c];
					v = a * i + b;

					if (mask_rect_float) {
						const float *m = mask_rect_float + pixel_index;

						pixel[c] = pixel[c] * (1.0f - m[c]) + v * m[c];
					}
					else
						pixel[c] = v;
				}
			}
		}
	}
}
예제 #28
0
/* MultiresBake callback for heights baking
 * general idea:
 *   - find coord of point with specified UV in hi-res mesh (let's call it p1)
 *   - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
 *     mesh to make texture smoother) let's call this point p0 and n.
 *   - height wound be dot(n, p1-p0) */
static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data,
                                   ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                   float UNUSED(tangmat[3][3]), const int x, const int y)
{
	MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;
	MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
	MultiresBakeThread *thread_data = (MultiresBakeThread *) thread_data_v;
	float uv[2], *st0, *st1, *st2, *st3;
	int pixel = ibuf->x * y + x;
	float vec[3], p0[3], p1[3], n[3], len;

	lores_dm->getTessFace(lores_dm, face_index, &mface);

	st0 = mtface[face_index].uv[0];
	st1 = mtface[face_index].uv[1];
	st2 = mtface[face_index].uv[2];

	if (mface.v4) {
		st3 = mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	}
	else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm,
	               height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
	               lvl, face_index, uv[0], uv[1], p1, NULL);

	if (height_data->ssdm) {
		get_ccgdm_data(lores_dm, height_data->ssdm,
		               height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
		               0, face_index, uv[0], uv[1], p0, n);
	}
	else {
		lores_dm->getTessFace(lores_dm, face_index, &mface);

		if (mface.v4) {
			interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
			interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
		}
		else {
			interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
			interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
		}
	}

	sub_v3_v3v3(vec, p1, p0);
	len = dot_v3v3(n, vec);

	height_data->heights[pixel] = len;

	thread_data->height_min = min_ff(thread_data->height_min, len);
	thread_data->height_max = max_ff(thread_data->height_max, len);

	if (ibuf->rect_float) {
		float *rrgbf = ibuf->rect_float + pixel * 4;
		rrgbf[0] = rrgbf[1] = rrgbf[2] = len;
		rrgbf[3] = 1.0f;
	}
	else {
		char *rrgb = (char *)ibuf->rect + pixel * 4;
		rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(len);
		rrgb[3] = 255;
	}
}
예제 #29
0
static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
                              ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                              float UNUSED(tangmat[3][3]), const int x, const int y)
{
	MAOBakeData *ao_data = (MAOBakeData *) bake_data;
	MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
	MFace mface;

	int i, k, perm_offs;
	float pos[3], nrm[3];
	float cen[3];
	float axisX[3], axisY[3], axisZ[3];
	float shadow = 0;
	float value;
	int pixel = ibuf->x * y + x;
	float uv[2], *st0, *st1, *st2, *st3;

	lores_dm->getTessFace(lores_dm, face_index, &mface);

	st0 = mtface[face_index].uv[0];
	st1 = mtface[face_index].uv[1];
	st2 = mtface[face_index].uv[2];

	if (mface.v4) {
		st3 = mtface[face_index].uv[3];
		resolve_quad_uv(uv, st, st0, st1, st2, st3);
	}
	else
		resolve_tri_uv(uv, st, st0, st1, st2);

	CLAMP(uv[0], 0.0f, 1.0f);
	CLAMP(uv[1], 0.0f, 1.0f);

	get_ccgdm_data(lores_dm, hires_dm,
	               ao_data->orig_index_mf_to_mpoly, ao_data->orig_index_mp_to_orig,
	               lvl, face_index, uv[0], uv[1], pos, nrm);

	/* offset ray origin by user bias along normal */
	for (i = 0; i < 3; i++)
		cen[i] = pos[i] + ao_data->bias * nrm[i];

	/* build tangent frame */
	for (i = 0; i < 3; i++)
		axisZ[i] = nrm[i];

	build_coordinate_frame(axisX, axisY, axisZ);

	/* static noise */
	perm_offs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);

	/* importance sample shadow rays (cosine weighted) */
	for (i = 0; i < ao_data->number_of_rays; i++) {
		int hit_something;

		/* use N-Rooks to distribute our N ray samples across
		 * a multi-dimensional domain (2D)
		 */
		const unsigned short I = ao_data->permutation_table_1[(i + perm_offs) % ao_data->number_of_rays];
		const unsigned short J = ao_data->permutation_table_2[i];

		const float JitPh = (get_ao_random2(I + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
		const float JitTh = (get_ao_random1(J + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
		const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
		const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);

		/* this gives results identical to the so-called cosine
		 * weighted distribution relative to the north pole.
		 */
		float SiPhi = sqrt(SiSqPhi);
		float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
		float CoThe = cos(Theta);
		float SiThe = sin(Theta);

		const float dx = CoThe * CoPhi;
		const float dy = SiThe * CoPhi;
		const float dz = SiPhi;

		/* transform ray direction out of tangent frame */
		float dv[3];
		for (k = 0; k < 3; k++)
			dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;

		hit_something = trace_ao_ray(ao_data, cen, dv);

		if (hit_something != 0)
			shadow += 1;
	}

	value = 1.0f - (shadow / ao_data->number_of_rays);

	if (ibuf->rect_float) {
		float *rrgbf = ibuf->rect_float + pixel * 4;
		rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
		rrgbf[3] = 1.0f;
	}
	else {
		unsigned char *rrgb = (unsigned char *) ibuf->rect + pixel * 4;
		rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(value);
		rrgb[3] = 255;
	}
}
예제 #30
0
파일: rectop.c 프로젝트: OldBrunet/BGERTPS
void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, float *col, int x1, int y1, int x2, int y2)
{
	int i, j;
	float a; /* alpha */
	float ai; /* alpha inverted */
	float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
	if ((!rect && !rectf) || (!col) || col[3]==0.0f)
		return;
	
	/* sanity checks for coords */
	CLAMP(x1, 0, width);
	CLAMP(x2, 0, width);
	CLAMP(y1, 0, height);
	CLAMP(y2, 0, height);

	if (x1>x2) SWAP(int,x1,x2);
	if (y1>y2) SWAP(int,y1,y2);
	if (x1==x2 || y1==y2) return;
	
	a = col[3];
	ai = 1-a;
	aich = ai/255.0f;

	if (rect) {
		unsigned char *pixel; 
		unsigned char chr=0, chg=0, chb=0;
		float fr=0, fg=0, fb=0;
		
		if (a == 1.0f) {
			chr = FTOCHAR(col[0]);
			chg = FTOCHAR(col[1]);
			chb = FTOCHAR(col[2]);
		} else {
			fr = col[0]*a;
			fg = col[1]*a;
			fb = col[2]*a;
		}
		for (j = 0; j < y2-y1; j++) {
			for (i = 0; i < x2-x1; i++) {
				pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
				if (pixel >= rect && pixel < rect+ (4 * (width * height))) {
					if (a == 1.0f) {
						pixel[0] = chr;
						pixel[1] = chg;
						pixel[2] = chb;
					} else {
						pixel[0] = (char)((fr + ((float)pixel[0]*aich))*255.0f);
						pixel[1] = (char)((fg + ((float)pixel[1]*aich))*255.0f);
						pixel[2] = (char)((fb + ((float)pixel[2]*aich))*255.0f);
					}
				}
			}
		}
	}
	
	if (rectf) {
		float *pixel;
		for (j = 0; j < y2-y1; j++) {
			for (i = 0; i < x2-x1; i++) {
				pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
				if (a == 1.0f) {
					pixel[0] = col[0];
					pixel[1] = col[1];
					pixel[2] = col[2];
				} else {
					pixel[0] = (col[0]*a) + (pixel[0]*ai);
					pixel[1] = (col[1]*a) + (pixel[1]*ai);
					pixel[2] = (col[2]*a) + (pixel[2]*ai);
				}
			}
		}
	}
}