Example #1
0
ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence *seq, ImBuf *ibuf, int cfra)
{
	SequenceModifierData *smd;
	ImBuf *processed_ibuf = ibuf;

	if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
		processed_ibuf = IMB_dupImBuf(ibuf);
		BKE_sequencer_imbuf_from_sequencer_space(context->scene, processed_ibuf);
	}

	for (smd = seq->modifiers.first; smd; smd = smd->next) {
		const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);

		/* could happen if modifier is being removed or not exists in current version of blender */
		if (!smti)
			continue;

		/* modifier is muted, do nothing */
		if (smd->flag & SEQUENCE_MODIFIER_MUTE)
			continue;

		if (smti->apply) {
			int frame_offset;
			if (smd->mask_time == SEQUENCE_MASK_TIME_RELATIVE) {
				frame_offset = seq->start;
			}
			else /*if (smd->mask_time == SEQUENCE_MASK_TIME_ABSOLUTE)*/ {
				frame_offset = 0;
			}

			ImBuf *mask = modifier_mask_get(smd,
			                                context,
			                                cfra,
			                                frame_offset,
			                                ibuf->rect_float != NULL);

			if (processed_ibuf == ibuf)
				processed_ibuf = IMB_dupImBuf(ibuf);

			smti->apply(smd, processed_ibuf, mask);

			if (mask)
				IMB_freeImBuf(mask);
		}
	}

	if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
		BKE_sequencer_imbuf_to_sequencer_space(context->scene, processed_ibuf, false);
	}

	return processed_ibuf;
}
Example #2
0
static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
                                   short *stop, short *do_update, float *progress)
{
	int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE);
	int i, pos;
	struct anim *anim = context->anim;

	for (pos = 0; pos < cnt; pos++) {
		struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
		struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf);
		float next_progress = (float) pos / (float) cnt;

		if (*progress != next_progress) {
			*progress = next_progress;
			*do_update = TRUE;
		}
		
		if (*stop) {
			break;
		}

		IMB_flipy(tmp_ibuf);

		for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
			if (context->proxy_sizes_in_use & proxy_sizes[i]) {
				int x = anim->x * proxy_fac[i];
				int y = anim->y * proxy_fac[i];

				struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf);

				IMB_scalefastImBuf(s_ibuf, x, y);

				IMB_convert_rgba_to_abgr(s_ibuf);
	
				AVI_write_frame(context->proxy_ctx[i], pos,
				                AVI_FORMAT_RGB32,
				                s_ibuf->rect, x * y * 4);

				/* note that libavi free's the buffer... */
				s_ibuf->rect = NULL;

				IMB_freeImBuf(s_ibuf);
			}
		}

		IMB_freeImBuf(tmp_ibuf);
		IMB_freeImBuf(ibuf);
	}
}
Example #3
0
/**
 * Deep-duplicate of an array of direntries, including the array itself.
 *
 * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
 */
void BLI_filelist_duplicate(
        struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries,
        void *(*dup_poin)(void *))
{
	unsigned int i;

	*dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__);
	for (i = 0; i < nrentries; ++i) {
		struct direntry * const src = &src_filelist[i];
		struct direntry *dest = &(*dest_filelist)[i];
		*dest = *src;
		if (dest->image) {
			dest->image = IMB_dupImBuf(src->image);
		}
		if (dest->relname) {
			dest->relname = MEM_dupallocN(src->relname);
		}
		if (dest->path) {
			dest->path = MEM_dupallocN(src->path);
		}
		if (dest->poin && dup_poin) {
			dest->poin = dup_poin(src->poin);
		}
	}
}
Example #4
0
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
{
    char name[FILE_MAX];
    int quality, rectx, recty;
    int size = rendersize_to_number(proxy_render_size);
    ImBuf *scaleibuf;

    get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);

    rectx = ibuf->x * size / 100.0f;
    recty = ibuf->y * size / 100.0f;

    scaleibuf = IMB_dupImBuf(ibuf);

    IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);

    quality = clip->proxy.quality;
    scaleibuf->ftype = JPG | quality;

    /* unsupported feature only confuses other s/w */
    if (scaleibuf->planes == 32)
        scaleibuf->planes = 24;

    BLI_lock_thread(LOCK_MOVIECLIP);

    BLI_make_existing_file(name);
    if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
        perror(name);

    BLI_unlock_thread(LOCK_MOVIECLIP);

    IMB_freeImBuf(scaleibuf);
}
Example #5
0
Brush *BKE_brush_copy(Main *bmain, Brush *brush)
{
	Brush *brushn;
	
	brushn = BKE_libblock_copy(bmain, &brush->id);

	if (brush->mtex.tex)
		id_us_plus((ID *)brush->mtex.tex);

	if (brush->mask_mtex.tex)
		id_us_plus((ID *)brush->mask_mtex.tex);

	if (brush->paint_curve)
		id_us_plus((ID *)brush->paint_curve);

	if (brush->icon_imbuf)
		brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);

	brushn->preview = NULL;

	brushn->curve = curvemapping_copy(brush->curve);

	/* enable fake user by default */
	id_fake_user_set(&brush->id);

	BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id);

	return brushn;
}
Example #6
0
/**
 * Only copy internal data of Brush ID from source
 * to already allocated/initialized destination.
 * You probably never want to use that directly,
 * use #BKE_id_copy or #BKE_id_copy_ex for typical needs.
 *
 * WARNING! This function will not handle ID user count!
 *
 * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
 */
void BKE_brush_copy_data(Main *UNUSED(bmain),
                         Brush *brush_dst,
                         const Brush *brush_src,
                         const int flag)
{
  if (brush_src->icon_imbuf) {
    brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf);
  }

  if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
    BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id);
  }
  else {
    brush_dst->preview = NULL;
  }

  brush_dst->curve = curvemapping_copy(brush_src->curve);
  if (brush_src->gpencil_settings != NULL) {
    brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings);
    brush_dst->gpencil_settings->curve_sensitivity = curvemapping_copy(
        brush_src->gpencil_settings->curve_sensitivity);
    brush_dst->gpencil_settings->curve_strength = curvemapping_copy(
        brush_src->gpencil_settings->curve_strength);
    brush_dst->gpencil_settings->curve_jitter = curvemapping_copy(
        brush_src->gpencil_settings->curve_jitter);
  }

  /* enable fake user by default */
  id_fake_user_set(&brush_dst->id);
}
ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
{
	ImBuf *rval;

	if (ibuf) {
		bool is_single;
		BLI_spin_lock(&refcounter_spin);
		is_single = (ibuf->refcounter == 0);
		BLI_spin_unlock(&refcounter_spin);
		if (is_single) {
			return ibuf;
		}
	}
	else {
		return NULL;
	}

	rval = IMB_dupImBuf(ibuf);

	IMB_metadata_copy(rval, ibuf);

	IMB_freeImBuf(ibuf);

	return rval;
}
Example #8
0
Brush *BKE_brush_copy(Brush *brush)
{
	Brush *brushn;
	
	brushn = BKE_libblock_copy(&brush->id);

	if (brush->mtex.tex)
		id_us_plus((ID *)brush->mtex.tex);

	if (brush->mask_mtex.tex)
		id_us_plus((ID *)brush->mask_mtex.tex);

	if (brush->icon_imbuf)
		brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);

	brushn->preview = NULL;

	brushn->curve = curvemapping_copy(brush->curve);

	/* enable fake user by default */
	if (!(brushn->id.flag & LIB_FAKEUSER)) {
		brushn->id.flag |= LIB_FAKEUSER;
		brushn->id.us++;
	}
	
	return brushn;
}
static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user)
{
	ImBuf *orig_ibuf, *ibuf;
	CompBuf *stackbuf;
	int type;

	float *rect;
	int alloc = FALSE;

	orig_ibuf = BKE_movieclip_get_ibuf(clip, user);

	if (orig_ibuf == NULL || (orig_ibuf->rect == NULL && orig_ibuf->rect_float == NULL)) {
		IMB_freeImBuf(orig_ibuf);
		return NULL;
	}

	ibuf = IMB_dupImBuf(orig_ibuf);
	IMB_freeImBuf(orig_ibuf);

	if (ibuf->rect_float == NULL || (ibuf->userflags & IB_RECT_INVALID)) {
		IMB_float_from_rect(ibuf);
		ibuf->userflags &= ~IB_RECT_INVALID;
	}

	/* now we need a float buffer from the image with matching color management */
	if (ibuf->channels == 4) {
		rect = node_composit_get_float_buffer(rd, ibuf, &alloc);
	}
	else {
		/* non-rgba passes can't use color profiles */
		rect = ibuf->rect_float;
	}
	/* done coercing into the correct color management */

	if (!alloc) {
		rect = MEM_dupallocN(rect);
		alloc = TRUE;
	}

	type = ibuf->channels;

	if (rd->scemode & R_COMP_CROP) {
		stackbuf = get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
		if (alloc)
			MEM_freeN(rect);
	}
	else {
		/* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
		stackbuf = alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
		stackbuf->rect = rect;
		stackbuf->malloc = alloc;
	}

	IMB_freeImBuf(ibuf);

	return stackbuf;
}
Example #10
0
static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
        int flag, int postprocess_flag)
{
    MovieClipCache *cache = clip->cache;
    MovieTrackingCamera *camera = &clip->tracking.camera;
    ImBuf *postproc_ibuf = NULL;

    if (cache->postprocessed.ibuf)
        IMB_freeImBuf(cache->postprocessed.ibuf);

    cache->postprocessed.framenr = user->framenr;
    cache->postprocessed.flag = postprocess_flag;

    if (flag & MCLIP_USE_PROXY) {
        cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
        cache->postprocessed.render_flag = user->render_flag;
    }
    else {
        cache->postprocessed.proxy = IMB_PROXY_NONE;
        cache->postprocessed.render_flag = 0;
    }

    if (need_undistortion_postprocess(user, flag)) {
        copy_v2_v2(cache->postprocessed.principal, camera->principal);
        copy_v3_v3(&cache->postprocessed.k1, &camera->k1);
        cache->postprocessed.undistoriton_used = TRUE;
        postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
    }
    else {
        cache->postprocessed.undistoriton_used = FALSE;
    }

    if (postprocess_flag) {
        int disable_red   = postprocess_flag & MOVIECLIP_DISABLE_RED,
            disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN,
            disable_blue  = postprocess_flag & MOVIECLIP_DISABLE_BLUE,
            grayscale     = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE;

        if (!postproc_ibuf)
            postproc_ibuf = IMB_dupImBuf(ibuf);

        if (disable_red || disable_green || disable_blue || grayscale)
            BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
    }

    IMB_refImBuf(postproc_ibuf);

    cache->postprocessed.ibuf = postproc_ibuf;

    if (cache->stabilized.ibuf) {
        /* force stable buffer be re-calculated */
        IMB_freeImBuf(cache->stabilized.ibuf);
        cache->stabilized.ibuf = NULL;
    }

    return postproc_ibuf;
}
Example #11
0
static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
{
	int dx, part;
	
	/* after lock we test cube[1], if set the other thread has done it fine */
	BLI_lock_thread(LOCK_IMAGE);
	if (env->cube[1] == NULL) {

		BKE_texture_envmap_free_data(env);
	
		dx = ibuf->y;
		dx /= 2;
		if (3 * dx == ibuf->x) {
			env->type = ENV_CUBE;
			env->ok = ENV_OSA;
		}
		else if (ibuf->x == ibuf->y) {
			env->type = ENV_PLANE;
			env->ok = ENV_OSA;
		}
		else {
			printf("Incorrect envmap size\n");
			env->ok = 0;
			env->ima->ok = 0;
		}
		
		if (env->ok) {
			if (env->type == ENV_CUBE) {
				for (part = 0; part < 6; part++) {
					env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat);
				}
				IMB_float_from_rect(ibuf);
				
				IMB_rectcpy(env->cube[0], ibuf, 
				            0, 0, 0, 0, dx, dx);
				IMB_rectcpy(env->cube[1], ibuf, 
				            0, 0, dx, 0, dx, dx);
				IMB_rectcpy(env->cube[2], ibuf, 
				            0, 0, 2 * dx, 0, dx, dx);
				IMB_rectcpy(env->cube[3], ibuf, 
				            0, 0, 0, dx, dx, dx);
				IMB_rectcpy(env->cube[4], ibuf, 
				            0, 0, dx, dx, dx, dx);
				IMB_rectcpy(env->cube[5], ibuf, 
				            0, 0, 2 * dx, dx, dx, dx);
				
			}
			else { /* ENV_PLANE */
				env->cube[1] = IMB_dupImBuf(ibuf);
				IMB_float_from_rect(env->cube[1]);
			}
		}
	}
	BLI_unlock_thread(LOCK_IMAGE);
}
Example #12
0
/* only used for image editor curves */
void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf)
{
	ImBuf *tmpbuf;
	int pixel;
	float *pix_in;
	float col[3];
	int stride = 4;
	float *pix_out;
	
	if (ibuf == NULL)
		return;
	if (ibuf->rect_float == NULL)
		IMB_float_from_rect(ibuf);
	else if (ibuf->rect == NULL)
		imb_addrectImBuf(ibuf);
	
	if (!ibuf->rect || !ibuf->rect_float)
		return;
	
	/* work on a temp buffer, so can color manage afterwards.
	 * No worse off memory wise than comp nodes */
	tmpbuf = IMB_dupImBuf(ibuf);
	
	curvemapping_premultiply(cumap, 0);
	
	pix_in = ibuf->rect_float;
	pix_out = tmpbuf->rect_float;

	if (ibuf->channels)
		stride = ibuf->channels;
	
	for (pixel = ibuf->x * ibuf->y; pixel > 0; pixel--, pix_in += stride, pix_out += stride) {
		if (stride < 3) {
			col[0] = curvemap_evaluateF(cumap->cm, *pix_in);
			
			pix_out[1] = pix_out[2] = pix_out[3] = pix_out[0] = col[0];
		}
		else {
			curvemapping_evaluate_premulRGBF(cumap, col, pix_in);
			pix_out[0] = col[0];
			pix_out[1] = col[1];
			pix_out[2] = col[2];
			if (stride > 3)
				pix_out[3] = pix_in[3];
			else
				pix_out[3] = 1.f;
		}
	}
	
	IMB_rect_from_float(tmpbuf);
	SWAP(unsigned int *, tmpbuf->rect, ibuf->rect);
	IMB_freeImBuf(tmpbuf);
	
	curvemapping_premultiply(cumap, 1);
}
Example #13
0
ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
{
	ImBuf *rval;

	if (!ibuf || ibuf->refcounter == 0) { return ibuf; }

	rval = IMB_dupImBuf(ibuf);

	IMB_freeImBuf(ibuf);

	return rval;
}
Example #14
0
static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
{
  struct ImBuf *ima;
  unsigned int *drect, *srect;
  float scaledx, scaledy;
  short ex, ey, dx, dy;

  /* paranoia test */
  if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
    return;
  }

  /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
  ima = IMB_dupImBuf(ibuf);

  if (!ima) {
    return;
  }

  if (ima->x > ima->y) {
    scaledx = (float)w;
    scaledy = ((float)ima->y / (float)ima->x) * (float)w;
  }
  else {
    scaledx = ((float)ima->x / (float)ima->y) * (float)h;
    scaledy = (float)h;
  }

  ex = (short)scaledx;
  ey = (short)scaledy;

  dx = (w - ex) / 2;
  dy = (h - ey) / 2;

  IMB_scalefastImBuf(ima, ex, ey);

  /* if needed, convert to 32 bits */
  if (ima->rect == NULL) {
    IMB_rect_from_float(ima);
  }

  srect = ima->rect;
  drect = rect;

  drect += dy * w + dx;
  for (; ey > 0; ey--) {
    memcpy(drect, srect, ex * sizeof(int));
    drect += w;
    srect += ima->x;
  }

  IMB_freeImBuf(ima);
}
Example #15
0
ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, ImBuf *ibuf, int cfra)
{
	SequenceModifierData *smd;
	ImBuf *processed_ibuf = ibuf;

	if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
		processed_ibuf = IMB_dupImBuf(ibuf);
		BKE_sequencer_imbuf_from_sequencer_space(context.scene, processed_ibuf);
	}

	for (smd = seq->modifiers.first; smd; smd = smd->next) {
		SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);

		/* could happen if modifier is being removed or not exists in current version of blender */
		if (!smti)
			continue;

		/* modifier is muted, do nothing */
		if (smd->flag & SEQUENCE_MODIFIER_MUTE)
			continue;

		if (smti->apply) {
			ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL);

			if (processed_ibuf == ibuf)
				processed_ibuf = IMB_dupImBuf(ibuf);

			smti->apply(smd, processed_ibuf, mask);

			if (mask)
				IMB_freeImBuf(mask);
		}
	}

	if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
		BKE_sequencer_imbuf_to_sequencer_space(context.scene, processed_ibuf, FALSE);
	}

	return processed_ibuf;
}
static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb) (ImBuf *ibuf))
{
	ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
	ImBuf *scope;
	
	IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
		                                             &scene->display_settings);

	scope = make_scope_cb(display_ibuf);

	IMB_freeImBuf(display_ibuf);

	return scope;
}
Example #17
0
static void thumbnails_update(void *tjv)
{
	ThumbnailJob *tj = tjv;

	if (tj->filelist && tj->filelist->filelist) {
		FileImage *limg = tj->loadimages.first;
		while (limg) {
			if (!limg->done && limg->img) {
				tj->filelist->filelist[limg->index].image = IMB_dupImBuf(limg->img);
				limg->done = true;
				IMB_freeImBuf(limg->img);
				limg->img = NULL;
			}
			limg = limg->next;
		}
	}
}
Example #18
0
/**
 * Only copy internal data of Brush ID from source to already allocated/initialized destination.
 * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
 *
 * WARNING! This function will not handle ID user count!
 *
 * \param flag  Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
 */
void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *brush_src, const int flag)
{
	if (brush_src->icon_imbuf) {
		brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf);
	}

	if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
		BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id);
	}
	else {
		brush_dst->preview = NULL;
	}

	brush_dst->curve = curvemapping_copy(brush_src->curve);

	/* enable fake user by default */
	id_fake_user_set(&brush_dst->id);
}
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id)
{
	ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
	RenderView *rv = RE_RenderViewGetById(rr, view_id);

	/* if not exists, BKE_imbuf_write makes one */
	ibuf->rect = (unsigned int *) rv->rect32;
	ibuf->rect_float = rv->rectf;
	ibuf->zbuf_float = rv->rectz;

	/* float factor for random dither, imbuf takes care of it */
	ibuf->dither = rd->dither_intensity;
	
	/* prepare to gamma correct to sRGB color space
	 * note that sequence editor can generate 8bpc render buffers
	 */
	if (ibuf->rect) {
		if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
			if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
				/* Higher depth bits are supported but not needed for current file output. */
				ibuf->rect_float = NULL;
			}
			else {
				IMB_float_from_rect(ibuf);
			}
		}
		else {
			/* ensure no float buffer remained from previous frame */
			ibuf->rect_float = NULL;
		}
	}

	/* color -> grayscale */
	/* editing directly would alter the render view */
	if (rd->im_format.planes == R_IMF_PLANES_BW) {
		ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
		IMB_color_to_bw(ibuf_bw);
		IMB_freeImBuf(ibuf);
		ibuf = ibuf_bw;
	}

	return ibuf;
}
Example #20
0
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
{
	char name[FILE_MAX];
	int quality, rectx, recty;
	int size = rendersize_to_number(proxy_render_size);
	ImBuf *scaleibuf;

	get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);

	rectx = ibuf->x * size / 100.0f;
	recty = ibuf->y * size / 100.0f;

	scaleibuf = IMB_dupImBuf(ibuf);

	if (threaded)
		IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
	else
		IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);

	quality = clip->proxy.quality;
	scaleibuf->ftype = JPG | quality;

	/* unsupported feature only confuses other s/w */
	if (scaleibuf->planes == 32)
		scaleibuf->planes = 24;

	/* TODO: currently the most weak part of multithreaded proxies,
	 *       could be solved in a way that thread only prepares memory
	 *       buffer and write to disk happens separately
	 */
	BLI_lock_thread(LOCK_MOVIECLIP);

	BLI_make_existing_file(name);
	if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
		perror(name);

	BLI_unlock_thread(LOCK_MOVIECLIP);

	IMB_freeImBuf(scaleibuf);
}
Example #21
0
static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int postprocess_flag)
{
	ImBuf *postproc_ibuf = NULL;

	if (need_undistortion_postprocess(user)) {
		postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
	}
	else {
		postproc_ibuf = IMB_dupImBuf(ibuf);
	}

	if (postprocess_flag) {
		bool disable_red   = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0,
			 disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0,
			 disable_blue  = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0,
			 grayscale     = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;

		if (disable_red || disable_green || disable_blue || grayscale)
			BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
	}

	return postproc_ibuf;
}
Example #22
0
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
{
	Scene *scene = oglrender->scene;
	ARegion *ar = oglrender->ar;
	View3D *v3d = oglrender->v3d;
	RegionView3D *rv3d = oglrender->rv3d;
	Object *camera = NULL;
	ImBuf *ibuf;
	int sizex = oglrender->sizex;
	int sizey = oglrender->sizey;
	const short view_context = (v3d != NULL);
	bool draw_bgpic = true;
	bool draw_sky = (scene->r.alphamode == R_ADDSKY);
	unsigned char *rect = NULL;
	const char *viewname = RE_GetActiveRenderView(oglrender->re);

	if (oglrender->is_sequencer) {
		SeqRenderData context;
		SpaceSeq *sseq = oglrender->sseq;
		int chanshown = sseq ? sseq->chanshown : 0;
		struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;

		BKE_sequencer_new_render_data(
		        oglrender->bmain->eval_ctx, oglrender->bmain, scene,
		        oglrender->sizex, oglrender->sizey, 100.0f,
		        &context);

		context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
		context.gpu_offscreen = oglrender->ofs;
		context.gpu_fx = oglrender->fx;
		context.gpu_full_samples = oglrender->ofs_full_samples;

		ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);

		if (ibuf) {
			ImBuf *out = IMB_dupImBuf(ibuf);
			IMB_freeImBuf(ibuf);
			/* OpenGL render is considered to be preview and should be
			 * as fast as possible. So currently we're making sure sequencer
			 * result is always byte to simplify color management pipeline.
			 *
			 * TODO(sergey): In the case of output to float container (EXR)
			 * it actually makes sense to keep float buffer instead.
			 */
			if (out->rect_float != NULL) {
				IMB_rect_from_float(out);
				imb_freerectfloatImBuf(out);
			}
			BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
			RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
			IMB_freeImBuf(out);
		}

		if (gpd) {
			int i;
			unsigned char *gp_rect;
			unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;

			GPU_offscreen_bind(oglrender->ofs, true);

			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			wmOrtho2(0, sizex, 0, sizey);
			glTranslatef(sizex / 2, sizey / 2, 0.0f);

			G.f |= G_RENDER_OGL;
			ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
			G.f &= ~G_RENDER_OGL;

			gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);

			for (i = 0; i < sizex * sizey * 4; i += 4) {
				blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
			}
			GPU_offscreen_unbind(oglrender->ofs, true);

			MEM_freeN(gp_rect);
		}
	}
	else {
		/* shouldnt suddenly give errors mid-render but possible */
		char err_out[256] = "unknown";
		ImBuf *ibuf_view;
		const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;

		if (view_context) {
			ibuf_view = ED_view3d_draw_offscreen_imbuf(
			       scene, v3d, ar, sizex, sizey,
			       IB_rect, draw_bgpic,
			       alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
			       oglrender->fx, oglrender->ofs, err_out);

			/* for stamp only */
			if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
				camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
			}
		}
		else {
			ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
			        scene, scene->camera, oglrender->sizex, oglrender->sizey,
			        IB_rect, OB_SOLID, false, true, true,
			        alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
			        oglrender->fx, oglrender->ofs, err_out);
			camera = scene->camera;
		}

		if (ibuf_view) {
			/* steal rect reference from ibuf */
			rect = (unsigned char *)ibuf_view->rect;
			ibuf_view->mall &= ~IB_rect;

			IMB_freeImBuf(ibuf_view);
		}
		else {
			fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
		}
	}

	/* note on color management:
	 *
	 * OpenGL renders into sRGB colors, but render buffers are expected to be
	 * linear So we convert to linear here, so the conversion back to bytes can make it
	 * sRGB (or other display space) again, and so that e.g. openexr saving also saves the
	 * correct linear float buffer.
	 */

	if (rect) {
		int profile_to;
		float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf;

		if (BKE_scene_check_color_management_enabled(scene))
			profile_to = IB_PROFILE_LINEAR_RGB;
		else
			profile_to = IB_PROFILE_SRGB;

		/* sequencer has got trickier conversion happened above
		 * also assume opengl's space matches byte buffer color space */
		IMB_buffer_float_from_byte(rectf, rect,
		                           profile_to, IB_PROFILE_SRGB, true,
		                           oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);

		/* rr->rectf is now filled with image data */

		if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
			BKE_image_stamp_buf(scene, camera, NULL, rect, rectf, rr->rectx, rr->recty, 4);

		MEM_freeN(rect);
	}
}
Example #23
0
void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma)
{
	// check whether this map was already loaded:
	if (!_maps.empty()) {
		mapsMap::iterator m = _maps.find(iMapName);
		if (m != _maps.end()) {
			// lazy check for size changes
			ImagePyramid *pyramid = (*m).second;
			if ((pyramid->width() != width()) || (pyramid->height() != height())) {
				delete pyramid;
			}
			else {
				return;
			}
		}
	}

	string filePath;
	if (_MapsPath) {
		filePath = _MapsPath;
		filePath += iFileName;
	}
	else {
		filePath = iFileName;
	}

#if 0 //soc
	QImage *qimg;
	QImage newMap(filePath.c_str());
	if (newMap.isNull()) {
		cerr << "Could not load image file " << filePath << endl;
		return;
	}
	qimg = &newMap;
#endif
	/* OCIO_TODO: support different input color space */
	ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL);
	if (qimg == 0) {
		cerr << "Could not load image file " << filePath << endl;
		return;
	}

#if 0 // soc
	// resize
	QImage scaledImg;
	if ((newMap.width() != width()) || (newMap.height() != height())) {
		scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
		qimg = &scaledImg;
	}
#endif
	ImBuf *scaledImg;
	if ((qimg->x != width()) || (qimg->y != height())) {
		scaledImg = IMB_dupImBuf(qimg);
		IMB_scaleImBuf(scaledImg, width(), height());
	}


	// deal with color image
#if 0
	if (newMap->depth() != 8) {
		int w = newMap->width();
		int h = newMap->height();
		QImage *tmp = new QImage(w, h, 8);
		for (unsigned int y = 0; y < h; ++y) {
			for (unsigned int x = 0; x < w; ++x) {
				int c = qGray(newMap->pixel(x, y));
				tmp->setPixel(x, y, c);
			}
		}
		delete newMap;
		newMap = tmp;
	}
#endif

	int x, y;
	int w = qimg->x;
	int h = qimg->y;
	int rowbytes = w * 4;
	GrayImage tmp(w, h);
	char *pix;

	for (y = 0; y < h; ++y) {
		for (x = 0; x < w; ++x) {
			pix = (char *)qimg->rect + y * rowbytes + x * 4;
			float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32;
			tmp.setPixel(x, y, c);
		}
	}

#if 0
	GrayImage blur(w, h);
	GaussianFilter gf(4.0f);
	//int bound = gf.getBound();
	for (y = 0; y < h; ++y) {
		for (x = 0; x < w; ++x) {
			int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y);
			blur.setPixel(x, y, c);
		}
	}
#endif

	GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
	int ow = pyramid->width(0);
	int oh = pyramid->height(0);
	string base(iMapName); //soc
	for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) {
		// save each image:
#if 0
		w = pyramid.width(i);
		h = pyramid.height(i);
#endif

		//soc  QImage qtmp(ow, oh, QImage::Format_RGB32);
		ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect);

		//int k = (1 << i);
		for (y = 0; y < oh; ++y) {
			for (x = 0; x < ow; ++x) {
				int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i);
				//soc qtmp.setPixel(x, y, qRgb(c, c, c));
				pix = (char *)qtmp->rect + y * rowbytes + x * 4;
				pix[0] = pix[1] = pix[2] = c;
			}
		}
		//soc qtmp.save(base + QString::number(i) + ".bmp", "BMP");
		stringstream filename;
		filename << base;
		filename << i << ".bmp";
		qtmp->ftype = BMP;
		IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0);
	}

#if 0
	QImage *qtmp = new QImage(w, h, 32);
	for (y = 0; y < h; ++y) {
		for (x = 0; x < w; ++x) {
			int c = (int)blur.pixel(x, y);
			qtmp->setPixel(x, y, qRgb(c, c, c));
		}
	}
	delete newMap;
	newMap = qtmp;
#endif

	_maps[iMapName] = pyramid;
	//newMap->save("toto.bmp", "BMP");
}
Example #24
0
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
{
	Scene *scene = oglrender->scene;
	ARegion *ar = oglrender->ar;
	View3D *v3d = oglrender->v3d;
	RegionView3D *rv3d = oglrender->rv3d;
	Object *camera = NULL;
	ImBuf *ibuf;
	float winmat[4][4];
	int sizex = oglrender->sizex;
	int sizey = oglrender->sizey;
	const short view_context = (v3d != NULL);
	bool draw_bgpic = true;
	bool draw_sky = (scene->r.alphamode == R_ADDSKY);
	unsigned char *rect = NULL;
	const char *viewname = RE_GetActiveRenderView(oglrender->re);

	if (oglrender->is_sequencer) {
		SeqRenderData context;
		SpaceSeq *sseq = oglrender->sseq;
		int chanshown = sseq ? sseq->chanshown : 0;
		struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;

		BKE_sequencer_new_render_data(
		        oglrender->bmain->eval_ctx, oglrender->bmain, scene,
		        oglrender->sizex, oglrender->sizey, 100.0f,
		        &context);

		context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
		ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);

		if (ibuf) {
			float *rectf;
			ImBuf *linear_ibuf;

			BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));

			linear_ibuf = IMB_dupImBuf(ibuf);
			IMB_freeImBuf(ibuf);

			if (linear_ibuf->rect_float == NULL) {
				/* internally sequencer working in display space and stores both bytes and float buffers in that space.
				 * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie
				 * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear
				 */

				IMB_float_from_rect(linear_ibuf);
			}
			else {
				/* ensure float buffer is in linear space, not in display space */
				BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
			}

			rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
			memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);

			IMB_freeImBuf(linear_ibuf);
		}

		if (gpd) {
			int i;
			unsigned char *gp_rect;

			GPU_offscreen_bind(oglrender->ofs, true);

			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			wmOrtho2(0, sizex, 0, sizey);
			glTranslatef(sizex / 2, sizey / 2, 0.0f);

			G.f |= G_RENDER_OGL;
			ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
			G.f &= ~G_RENDER_OGL;

			gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);

			for (i = 0; i < sizex * sizey * 4; i += 4) {
				float  col_src[4];
				rgba_uchar_to_float(col_src, &gp_rect[i]);
				blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src);
			}
			GPU_offscreen_unbind(oglrender->ofs, true);

			MEM_freeN(gp_rect);
		}
	}
	else if (view_context) {
		bool is_persp;
		/* full copy */
		GPUFXSettings fx_settings = v3d->fx_settings;

		ED_view3d_draw_offscreen_init(scene, v3d);

		GPU_offscreen_bind(oglrender->ofs, true); /* bind */

		/* render 3d view */
		if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
			/*int is_ortho = scene->r.mode & R_ORTHO;*/
			camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
			RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
			if (camera->type == OB_CAMERA) {
				Camera *cam = camera->data;
				is_persp = cam->type == CAM_PERSP;
			}
			else
				is_persp = true;
			BKE_camera_to_gpu_dof(camera, &fx_settings);
		}
		else {
			rctf viewplane;
			float clipsta, clipend;

			bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
			if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
			else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);

			is_persp = !is_ortho;
		}

		rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");

		if ((scene->r.mode & R_OSA) == 0) {
			ED_view3d_draw_offscreen(
			        scene, v3d, ar, sizex, sizey, NULL, winmat,
			        draw_bgpic, draw_sky, is_persp,
			        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
		}
		else {
			/* simple accumulation, less hassle then FSAA FBO's */
			static float jit_ofs[32][2];
			float winmat_jitter[4][4];
			int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1");
			int i, j;

			BLI_jitter_init(jit_ofs, scene->r.osa);

			/* first sample buffer, also initializes 'rv3d->persmat' */
			ED_view3d_draw_offscreen(
			        scene, v3d, ar, sizex, sizey, NULL, winmat,
			        draw_bgpic, draw_sky, is_persp,
			        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);

			for (i = 0; i < sizex * sizey * 4; i++)
				accum_buffer[i] = rect[i];

			/* skip the first sample */
			for (j = 1; j < scene->r.osa; j++) {
				copy_m4_m4(winmat_jitter, winmat);
				window_translate_m4(winmat_jitter, rv3d->persmat,
				                    (jit_ofs[j][0] * 2.0f) / sizex,
				                    (jit_ofs[j][1] * 2.0f) / sizey);

				ED_view3d_draw_offscreen(
				        scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
				        draw_bgpic, draw_sky, is_persp,
				        oglrender->ofs, oglrender->fx, &fx_settings, viewname);
				GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);

				for (i = 0; i < sizex * sizey * 4; i++)
					accum_buffer[i] += rect[i];
			}

			for (i = 0; i < sizex * sizey * 4; i++)
				rect[i] = accum_buffer[i] / scene->r.osa;

			MEM_freeN(accum_buffer);
		}

		GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
	}
	else {
		/* shouldnt suddenly give errors mid-render but possible */
		char err_out[256] = "unknown";
		ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
		                                                         IB_rect, OB_SOLID, false, true, true,
		                                                         (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, err_out);
		camera = scene->camera;

		if (ibuf_view) {
			/* steal rect reference from ibuf */
			rect = (unsigned char *)ibuf_view->rect;
			ibuf_view->mall &= ~IB_rect;

			IMB_freeImBuf(ibuf_view);
		}
		else {
			fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
		}
	}

	/* note on color management:
	 *
	 * OpenGL renders into sRGB colors, but render buffers are expected to be
	 * linear So we convert to linear here, so the conversion back to bytes can make it
	 * sRGB (or other display space) again, and so that e.g. openexr saving also saves the
	 * correct linear float buffer.
	 */

	if (rect) {
		int profile_to;
		float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
		
		if (BKE_scene_check_color_management_enabled(scene))
			profile_to = IB_PROFILE_LINEAR_RGB;
		else
			profile_to = IB_PROFILE_SRGB;

		/* sequencer has got trickier conversion happened above
		 * also assume opengl's space matches byte buffer color space */
		IMB_buffer_float_from_byte(rectf, rect,
		                           profile_to, IB_PROFILE_SRGB, true,
		                           oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);

		/* rr->rectf is now filled with image data */

		if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
			BKE_image_stamp_buf(scene, camera, rect, rectf, rr->rectx, rr->recty, 4);

		MEM_freeN(rect);
	}
}
Example #25
0
static void screen_opengl_render_apply(OGLRender *oglrender)
{
	Scene *scene = oglrender->scene;
	ARegion *ar = oglrender->ar;
	View3D *v3d = oglrender->v3d;
	RegionView3D *rv3d = oglrender->rv3d;
	RenderResult *rr;
	Object *camera = NULL;
	ImBuf *ibuf;
	void *lock;
	float winmat[4][4];
	int sizex = oglrender->sizex;
	int sizey = oglrender->sizey;
	const short view_context = (v3d != NULL);
	bool draw_bgpic = true;
	bool draw_sky = (scene->r.alphamode == R_ADDSKY);
	unsigned char *rect = NULL;

	rr = RE_AcquireResultRead(oglrender->re);

	if (oglrender->is_sequencer) {
		SeqRenderData context;
		int chanshown = oglrender->sseq ? oglrender->sseq->chanshown : 0;

		context = BKE_sequencer_new_render_data(oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f);

		ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown);

		if (ibuf) {
			ImBuf *linear_ibuf;

			BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));

			linear_ibuf = IMB_dupImBuf(ibuf);
			IMB_freeImBuf(ibuf);

			if (linear_ibuf->rect_float == NULL) {
				/* internally sequencer working in display space and stores both bytes and float buffers in that space.
				 * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie
				 * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear
				 */

				IMB_float_from_rect(linear_ibuf);
			}
			else {
				/* ensure float buffer is in linear space, not in display space */
				BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
			}

			memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);

			IMB_freeImBuf(linear_ibuf);
		}
	}
	else if (view_context) {
		ED_view3d_draw_offscreen_init(scene, v3d);

		GPU_offscreen_bind(oglrender->ofs); /* bind */

		/* render 3d view */
		if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
			/*int is_ortho = scene->r.mode & R_ORTHO;*/
			camera = v3d->camera;
			RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
			
		}
		else {
			rctf viewplane;
			float clipsta, clipend;

			int is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
			if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
			else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
		}

		rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");

		if ((scene->r.mode & R_OSA) == 0) {
			ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
		}
		else {
			/* simple accumulation, less hassle then FSAA FBO's */
			static float jit_ofs[32][2];
			float winmat_jitter[4][4];
			int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1");
			int i, j;

			BLI_jitter_init(jit_ofs[0], scene->r.osa);

			/* first sample buffer, also initializes 'rv3d->persmat' */
			ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
			GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);

			for (i = 0; i < sizex * sizey * 4; i++)
				accum_buffer[i] = rect[i];

			/* skip the first sample */
			for (j = 1; j < scene->r.osa; j++) {
				copy_m4_m4(winmat_jitter, winmat);
				window_translate_m4(winmat_jitter, rv3d->persmat,
				                    (jit_ofs[j][0] * 2.0f) / sizex,
				                    (jit_ofs[j][1] * 2.0f) / sizey);

				ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky);
				GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);

				for (i = 0; i < sizex * sizey * 4; i++)
					accum_buffer[i] += rect[i];
			}

			for (i = 0; i < sizex * sizey * 4; i++)
				rect[i] = accum_buffer[i] / scene->r.osa;

			MEM_freeN(accum_buffer);
		}

		GPU_offscreen_unbind(oglrender->ofs); /* unbind */
	}
	else {
		/* shouldnt suddenly give errors mid-render but possible */
		char err_out[256] = "unknown";
		ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
		                                                         IB_rect, OB_SOLID, FALSE, TRUE,
		                                                         (draw_sky) ? R_ADDSKY: R_ALPHAPREMUL, err_out);
		camera = scene->camera;

		if (ibuf_view) {
			/* steal rect reference from ibuf */
			rect = (unsigned char *)ibuf_view->rect;
			ibuf_view->mall &= ~IB_rect;

			IMB_freeImBuf(ibuf_view);
		}
		else {
			fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
		}
	}

	/* note on color management:
	 *
	 * OpenGL renders into sRGB colors, but render buffers are expected to be
	 * linear So we convert to linear here, so the conversion back to bytes can make it
	 * sRGB (or other display space) again, and so that e.g. openexr saving also saves the
	 * correct linear float buffer.
	 */

	if (rect) {
		int profile_to;
		
		if (BKE_scene_check_color_management_enabled(scene))
			profile_to = IB_PROFILE_LINEAR_RGB;
		else
			profile_to = IB_PROFILE_SRGB;

		/* sequencer has got trickier conversion happened above
		 * also assume opengl's space matches byte buffer color space */
		IMB_buffer_float_from_byte(rr->rectf, rect,
		                           profile_to, IB_PROFILE_SRGB, true,
		                           oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
	}

	/* rr->rectf is now filled with image data */

	if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
		BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4);

	RE_ReleaseResult(oglrender->re);

	/* update byte from float buffer */
	ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);

	if (ibuf) {
		/* update display buffer */
		if (ibuf->rect == NULL)
			imb_addrectImBuf(ibuf);

		IMB_partial_display_buffer_update(ibuf, rr->rectf, rect, rr->rectx, 0, 0,
		                                  &scene->view_settings, &scene->display_settings,
		                                  0, 0, rr->rectx, rr->recty, true);

		/* write file for animation */
		if (oglrender->write_still) {
			char name[FILE_MAX];
			int ok;

			if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) {
				IMB_color_to_bw(ibuf);
			}

			BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE);
			ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, TRUE); /* no need to stamp here */
			if (ok) printf("OpenGL Render written to '%s'\n", name);
			else printf("OpenGL Render failed to write '%s'\n", name);
		}
	}
	
	BKE_image_release_ibuf(oglrender->ima, ibuf, lock);

	if (rect)
		MEM_freeN(rect);
}
Example #26
0
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
	Main *bmain = CTX_data_main(C);
	OGLRender *oglrender = op->customdata;
	Scene *scene = oglrender->scene;
	ImBuf *ibuf, *ibuf_save = NULL;
	void *lock;
	char name[FILE_MAX];
	int ok = 0;
	const short view_context = (oglrender->v3d != NULL);
	Object *camera = NULL;
	int is_movie;

	/* go to next frame */
	if (CFRA < oglrender->nfra)
		CFRA++;
	while (CFRA < oglrender->nfra) {
		unsigned int lay = screen_opengl_layers(oglrender);

		if (lay & 0xFF000000)
			lay &= 0xFF000000;

		BKE_scene_update_for_newframe(bmain, scene, lay);
		CFRA++;
	}

	is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);

	if (!is_movie) {
		BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);

		if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
			BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
			ok = true;
			goto finally;
		}
	}

	WM_cursor_time(oglrender->win, scene->r.cfra);

	BKE_scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender));

	if (view_context) {
		if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
			/* since BKE_scene_update_for_newframe() is used rather
			 * then ED_update_for_newframe() the camera needs to be set */
			if (BKE_scene_camera_switch_update(scene)) {
				oglrender->v3d->camera = scene->camera;
			}

			camera = oglrender->v3d->camera;
		}
	}
	else {
		BKE_scene_camera_switch_update(scene);

		camera = scene->camera;
	}

	/* render into offscreen buffer */
	screen_opengl_render_apply(oglrender);

	/* save to disk */
	ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);

	if (ibuf) {
		int needs_free = FALSE;

		ibuf_save = ibuf;

		if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) {
			ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
			                                                &scene->display_settings, &scene->r.im_format);

			needs_free = TRUE;
		}

		/* color -> grayscale */
		/* editing directly would alter the render view */
		if (scene->r.im_format.planes == R_IMF_PLANES_BW) {
			ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save);
			IMB_color_to_bw(ibuf_bw);

			if (needs_free)
				IMB_freeImBuf(ibuf_save);

			ibuf_save = ibuf_bw;
		}
		else {
			/* this is lightweight & doesnt re-alloc the buffers, only do this
			 * to save the correct bit depth since the image is always RGBA */
			ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0);

			ibuf_cpy->rect = ibuf_save->rect;
			ibuf_cpy->rect_float = ibuf_save->rect_float;
			ibuf_cpy->zbuf_float = ibuf_save->zbuf_float;

			if (needs_free) {
				ibuf_cpy->mall = ibuf_save->mall;
				ibuf_save->mall = 0;
				IMB_freeImBuf(ibuf_save);
			}

			ibuf_save = ibuf_cpy;
		}

		if (is_movie) {
			ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect,
			                                 oglrender->sizex, oglrender->sizey, oglrender->reports);
			if (ok) {
				printf("Append frame %d", scene->r.cfra);
				BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
			}
		}
		else {
			ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format);

			if (ok == 0) {
				printf("Write error: cannot save %s\n", name);
				BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
			}
			else {
				printf("Saved: %s", name);
				BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
			}
		}

		if (needs_free)
			IMB_freeImBuf(ibuf_save);
	}

	BKE_image_release_ibuf(oglrender->ima, ibuf, lock);

	/* movie stats prints have no line break */
	printf("\n");


finally:  /* Step the frame and bail early if needed */

	/* go to next frame */
	oglrender->nfra += scene->r.frame_step;

	/* stop at the end or on error */
	if (CFRA >= PEFRA || !ok) {
		screen_opengl_render_end(C, op->customdata);
		return 0;
	}

	return 1;
}
static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
                                int clip_index,
                                int frame,
                                libmv_InputMode input_mode,
                                int downscale,
                                const libmv_Region *region,
                                const libmv_FrameTransform *transform)
{
	ImBuf *ibuf, *orig_ibuf, *final_ibuf;
	int64_t transform_key = 0;

	if (transform != NULL) {
		transform_key = libmv_frameAccessorgetTransformKey(transform);
	}

	/* First try to get fully processed image from the cache. */
	ibuf = accesscache_get(accessor,
	                       clip_index,
	                       frame,
	                       input_mode,
	                       downscale,
	                       transform_key);
	if (ibuf != NULL) {
		return ibuf;
	}

	/* And now we do postprocessing of the original frame. */
	orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);

	if (orig_ibuf == NULL) {
		return NULL;
	}

	if (region != NULL) {
		int width = region->max[0] - region->min[0],
		    height = region->max[1] - region->min[1];

		/* If the requested region goes outside of the actual frame we still
		 * return the requested region size, but only fill it's partially with
		 * the data we can.
		 */
		int clamped_origin_x = max_ii((int)region->min[0], 0),
		    clamped_origin_y = max_ii((int)region->min[1], 0);
		int dst_offset_x = clamped_origin_x - (int)region->min[0],
		    dst_offset_y = clamped_origin_y - (int)region->min[1];
		int clamped_width = width - dst_offset_x,
		    clamped_height = height - dst_offset_y;
		clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
		clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);

		final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);

		if (orig_ibuf->rect_float != NULL) {
			IMB_rectcpy(final_ibuf, orig_ibuf,
			            dst_offset_x, dst_offset_y,
			            clamped_origin_x, clamped_origin_y,
			            clamped_width, clamped_height);
		}
		else {
			int y;
			/* TODO(sergey): We don't do any color space or alpha conversion
			 * here. Probably Libmv is better to work in the linear space,
			 * but keep sRGB space here for compatibility for now.
			 */
			for (y = 0; y < clamped_height; ++y) {
				int x;
				for (x = 0; x < clamped_width; ++x) {
					int src_x = x + clamped_origin_x,
					    src_y = y + clamped_origin_y;
					int dst_x = x + dst_offset_x,
					    dst_y = y + dst_offset_y;
					int dst_index = (dst_y * width + dst_x) * 4,
					    src_index = (src_y * orig_ibuf->x + src_x) * 4;
					rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
					                    (unsigned char *)orig_ibuf->rect +
					                                     src_index);
				}
			}
		}
	}
	else {
		/* Libmv only works with float images,
		 *
		 * This would likely make it so loads of float buffers are being stored
		 * in the cache which is nice on the one hand (faster re-use of the
		 * frames) but on the other hand it bumps the memory usage up.
		 */
		BLI_lock_thread(LOCK_MOVIECLIP);
		IMB_float_from_rect(orig_ibuf);
		BLI_unlock_thread(LOCK_MOVIECLIP);
		final_ibuf = orig_ibuf;
	}

	if (downscale > 0) {
		if (final_ibuf == orig_ibuf) {
			final_ibuf = IMB_dupImBuf(orig_ibuf);
		}
		IMB_scaleImBuf(final_ibuf,
		               ibuf->x / (1 << downscale),
		               ibuf->y / (1 << downscale));
	}

	if (transform != NULL) {
		libmv_FloatImage input_image, output_image;
		ibuf_to_float_image(final_ibuf, &input_image);
		libmv_frameAccessorgetTransformRun(transform,
		                                   &input_image,
		                                   &output_image);
		if (final_ibuf != orig_ibuf) {
			IMB_freeImBuf(final_ibuf);
		}
		final_ibuf = float_image_to_ibuf(&output_image);
		libmv_floatImageDestroy(&output_image);
	}

	if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
		BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
		/* pass */
	}
	else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
		if (final_ibuf->channels != 1) {
			ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
			if (final_ibuf != orig_ibuf) {
				/* We dereference original frame later. */
				IMB_freeImBuf(final_ibuf);
			}
			final_ibuf = grayscale_ibuf;
		}
	}

	/* it's possible processing still didn't happen at this point,
	 * but we really need a copy of the buffer to be transformed
	 * and to be put to the cache.
	 */
	if (final_ibuf == orig_ibuf) {
		final_ibuf = IMB_dupImBuf(orig_ibuf);
	}

	IMB_freeImBuf(orig_ibuf);

	/* We put postprocessed frame to the cache always for now,
	 * not the smartest thing in the world, but who cares at this point.
	 */

	/* TODO(sergey): Disable cache for now, because we don't store region
	 * in the cache key and can't check whether cached version is usable for
	 * us or not.
	 *
	 * Need to think better about what to cache and when.
	 */
	if (false) {
		accesscache_put(accessor,
		                clip_index,
		                frame,
		                input_mode,
		                downscale,
		                transform_key,
		                final_ibuf);
	}

	return final_ibuf;
}
Example #28
0
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
	struct Main *bmain = CTX_data_main(C);
	struct ImBuf *ibuf = NULL;
	struct ImBuf *scope = NULL;
	struct View2D *v2d = &ar->v2d;
	/* int rectx, recty; */ /* UNUSED */
	float viewrect[2];
	float col[3];
	GLuint texid;
	GLuint last_texid;
	void *display_buffer;
	void *cache_handle = NULL;
	const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
	int format, type;
	bool glsl_used = false;
	const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
	const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
	bool draw_metadata = false;

	if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
		/* stop all running jobs, except screen one. currently previews frustrate Render
		 * needed to make so sequencer's rendering doesn't conflict with compositor
		 */
		WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE);

		if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
			/* in case of final rendering used for preview, kill all previews,
			 * otherwise threading conflict will happen in rendering module
			 */
			WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
		}
	}

	if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
		UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
		glClearColor(col[0], col[1], col[2], 0.0);
		glClear(GL_COLOR_BUFFER_BIT);
	}

	/* without this colors can flicker from previous opengl state */
	glColor4ub(255, 255, 255, 255);

	/* only initialize the preview if a render is in progress */
	if (G.is_rendering)
		return;

	if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
		return;
	}

	/* for now we only support Left/Right */
	ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);

	if ((ibuf == NULL) ||
	    (ibuf->rect == NULL && ibuf->rect_float == NULL))
	{
		/* gpencil can also be drawn without a valid imbuf */
		if (draw_gpencil && is_imbuf) {
			sequencer_display_size(scene, sseq, viewrect);

			sequencer_draw_background(sseq, v2d, viewrect);
			sequencer_draw_borders(sseq, v2d, scene);

			sequencer_draw_gpencil(C);
		}
		return;
	}

	sequencer_display_size(scene, sseq, viewrect);

	if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
		SequencerScopes *scopes = &sseq->scopes;

		sequencer_check_scopes(scopes, ibuf);

		switch (sseq->mainb) {
			case SEQ_DRAW_IMG_IMBUF:
				if (!scopes->zebra_ibuf) {
					ImBuf *display_ibuf = IMB_dupImBuf(ibuf);

					if (display_ibuf->rect_float) {
						IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
						                                             &scene->display_settings);
					}
					scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
					IMB_freeImBuf(display_ibuf);
				}
				scope = scopes->zebra_ibuf;
				break;
			case SEQ_DRAW_IMG_WAVEFORM:
				if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
					if (!scopes->sep_waveform_ibuf)
						scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
					scope = scopes->sep_waveform_ibuf;
				}
				else {
					if (!scopes->waveform_ibuf)
						scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
					scope = scopes->waveform_ibuf;
				}
				break;
			case SEQ_DRAW_IMG_VECTORSCOPE:
				if (!scopes->vector_ibuf)
					scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
				scope = scopes->vector_ibuf;
				break;
			case SEQ_DRAW_IMG_HISTOGRAM:
				if (!scopes->histogram_ibuf)
					scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
				scope = scopes->histogram_ibuf;
				break;
		}

		/* future files may have new scopes we don't catch above */
		if (scope) {
			scopes->reference_ibuf = ibuf;
			if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
				/* scopes drawn in image preview use viewrect from orig ibuf - currently that's only zebra */
			}
			else {
				viewrect[0] = scope->x;
				viewrect[1] = scope->y;
			}
		}
		else {
			scopes->reference_ibuf = NULL;
		}
	}

	if (!draw_backdrop) {
		sequencer_draw_background(sseq, v2d, viewrect);
	}

	if (scope) {
		IMB_freeImBuf(ibuf);
		ibuf = scope;

		if (ibuf->rect_float && ibuf->rect == NULL) {
			IMB_rect_from_float(ibuf);
		}

		display_buffer = (unsigned char *)ibuf->rect;
		format = GL_RGBA;
		type = GL_UNSIGNED_BYTE;
	}
	else {
		bool force_fallback = false;

		force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
		force_fallback |= (ibuf->dither != 0.0f);

		if (force_fallback) {
			/* Fallback to CPU based color space conversion */
			glsl_used = false;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}
		else if (ibuf->rect_float) {
			display_buffer = ibuf->rect_float;

			if (ibuf->channels == 4) {
				format = GL_RGBA;
			}
			else if (ibuf->channels == 3) {
				format = GL_RGB;
			}
			else {
				BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
				format = GL_RGBA;
				display_buffer = NULL;
			}

			type = GL_FLOAT;

			if (ibuf->float_colorspace) {
				glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, ibuf->dither, true);
			}
			else {
				glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true);
			}
		}
		else if (ibuf->rect) {
			display_buffer = ibuf->rect;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;

			glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, ibuf->dither, false);
		}
		else {
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}

		/* there's a data to be displayed, but GLSL is not initialized
		 * properly, in this case we fallback to CPU-based display transform
		 */
		if ((ibuf->rect || ibuf->rect_float) && !glsl_used) {
			display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
		}
	}

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glColor4f(1.0, 1.0, 1.0, 1.0);

	last_texid = glaGetOneInteger(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);
	glGenTextures(1, (GLuint *)&texid);

	glBindTexture(GL_TEXTURE_2D, texid);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	if (type == GL_FLOAT)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer);
	else
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);

	if (draw_backdrop) {
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();
	}
	glBegin(GL_QUADS);

	if (draw_overlay) {
		if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
			rctf tot_clip;
			tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
			tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
			tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
			tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);

			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
		}
		else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
			glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
		}
	}
	else if (draw_backdrop) {
		float aspect;
		float image_aspect = viewrect[0] / viewrect[1];
		float imagex, imagey;

		aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);

		if (aspect >= image_aspect) {
			imagex = image_aspect / aspect;
			imagey = 1.0f;
		}
		else {
			imagex = 1.0f;
			imagey = aspect / image_aspect;
		}

		glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
	}
	else {
		draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);

		glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
	}
	glEnd();

	glBindTexture(GL_TEXTURE_2D, last_texid);
	glDisable(GL_TEXTURE_2D);
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
		glDisable(GL_BLEND);
	glDeleteTextures(1, &texid);

	if (glsl_used)
		IMB_colormanagement_finish_glsl_draw();

	if (cache_handle)
		IMB_display_buffer_release(cache_handle);

	if (!scope)
		IMB_freeImBuf(ibuf);

	if (draw_metadata) {
		ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
	}

	if (draw_backdrop) {
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		return;
	}

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		sequencer_draw_borders(sseq, v2d, scene);
	}

	if (draw_gpencil && is_imbuf) {
		sequencer_draw_gpencil(C);
	}
	else {
		/* ortho at pixel level */
		UI_view2d_view_restore(C);
	}


	/* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
	 * for now just disable drawing since the strip frame will likely be offset */

	//if (sc->mode == SC_MODE_MASKEDIT) {
	if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		Mask *mask = BKE_sequencer_mask_get(scene);

		if (mask) {
			int width, height;
			float aspx = 1.0f, aspy = 1.0f;
			// ED_mask_get_size(C, &width, &height);

			//Scene *scene = CTX_data_scene(C);
			width = (scene->r.size * scene->r.xsch) / 100;
			height = (scene->r.size * scene->r.ysch) / 100;

			ED_mask_draw_region(mask, ar,
			                    0, 0, 0,  /* TODO */
			                    width, height,
			                    aspx, aspy,
			                    false, true,
			                    NULL, C);
		}
	}
}
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay)
{
	struct Main *bmain = CTX_data_main(C);
	struct ImBuf *ibuf = NULL;
	struct ImBuf *scope = NULL;
	struct View2D *v2d = &ar->v2d;
	/* int rectx, recty; */ /* UNUSED */
	float viewrectx, viewrecty;
	float render_size = 0.0;
	float proxy_size = 100.0;
	float col[3];
	GLuint texid;
	GLuint last_texid;
	void *display_buffer;
	void *cache_handle = NULL;
	const int is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
	int format, type;
	bool glsl_used = false;

	if (G.is_rendering == FALSE && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
		/* stop all running jobs, except screen one. currently previews frustrate Render
		 * needed to make so sequencer's rendering doesn't conflict with compositor
		 */
		WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE);

		if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
			/* in case of final rendering used for preview, kill all previews,
			 * otherwise threading conflict will happen in rendering module
			 */
			WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW);
		}
	}

	render_size = sseq->render_size;
	if (render_size == 0) {
		render_size = scene->r.size;
	}
	else {
		proxy_size = render_size;
	}
	if (render_size < 0) {
		return;
	}

	viewrectx = (render_size * (float)scene->r.xsch) / 100.0f;
	viewrecty = (render_size * (float)scene->r.ysch) / 100.0f;

	/* rectx = viewrectx + 0.5f; */ /* UNUSED */
	/* recty = viewrecty + 0.5f; */ /* UNUSED */

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		viewrectx *= scene->r.xasp / scene->r.yasp;
		viewrectx /= proxy_size / 100.0f;
		viewrecty /= proxy_size / 100.0f;
	}

	if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
		UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
		glClearColor(col[0], col[1], col[2], 0.0);
		glClear(GL_COLOR_BUFFER_BIT);
	}

	/* without this colors can flicker from previous opengl state */
	glColor4ub(255, 255, 255, 255);

	UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
	UI_view2d_curRect_validate(v2d);

	/* only initialize the preview if a render is in progress */
	if (G.is_rendering)
		return;

	ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs);
	
	if (ibuf == NULL)
		return;

	if (ibuf->rect == NULL && ibuf->rect_float == NULL)
		return;

	if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) {
		SequencerScopes *scopes = &sseq->scopes;

		sequencer_check_scopes(scopes, ibuf);

		switch (sseq->mainb) {
			case SEQ_DRAW_IMG_IMBUF:
				if (!scopes->zebra_ibuf) {
					ImBuf *display_ibuf = IMB_dupImBuf(ibuf);

					if (display_ibuf->rect_float) {
						IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings,
						                                             &scene->display_settings);
					}
					scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
					IMB_freeImBuf(display_ibuf);
				}
				scope = scopes->zebra_ibuf;
				break;
			case SEQ_DRAW_IMG_WAVEFORM:
				if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
					if (!scopes->sep_waveform_ibuf)
						scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
					scope = scopes->sep_waveform_ibuf;
				}
				else {
					if (!scopes->waveform_ibuf)
						scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
					scope = scopes->waveform_ibuf;
				}
				break;
			case SEQ_DRAW_IMG_VECTORSCOPE:
				if (!scopes->vector_ibuf)
					scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
				scope = scopes->vector_ibuf;
				break;
			case SEQ_DRAW_IMG_HISTOGRAM:
				if (!scopes->histogram_ibuf)
					scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
				scope = scopes->histogram_ibuf;
				break;
		}

		scopes->reference_ibuf = ibuf;
	}

	/* setting up the view - actual drawing starts here */
	UI_view2d_view_ortho(v2d);

	/* only draw alpha for main buffer */
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		if (sseq->flag & SEQ_USE_ALPHA) {
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
			glColor4f(1.0, 1.0, 1.0, 1.0);
		}
	}

	if (scope) {
		IMB_freeImBuf(ibuf);
		ibuf = scope;

		if (ibuf->rect_float && ibuf->rect == NULL) {
			IMB_rect_from_float(ibuf);
		}

		display_buffer = (unsigned char *)ibuf->rect;
		format = GL_RGBA;
		type = GL_UNSIGNED_BYTE;
	}
	else {
		bool force_fallback = false;

		force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
		force_fallback |= (ibuf->dither != 0.0f);

		if (force_fallback) {
			/* Fallback to CPU based color space conversion */
			glsl_used = false;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}
		else if (ibuf->rect_float) {
			display_buffer = ibuf->rect_float;

			if (ibuf->channels == 4) {
				format = GL_RGBA;
			}
			else if (ibuf->channels == 3) {
				format = GL_RGB;
			}
			else {
				BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
				format = GL_RGBA;
				display_buffer = NULL;
			}

			type = GL_FLOAT;

			if (ibuf->float_colorspace) {
				glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true);
			}
			else {
				glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true);
			}
		}
		else if (ibuf->rect) {
			display_buffer = ibuf->rect;
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;

			glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false);
		}
		else {
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
			display_buffer = NULL;
		}

		/* there's a data to be displayed, but GLSL is not initialized
		 * properly, in this case we fallback to CPU-based display transform
		 */
		if ((ibuf->rect || ibuf->rect_float) && !glsl_used) {
			display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
			format = GL_RGBA;
			type = GL_UNSIGNED_BYTE;
		}
	}

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glColor4f(1.0, 1.0, 1.0, 1.0);

	last_texid = glaGetOneInteger(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);
	glGenTextures(1, (GLuint *)&texid);

	glBindTexture(GL_TEXTURE_2D, texid);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	if (type == GL_FLOAT)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, ibuf->x, ibuf->y, 0, format, type, display_buffer);
	else
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);

	glBegin(GL_QUADS);

	if (draw_overlay) {
		if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
			rctf tot_clip;
			tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin);
			tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
			tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
			tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);

			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
			glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
			glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
		}
		else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
			glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
		}
	}
	else {
		glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
		glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
		glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
		glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
	}
	glEnd();
	glBindTexture(GL_TEXTURE_2D, last_texid);
	glDisable(GL_TEXTURE_2D);
	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
		glDisable(GL_BLEND);
	glDeleteTextures(1, &texid);

	if (glsl_used)
		IMB_colormanagement_finish_glsl_draw();

	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {

		float x1 = v2d->tot.xmin;
		float y1 = v2d->tot.ymin;
		float x2 = v2d->tot.xmax;
		float y2 = v2d->tot.ymax;

		/* border */
		setlinestyle(3);

		UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);

		glBegin(GL_LINE_LOOP);
		glVertex2f(x1 - 0.5f, y1 - 0.5f);
		glVertex2f(x1 - 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y2 + 0.5f);
		glVertex2f(x2 + 0.5f, y1 - 0.5f);
		glEnd();

		/* safety border */
		if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
			float fac = 0.1;

			float a = fac * (x2 - x1);
			x1 += a;
			x2 -= a;

			a = fac * (y2 - y1);
			y1 += a;
			y2 -= a;

			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

			uiSetRoundBox(UI_CNR_ALL);
			uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);

			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

		}

		setlinestyle(0);
	}
	
	if (sseq->flag & SEQ_SHOW_GPENCIL) {
		if (is_imbuf) {
			/* draw grease-pencil (image aligned) */
			draw_gpencil_2dimage(C);
		}
	}

	if (!scope)
		IMB_freeImBuf(ibuf);
	
	/* ortho at pixel level */
	UI_view2d_view_restore(C);
	
	if (sseq->flag & SEQ_SHOW_GPENCIL) {
		if (is_imbuf) {
			/* draw grease-pencil (screen aligned) */
			draw_gpencil_view2d(C, 0);
		}
	}


	/* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
	 * for now just disable drawing since the strip frame will likely be offset */

	//if (sc->mode == SC_MODE_MASKEDIT) {
	if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
		Mask *mask = BKE_sequencer_mask_get(scene);

		if (mask) {
			int width, height;
			float aspx = 1.0f, aspy = 1.0f;
			// ED_mask_get_size(C, &width, &height);

			//Scene *scene = CTX_data_scene(C);
			width = (scene->r.size * scene->r.xsch) / 100;
			height = (scene->r.size * scene->r.ysch) / 100;

			ED_mask_draw_region(mask, ar,
			                    0, 0,  /* TODO */
			                    width, height,
			                    aspx, aspy,
			                    FALSE, TRUE,
			                    NULL, C);
		}
	}

	if (cache_handle)
		IMB_display_buffer_release(cache_handle);
}
Example #30
0
LIBEXPORT struct ImBuf *dupImBuf(struct ImBuf *ib)
{
    return IMB_dupImBuf(ib);
}