Beispiel #1
0
void IMB_rect_from_float(ImBuf *ibuf)
{
  float *buffer;
  const char *from_colorspace;

  /* verify we have a float buffer */
  if (ibuf->rect_float == NULL) {
    return;
  }

  /* create byte rect if it didn't exist yet */
  if (ibuf->rect == NULL) {
    if (imb_addrectImBuf(ibuf) == 0) {
      return;
    }
  }

  if (ibuf->float_colorspace == NULL) {
    from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
  }
  else {
    from_colorspace = ibuf->float_colorspace->name;
  }

  buffer = MEM_dupallocN(ibuf->rect_float);

  /* first make float buffer in byte space */
  const bool predivide = IMB_alpha_affects_rgb(ibuf);
  IMB_colormanagement_transform(buffer,
                                ibuf->x,
                                ibuf->y,
                                ibuf->channels,
                                from_colorspace,
                                ibuf->rect_colorspace->name,
                                predivide);

  /* convert from float's premul alpha to byte's straight alpha */
  if (IMB_alpha_affects_rgb(ibuf)) {
    IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
  }

  /* convert float to byte */
  IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
                             buffer,
                             ibuf->channels,
                             ibuf->dither,
                             IB_PROFILE_SRGB,
                             IB_PROFILE_SRGB,
                             false,
                             ibuf->x,
                             ibuf->y,
                             ibuf->x,
                             ibuf->x);

  MEM_freeN(buffer);

  /* ensure user flag is reset */
  ibuf->userflags &= ~IB_RECT_INVALID;
}
Beispiel #2
0
/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
{
	const float *rect_float;
	uchar *rect_byte;
	int profile_from = IB_PROFILE_LINEAR_RGB;

	/* verify we have a float buffer */
	if (ibuf->rect_float == NULL || buffer == NULL)
		return;

	/* create byte rect if it didn't exist yet */
	if (ibuf->rect == NULL)
		imb_addrectImBuf(ibuf);

	/* do conversion */
	rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
	rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;

	if (is_data) {
		/* exception for non-color data, just copy float */
		IMB_buffer_float_from_float(buffer, rect_float,
		                            ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0,
		                            w, h, w, ibuf->x);

		/* and do color space conversion to byte */
		IMB_buffer_byte_from_float(rect_byte, rect_float,
		                           4, ibuf->dither, IB_PROFILE_SRGB, profile_from, true,
		                           w, h, ibuf->x, w);
	}
	else {
		IMB_buffer_float_from_float(buffer, rect_float,
		                            ibuf->channels, IB_PROFILE_SRGB, profile_from, true,
		                            w, h, w, ibuf->x);

		IMB_buffer_float_unpremultiply(buffer, w, h);
		/* XXX: need to convert to image buffer's rect space */
		IMB_buffer_byte_from_float(rect_byte, buffer,
		                           4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
		                           w, h, ibuf->x, w);
	}

	/* ensure user flag is reset */
	ibuf->userflags &= ~IB_RECT_INVALID;
}
static bool write_external_bake_pixels(
        const char *filepath, BakePixel pixel_array[], float *buffer,
        const int width, const int height, const int margin,
        ImageFormatData *im_format, const bool is_noncolor)
{
	ImBuf *ibuf = NULL;
	bool ok = false;
	bool is_float;

	is_float = im_format->depth > 8;

	/* create a new ImBuf */
	ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));

	if (!ibuf)
		return false;

	/* populates the ImBuf */
	if (is_float) {
		IMB_buffer_float_from_float(
		        ibuf->rect_float, buffer, ibuf->channels,
		        IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
		        ibuf->x, ibuf->y, ibuf->x, ibuf->x);
	}
	else {
		if (!is_noncolor) {
			const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
			const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
			IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
		}

		IMB_buffer_byte_from_float(
		        (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
		        IB_PROFILE_SRGB, IB_PROFILE_SRGB,
		        false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
	}

	/* margins */
	if (margin > 0) {
		char *mask_buffer = NULL;
		const size_t num_pixels = (size_t)width * (size_t)height;

		mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
		RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
		RE_bake_margin(ibuf, mask_buffer, margin);

		if (mask_buffer)
			MEM_freeN(mask_buffer);
	}

	if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
#ifndef WIN32
		chmod(filepath, S_IRUSR | S_IWUSR);
#endif
		//printf("%s saving bake map: '%s'\n", __func__, filepath);
	}

	/* garbage collection */
	IMB_freeImBuf(ibuf);

	return ok;
}
static bool write_internal_bake_pixels(
        Image *image, BakePixel pixel_array[], float *buffer,
        const int width, const int height, const int margin,
        const bool is_clear, const bool is_noncolor)
{
	ImBuf *ibuf;
	void *lock;
	bool is_float;
	char *mask_buffer = NULL;
	const size_t num_pixels = (size_t)width * (size_t)height;

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

	if (!ibuf)
		return false;

	if (margin > 0 || !is_clear) {
		mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
		RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
	}

	is_float = (ibuf->flags & IB_rectfloat);

	/* colormanagement conversions */
	if (!is_noncolor) {
		const char *from_colorspace;
		const char *to_colorspace;

		from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);

		if (is_float)
			to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
		else
			to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);

		if (from_colorspace != to_colorspace)
			IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
	}

	/* populates the ImBuf */
	if (is_clear) {
		if (is_float) {
			IMB_buffer_float_from_float(
			        ibuf->rect_float, buffer, ibuf->channels,
			        IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
			        ibuf->x, ibuf->y, ibuf->x, ibuf->x);
		}
		else {
			IMB_buffer_byte_from_float(
			        (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
			        IB_PROFILE_SRGB, IB_PROFILE_SRGB,
			        false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
		}
	}
	else {
		if (is_float) {
			IMB_buffer_float_from_float_mask(
			        ibuf->rect_float, buffer, ibuf->channels,
			        ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
		}
		else {
			IMB_buffer_byte_from_float_mask(
			        (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
			        false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
		}
	}

	/* margins */
	if (margin > 0)
		RE_bake_margin(ibuf, mask_buffer, margin);

	ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;

	if (ibuf->rect_float)
		ibuf->userflags |= IB_RECT_INVALID;

	/* force mipmap recalc */
	if (ibuf->mipmap[0]) {
		ibuf->userflags |= IB_MIPMAP_INVALID;
		imb_freemipmapImBuf(ibuf);
	}

	BKE_image_release_ibuf(image, ibuf, NULL);

	if (mask_buffer)
		MEM_freeN(mask_buffer);

	return true;
}
/* called inside thread! */
void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
{
	float *rectf = NULL;
	int ymin, ymax, xmin, xmax;
	int rymin, rxmin, predivide, profile_from;
	unsigned 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 composite... 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 = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin);

	if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
		profile_from = IB_PROFILE_LINEAR_RGB;
		predivide = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
	}
	else {
		profile_from = IB_PROFILE_SRGB;
		predivide = 0;
	}

	IMB_buffer_byte_from_float(rectc, rectf,
	                           4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
	                           xmax, ymax, ibuf->x, rr->rectx);
}
Beispiel #6
0
/* uses ROUNDBOX button in block to get the rect */
static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect)
{
	Render *re;
	RenderResult rres;
	char name[32];
	int do_gamma_correct = 0, do_predivide = 0;
	int offx = 0, newx = rect->xmax - rect->xmin, newy = rect->ymax - rect->ymin;

	if (id && GS(id->name) != ID_TE) {
		/* exception: don't color manage texture previews - show the raw values */
		if (sce) {
			do_gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT;
			do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
		}
	}

	if (!split || first) sprintf(name, "Preview %p", (void *)sa);
	else sprintf(name, "SecondPreview %p", (void *)sa);

	if (split) {
		if (first) {
			offx = 0;
			newx = newx / 2;
		}
		else {
			offx = newx / 2;
			newx = newx - newx / 2;
		}
	}

	re = RE_GetRender(name);
	RE_AcquireResultImage(re, &rres);

	if (rres.rectf) {
		
		if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {

			newrect->xmax = MAX2(newrect->xmax, rect->xmin + rres.rectx + offx);
			newrect->ymax = MAX2(newrect->ymax, rect->ymin + rres.recty);

			if (rres.rectx && rres.recty) {
				/* temporary conversion to byte for drawing */
				float fx = rect->xmin + offx;
				float fy = rect->ymin;
				int profile_from = (do_gamma_correct) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
				int dither = 0;
				unsigned char *rect_byte;

				rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");

				IMB_buffer_byte_from_float(rect_byte, rres.rectf,
				                           4, dither, IB_PROFILE_SRGB, profile_from, do_predivide,
				                           rres.rectx, rres.recty, rres.rectx, rres.rectx);

				glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);

				MEM_freeN(rect_byte);
			}

			RE_ReleaseResultImage(re);
			return 1;
		}
	}

	RE_ReleaseResultImage(re);
	return 0;
}