Пример #1
0
/* Return the floating point zbuffer */
static void rna_Image_zbuf_blensor(Image *image, bContext *C, ReportList *reports, int *outbuffer_len, float **outbuffer, Scene *scene)
{

    ImBuf *ibuf;
    int idx=0;
    if (scene == NULL) {
        scene = CTX_data_scene(C);
    }


    *outbuffer_len=0;

    ImageUser iuser;
    void *lock;

    iuser.scene = scene;
    iuser.ok = 1;

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

    if (ibuf == NULL) {
        BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image");
    }
    else {
        *outbuffer = (float *) MEM_mallocN(ibuf->x * ibuf->y * sizeof(float),"rna_Image_zbuf");
        if (*outbuffer == NULL)
        {
            BKE_reportf(reports, RPT_ERROR, "Couldn't allocate buffer for zbuffer output");
        }
        else
        {
            memcpy((void *)*outbuffer, (const void *)ibuf->zbuf_float, ibuf->x * ibuf->y* sizeof(float));
            *outbuffer_len = ibuf->x * ibuf->y;
        }

    }
    BKE_image_release_ibuf(image, ibuf, lock);

}
Пример #2
0
static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports, const char *path, Scene *scene)
{
	ImBuf *ibuf;

	if (scene == NULL) {
		scene = CTX_data_scene(C);
	}

	if (scene) {
		ImageUser iuser;
		void *lock;

		iuser.scene = scene;
		iuser.ok = 1;

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

		if (ibuf == NULL) {
			BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image");
		}
		else {
			/* temp swap out the color */
			const unsigned char imb_depth_back= ibuf->depth;
			const float dither_back= ibuf->dither; 
			ibuf->depth= scene->r.planes;
			ibuf->dither= scene->r.dither_intensity;
			if (!BKE_write_ibuf(ibuf, path, scene->r.imtype, scene->r.subimtype, scene->r.quality)) {
				BKE_reportf(reports, RPT_ERROR, "Couldn't write image: %s", path);
			}
			ibuf->depth= imb_depth_back;
			ibuf->dither= dither_back;
		}

		BKE_image_release_ibuf(image, lock);
	} else {
		BKE_reportf(reports, RPT_ERROR, "Scene not in context, couldn't get save parameters");
	}
}
Пример #3
0
static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
{
	RenderJob *rj = rjv;
	Image *ima = rj->image;
	ImBuf *ibuf;
	void *lock;

	/* only update if we are displaying the slot being rendered */
	if (ima->render_slot != ima->last_render_slot) {
		rj->image_outdated = true;
		return;
	}
	else if (rj->image_outdated) {
		/* update entire render */
		rj->image_outdated = false;
		BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
		*(rj->do_update) = TRUE;
		return;
	}

	/* update part of render */
	render_image_update_pass_and_layer(rj, rr, &rj->iuser);
	ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
	if (ibuf) {
		/* Don't waste time on CPU side color management if
		 * image will be displayed using GLSL.
		 */
		if (ibuf->channels == 1 ||
		    U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
		{
			image_buffer_rect_update(rj->scene, rr, ibuf, &rj->iuser, renrect);
		}

		/* make jobs timer to send notifier */
		*(rj->do_update) = TRUE;
	}
	BKE_image_release_ibuf(ima, ibuf, lock);
}
void ViewerOperation::initImage()
{
	Image *ima = this->m_image;
	void *lock;
	ImBuf *ibuf = BKE_image_acquire_ibuf(ima, this->m_imageUser, &lock);

	if (!ibuf) return;
	BLI_lock_thread(LOCK_DRAW_IMAGE);
	if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {

		imb_freerectImBuf(ibuf);
		imb_freerectfloatImBuf(ibuf);
		IMB_freezbuffloatImBuf(ibuf);
		ibuf->x = getWidth();
		ibuf->y = getHeight();
		imb_addrectfloatImBuf(ibuf);
		ima->ok = IMA_OK_LOADED;

		ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
	}

	if (m_doDepthBuffer) {
		addzbuffloatImBuf(ibuf);
	}
	BLI_unlock_thread(LOCK_DRAW_IMAGE);

	/* now we combine the input with ibuf */
	this->m_outputBuffer = ibuf->rect_float;

	/* needed for display buffer update */
	this->m_ibuf = ibuf;

	if (m_doDepthBuffer) {
		this->m_depthBuffer = ibuf->zbuf_float;
	}

	BKE_image_release_ibuf(this->m_image, this->m_ibuf, lock);
}
Пример #5
0
static void rna_Image_pixels_get(PointerRNA *ptr, 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(values, ibuf->rect_float, sizeof(float) * size);
		}
		else {
			for (i = 0; i < size; i++)
				values[i] = ((unsigned char *)ibuf->rect)[i] * (1.0f / 255.0f);
		}
	}

	BKE_image_release_ibuf(ima, ibuf, lock);
}
static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
	Tex *tex = (Tex *)node->id;

	if (tex && tex->type == TEX_IMAGE && tex->ima) {
		GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false);
		int ret = GPU_stack_link(mat, "texture_image", in, out, texlink);

		if (ret) {
			ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
			if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
			    GPU_material_do_color_management(mat))
			{
				GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link);
			}
			BKE_image_release_ibuf(tex->ima, ibuf, NULL);
		}

		return ret;
	}
	else
		return 0;
}
Пример #7
0
static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
{
	MHeightBakeData *height_data;
	ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
	DerivedMesh *lodm = bkr->lores_dm;

	height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");

	height_data->ima = ima;
	height_data->heights = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights");
	height_data->height_max = -FLT_MAX;
	height_data->height_min = FLT_MAX;

	if (!bkr->use_lores_mesh) {
		SubsurfModifierData smd = {{NULL}};
		int ss_lvl = bkr->tot_lvl - bkr->lvl;

		CLAMP(ss_lvl, 0, 6);

		if (ss_lvl > 0) {
			smd.levels = smd.renderLevels = ss_lvl;
			smd.flags |= eSubsurfModifierFlag_SubsurfUv;

			if (bkr->simple)
				smd.subdivType = ME_SIMPLE_SUBSURF;

			height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0);
		}
	}

	height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
	height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);

	BKE_image_release_ibuf(ima, ibuf, NULL);

	return (void *)height_data;
}
static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
	Image *ima = (Image *)node->id;
	ImageUser *iuser = NULL;
	NodeTexImage *tex = node->storage;
	int isdata = tex->color_space == SHD_COLORSPACE_NONE;

	if (!ima)
		return GPU_stack_link(mat, "node_tex_environment_empty", in, out);

	if (!in[0].link) {
		GPUMatType type = GPU_Material_get_type(mat);
		
		if (type == GPU_MATERIAL_TYPE_MESH)
			in[0].link = GPU_builtin(GPU_VIEW_POSITION);
		else
			GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
	}
	
	node_shader_gpu_tex_mapping(mat, node, in, out);

	if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
		GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
	else
		GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
		
	ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
	if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
	    GPU_material_do_color_management(mat))
	{
		GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
	}
	BKE_image_release_ibuf(ima, ibuf, NULL);

	return true;
}
Пример #9
0
// close added texture
PyObject *Texture_close(Texture * self)
{
	// restore texture
	if (self->m_orgSaved)
	{
		self->m_orgSaved = false;
		// restore original texture code
		if (self->m_useMatTexture)
			self->m_matTexture->swapTexture(self->m_orgTex);
		else
		{
			self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D] = self->m_orgTex;
			BKE_image_release_ibuf(self->m_imgTexture, self->m_imgBuf, NULL);
			self->m_imgBuf = NULL;
		}
		// drop actual texture
		if (self->m_actTex != 0)
		{
			glDeleteTextures(1, (GLuint *)&self->m_actTex);
			self->m_actTex = 0;
		}
	}
	Py_RETURN_NONE;
}
Пример #10
0
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock)
{
	ImBuf *ibuf;

	if (sima && sima->image) {
#if 0
		if (sima->image->type == IMA_TYPE_R_RESULT && BIF_show_render_spare())
			return BIF_render_spare_imbuf();
		else
#endif
		ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock);

		if (ibuf) {
			if (ibuf->rect || ibuf->rect_float)
				return ibuf;
			BKE_image_release_ibuf(sima->image, ibuf, *r_lock);
			*r_lock = NULL;
		}
	}
	else
		*r_lock = NULL;

	return NULL;
}
Пример #11
0
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;
}
Пример #12
0
static void draw_plane_marker_image(Scene *scene,
                                    MovieTrackingPlaneTrack *plane_track,
                                    MovieTrackingPlaneMarker *plane_marker)
{
	Image *image = plane_track->image;
	ImBuf *ibuf;
	void *lock;

	if (image == NULL) {
		return;
	}

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

	if (ibuf) {
		unsigned char *display_buffer;
		void *cache_handle;

		if (image->flag & IMA_VIEW_AS_RENDER) {
			display_buffer = IMB_display_buffer_acquire(ibuf,
			                                            &scene->view_settings,
			                                            &scene->display_settings,
			                                            &cache_handle);
		}
		else {
			display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
			                                            &scene->display_settings,
			                                            &cache_handle);
		}

		if (display_buffer) {
			GLuint texid, last_texid;
			float frame_corners[4][2] = {{0.0f, 0.0f},
			                             {1.0f, 0.0f},
			                             {1.0f, 1.0f},
			                             {0.0f, 1.0f}};
			float perspective_matrix[3][3];
			float gl_matrix[4][4];
			bool transparent = false;
			BKE_tracking_homography_between_two_quads(frame_corners,
			                                          plane_marker->corners,
			                                          perspective_matrix);

			homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);

			if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
				transparent = true;
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
			}

			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);

			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);

			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
			             GL_UNSIGNED_BYTE, display_buffer);

			glPushMatrix();
			glMultMatrixf(gl_matrix);

			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
			glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
			glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
			glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
			glEnd();

			glPopMatrix();

			glBindTexture(GL_TEXTURE_2D, last_texid);
			glDisable(GL_TEXTURE_2D);

			if (transparent) {
				glDisable(GL_BLEND);
			}
		}

		IMB_display_buffer_release(cache_handle);
	}

	BKE_image_release_ibuf(image, ibuf, lock);
}
Пример #13
0
void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock)
{
	if (sima && sima->image)
		BKE_image_release_ibuf(sima->image, ibuf, lock);
}
Пример #14
0
/* reads full rect, converts indices */
uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
{
  if (UNLIKELY((xmin > xmax) || (ymin > ymax))) {
    return NULL;
  }

  const rcti rect = {
      .xmin = xmin,
      .xmax = xmax + 1,
      .ymin = ymin,
      .ymax = ymax + 1,
  };

  uint buf_len;
  uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len);

  if (r_buf_len) {
    *r_buf_len = buf_len;
  }

  return buf;
}

/* ************************************************************* */

static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
{
  if (BKE_image_is_stereo(ima)) {
    iuser->flag |= IMA_SHOW_STEREO;

    if ((scene->r.scemode & R_MULTIVIEW) == 0) {
      iuser->multiview_eye = STEREO_LEFT_ID;
    }
    else if (v3d->stereo3d_camera != STEREO_3D_ID) {
      /* show only left or right camera */
      iuser->multiview_eye = v3d->stereo3d_camera;
    }

    BKE_image_multiview_index(ima, iuser);
  }
  else {
    iuser->flag &= ~IMA_SHOW_STEREO;
  }
}

static void view3d_draw_bgpic(Scene *scene,
                              Depsgraph *depsgraph,
                              ARegion *ar,
                              View3D *v3d,
                              const bool do_foreground,
                              const bool do_camera_frame)
{
  RegionView3D *rv3d = ar->regiondata;
  int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0;
  if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) {
    return;
  }
  Camera *cam = v3d->camera->data;

  for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
    if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) {
      continue;
    }

    {
      float image_aspect[2];
      float x1, y1, x2, y2, centx, centy;

      void *lock;

      Image *ima = NULL;

      /* disable individual images */
      if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) {
        continue;
      }

      ImBuf *ibuf = NULL;
      ImBuf *freeibuf = NULL;
      ImBuf *releaseibuf = NULL;
      if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
        ima = bgpic->ima;
        if (ima == NULL) {
          continue;
        }

        ImageUser iuser = bgpic->iuser;
        iuser.scene = scene; /* Needed for render results. */
        BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph));
        if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
          ibuf = NULL; /* frame is out of range, dont show */
        }
        else {
          view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser);
          ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
          releaseibuf = ibuf;
        }

        image_aspect[0] = ima->aspx;
        image_aspect[1] = ima->aspy;
      }
      else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
        /* TODO: skip drawing when out of frame range (as image sequences do above) */
        MovieClip *clip = NULL;

        if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
          if (scene->camera) {
            clip = BKE_object_movieclip_get(scene, scene->camera, true);
          }
        }
        else {
          clip = bgpic->clip;
        }

        if (clip == NULL) {
          continue;
        }

        BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph));
        ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);

        image_aspect[0] = clip->aspx;
        image_aspect[1] = clip->aspy;

        /* working with ibuf from image and clip has got different workflow now.
         * ibuf acquired from clip is referenced by cache system and should
         * be dereferenced after usage. */
        freeibuf = ibuf;
      }
      else {
        /* perhaps when loading future files... */
        BLI_assert(0);
        copy_v2_fl(image_aspect, 1.0f);
      }

      if (ibuf == NULL) {
        continue;
      }

      if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) {
        /* invalid image format */
        if (freeibuf) {
          IMB_freeImBuf(freeibuf);
        }
        if (releaseibuf) {
          BKE_image_release_ibuf(ima, releaseibuf, lock);
        }

        continue;
      }

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

      BLI_assert(rv3d->persp == RV3D_CAMOB);
      {
        if (do_camera_frame) {
          rctf vb;
          ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
          x1 = vb.xmin;
          y1 = vb.ymin;
          x2 = vb.xmax;
          y2 = vb.ymax;
        }
        else {
          x1 = ar->winrct.xmin;
          y1 = ar->winrct.ymin;
          x2 = ar->winrct.xmax;
          y2 = ar->winrct.ymax;
        }

        /* apply offset last - camera offset is different to offset in blender units */
        /* so this has some sane way of working - this matches camera's shift _exactly_ */
        {
          const float max_dim = max_ff(x2 - x1, y2 - y1);
          const float xof_scale = bgpic->offset[0] * max_dim;
          const float yof_scale = bgpic->offset[1] * max_dim;

          x1 += xof_scale;
          y1 += yof_scale;
          x2 += xof_scale;
          y2 += yof_scale;
        }

        centx = (x1 + x2) * 0.5f;
        centy = (y1 + y2) * 0.5f;

        /* aspect correction */
        if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
          /* apply aspect from clip */
          const float w_src = ibuf->x * image_aspect[0];
          const float h_src = ibuf->y * image_aspect[1];

          /* destination aspect is already applied from the camera frame */
          const float w_dst = x1 - x2;
          const float h_dst = y1 - y2;

          const float asp_src = w_src / h_src;
          const float asp_dst = w_dst / h_dst;

          if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
            if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) {
              /* fit X */
              const float div = asp_src / asp_dst;
              x1 = ((x1 - centx) * div) + centx;
              x2 = ((x2 - centx) * div) + centx;
            }
            else {
              /* fit Y */
              const float div = asp_dst / asp_src;
              y1 = ((y1 - centy) * div) + centy;
              y2 = ((y2 - centy) * div) + centy;
            }
          }
        }
      }

      /* complete clip? */
      rctf clip_rect;
      BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
      if (bgpic->rotation) {
        BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
      }

      if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx ||
          clip_rect.ymin > ar->winy) {
        if (freeibuf) {
          IMB_freeImBuf(freeibuf);
        }
        if (releaseibuf) {
          BKE_image_release_ibuf(ima, releaseibuf, lock);
        }

        continue;
      }

      float zoomx = (x2 - x1) / ibuf->x;
      float zoomy = (y2 - y1) / ibuf->y;

      /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */
      if (zoomx < 1.0f || zoomy < 1.0f) {
        float tzoom = min_ff(zoomx, zoomy);
        int mip = 0;

        if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
          IMB_remakemipmap(ibuf, 0);
          ibuf->userflags &= ~IB_MIPMAP_INVALID;
        }
        else if (ibuf->mipmap[0] == NULL) {
          IMB_makemipmap(ibuf, 0);
        }

        while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
          tzoom *= 2.0f;
          zoomx *= 2.0f;
          zoomy *= 2.0f;
          mip++;
        }
        if (mip > 0) {
          ibuf = ibuf->mipmap[mip - 1];
        }
      }

      GPU_depth_test(!do_foreground);
      glDepthMask(GL_FALSE);

      GPU_blend(true);
      GPU_blend_set_func_separate(
          GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);

      GPU_matrix_push_projection();
      GPU_matrix_push();
      ED_region_pixelspace(ar);

      GPU_matrix_translate_2f(centx, centy);
      GPU_matrix_scale_1f(bgpic->scale);
      GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation));

      if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
        zoomx *= -1.0f;
        x1 = x2;
      }
      if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) {
        zoomy *= -1.0f;
        y1 = y2;
      }

      float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
      IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
      immDrawPixelsTex(&state,
                       x1 - centx,
                       y1 - centy,
                       ibuf->x,
                       ibuf->y,
                       GL_RGBA,
                       GL_UNSIGNED_BYTE,
                       GL_LINEAR,
                       ibuf->rect,
                       zoomx,
                       zoomy,
                       col);

      GPU_matrix_pop_projection();
      GPU_matrix_pop();

      GPU_blend(false);

      glDepthMask(GL_TRUE);
      GPU_depth_test(true);

      if (freeibuf) {
        IMB_freeImBuf(freeibuf);
      }
      if (releaseibuf) {
        BKE_image_release_ibuf(ima, releaseibuf, lock);
      }
    }
  }
}
Пример #15
0
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
{
	ShaderPreview *sp = customdata;
	ID *id = sp->id;
	short idtype = GS(id->name);
	
	if (idtype == ID_IM) {
		Image *ima = (Image *)id;
		ImBuf *ibuf = NULL;
		ImageUser iuser = {NULL};

		/* ima->ok is zero when Image cannot load */
		if (ima == NULL || ima->ok == 0)
			return;

		/* setup dummy image user */
		iuser.ok = iuser.framenr = 1;
		iuser.scene = sp->scene;
		
		/* elubie: this needs to be changed: here image is always loaded if not
		 * already there. Very expensive for large images. Need to find a way to 
		 * only get existing ibuf */
		ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
		if (ibuf == NULL || ibuf->rect == NULL) {
			BKE_image_release_ibuf(ima, ibuf, NULL);
			return;
		}
		
		icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);

		*do_update = TRUE;

		BKE_image_release_ibuf(ima, ibuf, NULL);
	}
	else if (idtype == ID_BR) {
		Brush *br = (Brush *)id;

		br->icon_imbuf = get_brush_icon(br);

		memset(sp->pr_rect, 0x888888, sp->sizex * sp->sizey * sizeof(unsigned int));

		if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
			return;

		icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);

		*do_update = TRUE;
	}
	else {
		/* re-use shader job */
		shader_preview_startjob(customdata, stop, do_update);

		/* world is rendered with alpha=0, so it wasn't displayed 
		 * this could be render option for sky to, for later */
		if (idtype == ID_WO) {
			set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
		}
		else if (idtype == ID_MA) {
			Material *ma = (Material *)id;

			if (ma->material_type == MA_TYPE_HALO)
				set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
		}
	}
}
Пример #16
0
void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	/// Image output
	OutputSocket *outputImage = this->getOutputSocket(0);
	bNode *editorNode = this->getbNode();
	Image *image = (Image *)editorNode->id;
	ImageUser *imageuser = (ImageUser *)editorNode->storage;
	int framenumber = context->getFramenumber();
	int numberOfOutputs = this->getNumberOfOutputSockets();
	BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0);

	/* force a load, we assume iuser index will be set OK anyway */
	if (image && image->type == IMA_TYPE_MULTILAYER) {
		bool is_multilayer_ok = false;
		ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL);
		if (image->rr) {
			RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
			if (rl) {
				OutputSocket *socket;
				int index;

				is_multilayer_ok = true;

				for (index = 0; index < numberOfOutputs; index++) {
					NodeOperation *operation = NULL;
					socket = this->getOutputSocket(index);
					if (socket->isConnected() || index == 0) {
						bNodeSocket *bnodeSocket = socket->getbNodeSocket();
						NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
						int passindex = storage->pass_index;
						
						RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
						if (rpass) {
							imageuser->pass = passindex;
							switch (rpass->channels) {
								case 1:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
									break;
								/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
								/* XXX any way to detect actual vector images? */
								case 3:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
									break;
								case 4:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
									break;
								default:
									/* dummy operation is added below */
									break;
							}

							if (index == 0 && operation) {
								addPreviewOperation(graph, context, operation->getOutputSocket());
							}
						}
					}

					/* incase we can't load the layer */
					if (operation == NULL) {
						convertToOperations_invalid_index(graph, index);
					}
				}
			}
		}
		BKE_image_release_ibuf(image, ibuf, NULL);

		/* without this, multilayer that fail to load will crash blender [#32490] */
		if (is_multilayer_ok == false) {
			convertToOperations_invalid(graph, context);
		}
	}
	else {
		if (numberOfOutputs >  0) {
			ImageOperation *operation = new ImageOperation();
			if (outputImage->isConnected()) {
				outputImage->relinkConnections(operation->getOutputSocket());
			}
			operation->setImage(image);
			operation->setImageUser(imageuser);
			operation->setFramenumber(framenumber);
			graph->addOperation(operation);
			addPreviewOperation(graph, context, operation->getOutputSocket());
		}
		
		if (numberOfOutputs > 1) {
			OutputSocket *alphaImage = this->getOutputSocket(1);
			if (alphaImage->isConnected()) {
				ImageAlphaOperation *alphaOperation = new ImageAlphaOperation();
				alphaOperation->setImage(image);
				alphaOperation->setImageUser(imageuser);
				alphaOperation->setFramenumber(framenumber);
				alphaImage->relinkConnections(alphaOperation->getOutputSocket());
				graph->addOperation(alphaOperation);
			}
		}
		if (numberOfOutputs > 2) {
			OutputSocket *depthImage = this->getOutputSocket(2);
			if (depthImage->isConnected()) {
				ImageDepthOperation *depthOperation = new ImageDepthOperation();
				depthOperation->setImage(image);
				depthOperation->setImageUser(imageuser);
				depthOperation->setFramenumber(framenumber);
				depthImage->relinkConnections(depthOperation->getOutputSocket());
				graph->addOperation(depthOperation);
			}
		}
		if (numberOfOutputs > 3) {
			/* happens when unlinking image datablock from multilayer node */
			for (int i = 3; i < numberOfOutputs; i++) {
				OutputSocket *output = this->getOutputSocket(i);
				NodeOperation *operation = NULL;
				switch (output->getDataType()) {
					case COM_DT_VALUE:
					{
						SetValueOperation *valueoperation = new SetValueOperation();
						valueoperation->setValue(0.0f);
						operation = valueoperation;
						break;
					}
					case COM_DT_VECTOR:
					{
						SetVectorOperation *vectoroperation = new SetVectorOperation();
						vectoroperation->setX(0.0f);
						vectoroperation->setY(0.0f);
						vectoroperation->setW(0.0f);
						operation = vectoroperation;
						break;
					}
					case COM_DT_COLOR:
					{
						SetColorOperation *coloroperation = new SetColorOperation();
						coloroperation->setChannel1(0.0f);
						coloroperation->setChannel2(0.0f);
						coloroperation->setChannel3(0.0f);
						coloroperation->setChannel4(0.0f);
						operation = coloroperation;
						break;
					}
				}

				if (operation) {
					output->relinkConnections(operation->getOutputSocket());
					graph->addOperation(operation);
				}
			}
		}
	}
}
Пример #17
0
static void render_endjob(void *rjv)
{
	RenderJob *rj = rjv;

	/* this render may be used again by the sequencer without the active 'Render' where the callbacks
	 * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
	RE_InitRenderCB(rj->re);

	if (rj->main != G.main)
		BKE_main_free(rj->main);

	/* else the frame will not update for the original value */
	if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
		/* possible this fails of loading new file while rendering */
		if (G.main->wm.first) {
			ED_update_for_newframe(G.main, rj->scene, 1);
		}
	}
	
	/* XXX above function sets all tags in nodes */
	ntreeCompositClearTags(rj->scene->nodetree);
	
	/* potentially set by caller */
	rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
	
	if (rj->srl) {
		nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
		WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
	}

	if (rj->sa) {
		render_image_restore_layer(rj);
	}

	/* XXX render stability hack */
	G.is_rendering = false;
	WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);

	/* Partial render result will always update display buffer
	 * for first render layer only. This is nice because you'll
	 * see render progress during rendering, but it ends up in
	 * wrong display buffer shown after rendering.
	 *
	 * The code below will mark display buffer as invalid after
	 * rendering in case multiple layers were rendered, which
	 * ensures display buffer matches render layer after
	 * rendering.
	 *
	 * Perhaps proper way would be to toggle active render
	 * layer in image editor and job, so we always display
	 * layer being currently rendered. But this is not so much
	 * trivial at this moment, especially because of external
	 * engine API, so lets use simple and robust way for now
	 *                                          - sergey -
	 */
	if (rj->scene->r.layers.first != rj->scene->r.layers.last ||
	    rj->image_outdated)
	{
		void *lock;
		Image *ima = rj->image;
		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);

		if (ibuf)
			ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;

		BKE_image_release_ibuf(ima, ibuf, lock);
	}

	/* Finally unlock the user interface (if it was locked). */
	if (rj->interface_locked) {
		Scene *scene;

		/* Interface was locked, so window manager couldn't have been changed
		 * and using one from Global will unlock exactly the same manager as
		 * was locked before running the job.
		 */
		WM_set_locked_interface(G.main->wm.first, false);

		/* We've freed all the derived caches before rendering, which is
		 * effectively the same as if we re-loaded the file.
		 *
		 * So let's not try being smart here and just reset all updated
		 * scene layers and use generic DAG_on_visible_update.
		 */
		for (scene = G.main->scene.first; scene; scene = scene->id.next) {
			scene->lay_updated = 0;
		}

		DAG_on_visible_update(G.main, false);
	}
}
Пример #18
0
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
{
#define MAX_INFO_LEN  128

	PropertyRNA *prop;
	PointerRNA imaptr;
	RNAUpdateCb *cb;
	Image *ima;
	ImageUser *iuser;
	Scene *scene = CTX_data_scene(C);
	uiLayout *row, *split, *col;
	uiBlock *block;
	char str[MAX_INFO_LEN];

	void *lock;

	if (!ptr->data)
		return;

	prop = RNA_struct_find_property(ptr, propname);
	if (!prop) {
		printf("%s: property not found: %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	if (RNA_property_type(prop) != PROP_POINTER) {
		printf("%s: expected pointer property for %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	block = uiLayoutGetBlock(layout);

	imaptr = RNA_property_pointer_get(ptr, prop);
	ima = imaptr.data;
	iuser = userptr->data;

	BKE_image_user_check_frame_calc(iuser, (int)scene->r.cfra, 0);

	cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
	cb->ptr = *ptr;
	cb->prop = prop;
	cb->iuser = iuser;

	uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
	uiLayoutSetContextPointer(layout, "edit_image_user", userptr);

	if (!compact)
		uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);

	if (ima) {
		uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);

		if (ima->source == IMA_SRC_VIEWER) {
			ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
			image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
			BKE_image_release_ibuf(ima, ibuf, lock);

			uiItemL(layout, ima->id.name + 2, ICON_NONE);
			uiItemL(layout, str, ICON_NONE);

			if (ima->type == IMA_TYPE_COMPOSITE) {
				// XXX not working yet
#if 0
				iuser = ntree_get_active_iuser(scene->nodetree);
				if (iuser) {
					uiBlockBeginAlign(block);
					uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
					uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110, 120, 100, 20, 0, 0, 0, 0, 0, "");
					but = uiDefBut(block, BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
					uiButSetFunc(but, image_freecache_cb, ima, NULL);
					
					if (iuser->frames)
						BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
					else strcpy(str, "Frames:");
					uiBlockBeginAlign(block);
					uiDefButI(block, NUM, imagechanged, str,        10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
					uiDefButI(block, NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
				}
#endif
			}
			else if (ima->type == IMA_TYPE_R_RESULT) {
				/* browse layer/passes */
				RenderResult *rr;

				/* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
				rr = BKE_image_acquire_renderresult(scene, ima);
				uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
				BKE_image_release_renderresult(scene, ima);
			}
		}
		else {
			uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);

			if (ima->source != IMA_SRC_GENERATED) {
				row = uiLayoutRow(layout, TRUE);
				if (ima->packedfile)
					uiItemO(row, "", ICON_PACKAGE, "image.unpack");
				else
					uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
				
				row = uiLayoutRow(row, TRUE);
				uiLayoutSetEnabled(row, ima->packedfile == NULL);
				uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
				uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
			}

			// XXX what was this for?
#if 0
			/* check for re-render, only buttons */
			if (imagechanged == B_IMAGECHANGED) {
				if (iuser->flag & IMA_ANIM_REFRESHED) {
					iuser->flag &= ~IMA_ANIM_REFRESHED;
					WM_event_add_notifier(C, NC_IMAGE, ima);
				}
			}
#endif

			/* multilayer? */
			if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
				uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
			}
			else if (ima->source != IMA_SRC_GENERATED) {
				if (compact == 0) {
					ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
					image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
					BKE_image_release_ibuf(ima, ibuf, lock);
					uiItemL(layout, str, ICON_NONE);
				}
			}

			col = uiLayoutColumn(layout, FALSE);
			uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
			uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);

			if (ima->source != IMA_SRC_GENERATED) {
				if (compact == 0) { /* background image view doesnt need these */
					ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
					int has_alpha = TRUE;

					if (ibuf) {
						int imtype = BKE_ftype_to_imtype(ibuf->ftype);
						char valid_channels = BKE_imtype_valid_channels(imtype);

						has_alpha = valid_channels & IMA_CHAN_FLAG_ALPHA;

						BKE_image_release_ibuf(ima, ibuf, NULL);
					}

					if (has_alpha) {
						col = uiLayoutColumn(layout, FALSE);
						uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
						uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
					}

					uiItemS(layout);

					split = uiLayoutSplit(layout, 0.0f, FALSE);

					col = uiLayoutColumn(split, FALSE);
					/* XXX Why only display fields_per_frame only for video image types?
					 *     And why allow fields for non-video image types at all??? */
					if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
						uiLayout *subsplit = uiLayoutSplit(col, 0.0f, FALSE);
						uiLayout *subcol = uiLayoutColumn(subsplit, FALSE);
						uiItemR(subcol, &imaptr, "use_fields", 0, NULL, ICON_NONE);
						subcol = uiLayoutColumn(subsplit, FALSE);
						uiLayoutSetActive(subcol, RNA_boolean_get(&imaptr, "use_fields"));
						uiItemR(subcol, userptr, "fields_per_frame", 0, IFACE_("Fields"), ICON_NONE);
					}
					else
						uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
					row = uiLayoutRow(col, FALSE);
					uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
					uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
				}
			}

			if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
				uiItemS(layout);

				split = uiLayoutSplit(layout, 0.0f, FALSE);

				col = uiLayoutColumn(split, FALSE);

				BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
				uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
				uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
				uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);

				col = uiLayoutColumn(split, FALSE);
				uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
				uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
				uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
			}
			else if (ima->source == IMA_SRC_GENERATED) {
				split = uiLayoutSplit(layout, 0.0f, FALSE);

				col = uiLayoutColumn(split, TRUE);
				uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
				uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
				
				uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);

				uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
			}

		}

		uiBlockSetNFunc(block, NULL, NULL, NULL);
	}

	MEM_freeN(cb);

#undef MAX_INFO_LEN
}
Пример #19
0
/* used for both 3d view and image window */
void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
	Scene *scene = CTX_data_scene(C);
	Paint *paint = BKE_paint_get_active_from_context(C);
	Palette *palette = BKE_paint_palette(paint);
	PaletteColor *color;
	Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
	unsigned int col;
	const unsigned char *cp;

	CLAMP(x, 0, ar->winx);
	CLAMP(y, 0, ar->winy);
	
	if (use_palette) {
		if (!palette) {
			palette = BKE_palette_add(CTX_data_main(C), "Palette");
			BKE_paint_palette_set(paint, palette);
		}

		color = BKE_palette_color_add(palette);
	}


	if (CTX_wm_view3d(C) && texpaint_proj) {
		/* first try getting a colour directly from the mesh faces if possible */
		Object *ob = OBACT;
		bool sample_success = false;

		if (ob) {
			DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);

			ViewContext vc;
			const int mval[2] = {x, y};
			unsigned int faceindex;
			unsigned int totface = dm->getNumTessFaces(dm);
			MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);

			DM_update_materials(dm, ob);

			if (dm_mtface) {
				view3d_set_viewcontext(C, &vc);

				view3d_operator_needs_opengl(C);

				if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
					Image *image = imapaint_face_image(dm, faceindex);

					ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
					if (ibuf && ibuf->rect) {
						float uv[2];
						float u, v;
						imapaint_pick_uv(scene, ob, faceindex, mval, uv);
						sample_success = true;

						u = fmodf(uv[0], 1.0f);
						v = fmodf(uv[1], 1.0f);

						if (u < 0.0f) u += 1.0f;
						if (v < 0.0f) v += 1.0f;

						u = u * ibuf->x - 0.5f;
						v = v * ibuf->y - 0.5f;

						if (ibuf->rect_float) {
							float rgba_f[4];
							bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
							straight_to_premul_v4(rgba_f);
							if (use_palette) {
								linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
							}
							else {
								linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
								BKE_brush_color_set(scene, br, rgba_f);
							}
						}
						else {
							unsigned char rgba[4];
							bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
							if (use_palette) {
								rgb_uchar_to_float(color->rgb, rgba);
							}
							else {
								float rgba_f[3];
								rgb_uchar_to_float(rgba_f, rgba);
								BKE_brush_color_set(scene, br, rgba_f);
							}
						}
					}

					BKE_image_release_ibuf(image, ibuf, NULL);
				}
			}
			dm->release(dm);
		}

		if (!sample_success) {
			glReadBuffer(GL_FRONT);
			glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
			glReadBuffer(GL_BACK);
		}
		else
			return;
	}
	else {
		glReadBuffer(GL_FRONT);
		glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
		glReadBuffer(GL_BACK);
	}
	cp = (unsigned char *)&col;
	
	if (use_palette) {
		rgb_uchar_to_float(color->rgb, cp);
	}
	else {
		float rgba_f[3];
		rgb_uchar_to_float(rgba_f, cp);
		BKE_brush_color_set(scene, br, rgba_f);
	}
}
Пример #20
0
static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
    SpaceNode *snode = CTX_wm_space_node(C);
    ARegion *ar = CTX_wm_region(C);
    ImageSampleInfo *info = op->customdata;
    void *lock;
    Image *ima;
    ImBuf *ibuf;
    float fx, fy, bufx, bufy;

    ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
    ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
    if (!ibuf) {
        info->draw = 0;
        return;
    }

    if (!ibuf->rect) {
        IMB_rect_from_float(ibuf);
    }

    /* map the mouse coords to the backdrop image space */
    bufx = ibuf->x * snode->zoom;
    bufy = ibuf->y * snode->zoom;
    fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
    fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);

    if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
        float *fp;
        unsigned char *cp;
        int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);

        CLAMP(x, 0, ibuf->x - 1);
        CLAMP(y, 0, ibuf->y - 1);

        info->x = x;
        info->y = y;
        info->draw = 1;
        info->channels = ibuf->channels;

        info->zp = NULL;
        info->zfp = NULL;

        if (ibuf->rect) {
            cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);

            info->col[0] = cp[0];
            info->col[1] = cp[1];
            info->col[2] = cp[2];
            info->col[3] = cp[3];

            info->colf[0] = (float)cp[0] / 255.0f;
            info->colf[1] = (float)cp[1] / 255.0f;
            info->colf[2] = (float)cp[2] / 255.0f;
            info->colf[3] = (float)cp[3] / 255.0f;

            copy_v4_v4(info->linearcol, info->colf);
            IMB_colormanagement_colorspace_to_scene_linear_v4(info->linearcol, false, ibuf->rect_colorspace);

            info->color_manage = TRUE;
        }
        if (ibuf->rect_float) {
            fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));

            info->colf[0] = fp[0];
            info->colf[1] = fp[1];
            info->colf[2] = fp[2];
            info->colf[3] = fp[3];

            info->color_manage = TRUE;
        }

        if (ibuf->zbuf) {
            info->z = ibuf->zbuf[y * ibuf->x + x];
            info->zp = &info->z;
        }
        if (ibuf->zbuf_float) {
            info->zf = ibuf->zbuf_float[y * ibuf->x + x];
            info->zfp = &info->zf;
        }

        ED_node_sample_set(info->colf);
    }
    else {
        info->draw = 0;
        ED_node_sample_set(NULL);
    }

    BKE_image_release_ibuf(ima, ibuf, lock);

    ED_area_tag_redraw(CTX_wm_area(C));
}
Пример #21
0
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
{
	ShaderPreview *sp = customdata;

	if (sp->pr_method == PR_ICON_DEFERRED) {
		PreviewImage *prv = sp->owner;
		ImBuf *thumb;
		char *deferred_data = PRV_DEFERRED_DATA(prv);
		int source =  deferred_data[0];
		char *path = &deferred_data[1];

//		printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);

		thumb = IMB_thumb_manage(path, THB_LARGE, source);

		if (thumb) {
			/* PreviewImage assumes premultiplied alhpa... */
			IMB_premultiply_alpha(thumb);

			icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
			IMB_freeImBuf(thumb);
		}
	}
	else {
		ID *id = sp->id;
		short idtype = GS(id->name);

		if (idtype == ID_IM) {
			Image *ima = (Image *)id;
			ImBuf *ibuf = NULL;
			ImageUser iuser = {NULL};

			/* ima->ok is zero when Image cannot load */
			if (ima == NULL || ima->ok == 0)
				return;

			/* setup dummy image user */
			iuser.ok = iuser.framenr = 1;
			iuser.scene = sp->scene;

			/* elubie: this needs to be changed: here image is always loaded if not
			 * already there. Very expensive for large images. Need to find a way to
			 * only get existing ibuf */
			ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
			if (ibuf == NULL || ibuf->rect == NULL) {
				BKE_image_release_ibuf(ima, ibuf, NULL);
				return;
			}

			icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);

			*do_update = true;

			BKE_image_release_ibuf(ima, ibuf, NULL);
		}
		else if (idtype == ID_BR) {
			Brush *br = (Brush *)id;

			br->icon_imbuf = get_brush_icon(br);

			memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));

			if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
				return;

			icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);

			*do_update = true;
		}
		else {
			/* re-use shader job */
			shader_preview_startjob(customdata, stop, do_update);

			/* world is rendered with alpha=0, so it wasn't displayed
			 * this could be render option for sky to, for later */
			if (idtype == ID_WO) {
				set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
			}
			else if (idtype == ID_MA) {
				Material *ma = (Material *)id;

				if (ma->material_type == MA_TYPE_HALO)
					set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
			}
		}
	}
}
Пример #22
0
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
{
	PropertyRNA *prop;
	PointerRNA imaptr;
	RNAUpdateCb *cb;
	Image *ima;
	ImageUser *iuser;
	ImBuf *ibuf;
	Scene *scene = CTX_data_scene(C);
	uiLayout *row, *split, *col;
	uiBlock *block;
	uiBut *but;
	char str[128];
	void *lock;

	if (!ptr->data)
		return;

	prop = RNA_struct_find_property(ptr, propname);
	if (!prop) {
		printf("%s: property not found: %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	if (RNA_property_type(prop) != PROP_POINTER) {
		printf("%s: expected pointer property for %s.%s\n",
		       __func__, RNA_struct_identifier(ptr->type), propname);
		return;
	}

	block = uiLayoutGetBlock(layout);

	imaptr = RNA_property_pointer_get(ptr, prop);
	ima = imaptr.data;
	iuser = userptr->data;

	cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
	cb->ptr = *ptr;
	cb->prop = prop;
	cb->iuser = iuser;

	uiLayoutSetContextPointer(layout, "edit_image", &imaptr);

	if (!compact)
		uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);

	if (ima) {
		uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);

		if (ima->source == IMA_SRC_VIEWER) {
			ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
			image_info(scene, iuser, ima, ibuf, str);
			BKE_image_release_ibuf(ima, lock);

			uiItemL(layout, ima->id.name + 2, ICON_NONE);
			uiItemL(layout, str, ICON_NONE);

			if (ima->type == IMA_TYPE_COMPOSITE) {
				// XXX not working yet
#if 0
				iuser = ntree_get_active_iuser(scene->nodetree);
				if (iuser) {
					uiBlockBeginAlign(block);
					uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
					uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110, 120, 100, 20, 0, 0, 0, 0, 0, "");
					but = uiDefBut(block, BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
					uiButSetFunc(but, image_freecache_cb, ima, NULL);
					
					if (iuser->frames)
						BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
					else strcpy(str, "Frames:");
					uiBlockBeginAlign(block);
					uiDefButI(block, NUM, imagechanged, str,        10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
					uiDefButI(block, NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
				}
#endif
			}
			else if (ima->type == IMA_TYPE_R_RESULT) {
				/* browse layer/passes */
				Render *re = RE_GetRender(scene->id.name);
				RenderResult *rr = RE_AcquireResultRead(re);
				uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
				RE_ReleaseResult(re);
			}
		}
		else {
			uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);

			if (ima->source != IMA_SRC_GENERATED) {
				row = uiLayoutRow(layout, 1);
				if (ima->packedfile)
					uiItemO(row, "", ICON_PACKAGE, "image.unpack");
				else
					uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
				
				row = uiLayoutRow(row, 0);
				uiLayoutSetEnabled(row, ima->packedfile == NULL);
				uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
				uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
			}

			// XXX what was this for?
#if 0
			/* check for re-render, only buttons */
			if (imagechanged == B_IMAGECHANGED) {
				if (iuser->flag & IMA_ANIM_REFRESHED) {
					iuser->flag &= ~IMA_ANIM_REFRESHED;
					WM_event_add_notifier(C, NC_IMAGE, ima);
				}
			}
#endif

			/* multilayer? */
			if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
				uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
			}
			else if (ima->source != IMA_SRC_GENERATED) {
				if (compact == 0) {
					ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
					image_info(scene, iuser, ima, ibuf, str);
					BKE_image_release_ibuf(ima, lock);
					uiItemL(layout, str, ICON_NONE);
				}
			}
			
			if (ima->source != IMA_SRC_GENERATED) {
				if (compact == 0) { /* background image view doesnt need these */
					uiItemS(layout);

					split = uiLayoutSplit(layout, 0, 0);

					col = uiLayoutColumn(split, 0);
					uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
					row = uiLayoutRow(col, 0);
					uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
					uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
					
					row = uiLayoutRow(layout, 0);
					uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
					uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE);
				}
			}

			if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
				uiItemS(layout);
				
				split = uiLayoutSplit(layout, 0, 0);

				col = uiLayoutColumn(split, 0);
				 
				BLI_snprintf(str, sizeof(str), "(%d) Frames", iuser->framenr);
				uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
				if (ima->anim) {
					block = uiLayoutGetBlock(col);
					but = uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X * 2, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence");
					uiButSetFunc(but, set_frames_cb, ima, iuser);
				}

				uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE);
				uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);

				col = uiLayoutColumn(split, 0);
				row = uiLayoutRow(col, 0);
				uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
				uiItemR(row, userptr, "fields_per_frame", 0, "Fields", ICON_NONE);
				uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
				uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
			}
			else if (ima->source == IMA_SRC_GENERATED) {
				split = uiLayoutSplit(layout, 0, 0);

				col = uiLayoutColumn(split, 1);
				uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
				uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
				uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);

				uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
			}

		}

		uiBlockSetNFunc(block, NULL, NULL, NULL);
	}

	MEM_freeN(cb);
}
Пример #23
0
static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
{
	/* image assigned to output */
	/* stack order input sockets: image image */
	
	if(in[0]->data==NULL || in[1]->data==NULL)
		return;
	
	if(node->id && (node->flag & NODE_DO_OUTPUT)) {	/* only one works on out */
		Image *ima= (Image *)node->id;
		RenderData *rd= data;
		ImBuf *ibuf;
		CompBuf *cbuf, *buf1, *buf2, *mask;
		int x, y;
		float offset;
		void *lock;
		
		buf1= typecheck_compbuf(in[0]->data, CB_RGBA);
		buf2= typecheck_compbuf(in[1]->data, CB_RGBA);
		
		BKE_image_user_calc_frame(node->storage, rd->cfra, 0);
		
		/* always returns for viewer image, but we check nevertheless */
		ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock);
		if(ibuf==NULL) {
			printf("node_composit_exec_viewer error\n");
			BKE_image_release_ibuf(ima, lock);
			return;
		}
		
		/* free all in ibuf */
		imb_freerectImBuf(ibuf);
		imb_freerectfloatImBuf(ibuf);
		IMB_freezbuffloatImBuf(ibuf);
		
		/* make ibuf, and connect to ima */
		ibuf->x= buf1->x;
		ibuf->y= buf1->y;
		imb_addrectfloatImBuf(ibuf);
		
		ima->ok= IMA_OK_LOADED;

		/* output buf */
		cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0);	/* no alloc*/
		cbuf->rect= ibuf->rect_float;
		
		/* mask buf */
		mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1);
		
		
		/* Check which offset mode is selected and limit offset if needed */
		if(node->custom2 == 0) {
			offset = buf1->x / 100.0f * node->custom1;
			CLAMP(offset, 0, buf1->x);
		}
		else {
			offset = buf1->y / 100.0f * node->custom1;
			CLAMP(offset, 0, buf1->y);
		}
		
		if(node->custom2 == 0) {
			for(y=0; y<buf1->y; y++) {
				float *fac= mask->rect + y*buf1->x;
				for(x=offset; x>0; x--, fac++)
					*fac= 1.0f;
			}
		}
		else {
			for(y=0; y<offset; y++) {
				float *fac= mask->rect + y*buf1->x;
				for(x=buf1->x; x>0; x--, fac++)
					*fac= 1.0f;
			}
		}
		
		composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL);
		
		BKE_image_release_ibuf(ima, lock);
		
		generate_preview(data, node, cbuf);
		free_compbuf(cbuf);
		free_compbuf(mask);
		
		if(in[0]->data != buf1) 
			free_compbuf(buf1);
		if(in[1]->data != buf2) 
			free_compbuf(buf2);
	}
}
Пример #24
0
void BaseImageOperation::deinitExecution()
{
	this->m_imageFloatBuffer = NULL;
	this->m_imageByteBuffer = NULL;
	BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL);
}
Пример #25
0
static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData,
                             MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
{
	DerivedMesh *dm = bkr->lores_dm;
	const int lvl = bkr->lvl;
	const int tot_face = dm->getNumTessFaces(dm);

	if (tot_face > 0) {
		MultiresBakeThread *handles;
		MultiresBakeQueue queue;

		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
		MVert *mvert = dm->getVertArray(dm);
		MFace *mface = dm->getTessFaceArray(dm);
		MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
		float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
		float *pvtangent = NULL;

		ListBase threads;
		int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();

		void *bake_data = NULL;

		if (require_tangent) {
			if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
				DM_add_tangent_layer(dm);

			pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
		}

		/* all threads shares the same custom bake data */
		if (initBakeData)
			bake_data = initBakeData(bkr, ima);

		if (tot_thread > 1)
			BLI_init_threads(&threads, do_multires_bake_thread, tot_thread);

		handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");

		/* faces queue */
		queue.cur_face = 0;
		queue.tot_face = tot_face;
		BLI_spin_init(&queue.spin);

		/* fill in threads handles */
		for (i = 0; i < tot_thread; i++) {
			MultiresBakeThread *handle = &handles[i];

			handle->bkr = bkr;
			handle->image = ima;
			handle->queue = &queue;

			handle->data.mface = mface;
			handle->data.mvert = mvert;
			handle->data.mtface = mtface;
			handle->data.pvtangent = pvtangent;
			handle->data.precomputed_normals = precomputed_normals;  /* don't strictly need this */
			handle->data.w = ibuf->x;
			handle->data.h = ibuf->y;
			handle->data.lores_dm = dm;
			handle->data.hires_dm = bkr->hires_dm;
			handle->data.lvl = lvl;
			handle->data.pass_data = passKnownData;
			handle->data.bake_data = bake_data;
			handle->data.ibuf = ibuf;

			init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel);

			if (tot_thread > 1)
				BLI_insert_thread(&threads, handle);
		}

		/* run threads */
		if (tot_thread > 1)
			BLI_end_threads(&threads);
		else
			do_multires_bake_thread(&handles[0]);

		BLI_spin_end(&queue.spin);

		/* finalize baking */
		if (applyBakeData)
			applyBakeData(bake_data);

		if (freeBakeData)
			freeBakeData(bake_data);

		BKE_image_release_ibuf(ima, ibuf, NULL);
	}
}
Пример #26
0
static int get_next_bake_face(BakeShade *bs)
{
	ObjectRen *obr;
	VlakRen *vlr;
	MTFace *tface;
	static int v = 0, vdone = false;
	static ObjectInstanceRen *obi = NULL;

	if (bs == NULL) {
		vlr = NULL;
		v = vdone = false;
		obi = R.instancetable.first;
		return 0;
	}
	
	BLI_lock_thread(LOCK_CUSTOM1);

	for (; obi; obi = obi->next, v = 0) {
		obr = obi->obr;

		for (; v < obr->totvlak; v++) {
			vlr = RE_findOrAddVlak(obr, v);

			if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
				if (R.r.bake_flag & R_BAKE_VCOL) {
					/* Gather face data for vertex color bake */
					Mesh *me;
					int *origindex, vcollayer;
					CustomDataLayer *cdl;

					if (obr->ob->type != OB_MESH)
						continue;
					me = obr->ob->data;

					origindex = RE_vlakren_get_origindex(obr, vlr, 0);
					if (origindex == NULL)
						continue;
					if (*origindex >= me->totpoly) {
						/* Small hack for Array modifier, which gives false
						 * original indices - z0r */
						continue;
					}
#if 0
					/* Only shade selected faces. */
					if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
						continue;
#endif

					vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
					if (vcollayer == -1)
						continue;

					cdl = &me->ldata.layers[vcollayer];
					bs->mpoly = me->mpoly + *origindex;
					bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart;
					bs->mloop = me->mloop + bs->mpoly->loopstart;

					/* Tag mesh for reevaluation. */
					me->id.flag |= LIB_DOIT;
				}
				else {
					Image *ima = NULL;
					ImBuf *ibuf = NULL;
					const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
					const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
					const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
					const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
					const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
					const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};

					tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);

					if (!tface || !tface->tpage)
						continue;

					ima = tface->tpage;
					ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);

					if (ibuf == NULL)
						continue;

					if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}

					if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) {
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}
					
					if (ima->flag & IMA_USED_FOR_RENDER) {
						ima->id.flag &= ~LIB_DOIT;
						BKE_image_release_ibuf(ima, ibuf, NULL);
						continue;
					}
					
					/* find the image for the first time? */
					if (ima->id.flag & LIB_DOIT) {
						ima->id.flag &= ~LIB_DOIT;
						
						/* we either fill in float or char, this ensures things go fine */
						if (ibuf->rect_float)
							imb_freerectImBuf(ibuf);
						/* clear image */
						if (R.r.bake_flag & R_BAKE_CLEAR) {
							if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
							else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE))
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
							else
								IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
						}
						/* might be read by UI to set active image for display */
						R.bakebuf = ima;
					}

					/* Tag image for redraw. */
					ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
					BKE_image_release_ibuf(ima, ibuf, NULL);
				}

				bs->obi = obi;
				bs->vlr = vlr;
				bs->vdone++;  /* only for error message if nothing was rendered */
				v++;
				BLI_unlock_thread(LOCK_CUSTOM1);
				return 1;
			}
		}
	}
	
	BLI_unlock_thread(LOCK_CUSTOM1);
	return 0;
}
Пример #27
0
static void render_endjob(void *rjv)
{
	RenderJob *rj = rjv;

	/* this render may be used again by the sequencer without the active 'Render' where the callbacks
	 * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
	RE_InitRenderCB(rj->re);

	if (rj->main != G.main)
		free_main(rj->main);

	/* else the frame will not update for the original value */
	if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
		/* possible this fails of loading new file while rendering */
		if (G.main->wm.first) {
			ED_update_for_newframe(G.main, rj->scene, 1);
		}
	}
	
	/* XXX above function sets all tags in nodes */
	ntreeCompositClearTags(rj->scene->nodetree);
	
	/* potentially set by caller */
	rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
	
	if (rj->srl) {
		nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
		WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
	}

	/* XXX render stability hack */
	G.is_rendering = FALSE;
	WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);

	/* Partial render result will always update display buffer
	 * for first render layer only. This is nice because you'll
	 * see render progress during rendering, but it ends up in
	 * wrong display buffer shown after rendering.
	 *
	 * The code below will mark display buffer as invalid after
	 * rendering in case multiple layers were rendered, which
	 * ensures display buffer matches render layer after
	 * rendering.
	 *
	 * Perhaps proper way would be to toggle active render
	 * layer in image editor and job, so we always display
	 * layer being currently rendered. But this is not so much
	 * trivial at this moment, especially because of external
	 * engine API, so lets use simple and robust way for now
	 *                                          - sergey -
	 */
	if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
		void *lock;
		Image *ima = rj->image;
		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);

		if (ibuf)
			ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;

		BKE_image_release_ibuf(ima, ibuf, lock);
	}
}
Пример #28
0
/* already have tested for tface and ima and zspan */
static void shade_tface(BakeShade *bs)
{
	VlakRen *vlr = bs->vlr;
	ObjectInstanceRen *obi = bs->obi;
	ObjectRen *obr = obi->obr;
	MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
	Image *ima = tface->tpage;
	float vec[4][2];
	int a, i1, i2, i3;
	
	/* check valid zspan */
	if (ima != bs->ima) {
		BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);

		bs->ima = ima;
		bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);
		/* note, these calls only free/fill contents of zspan struct, not zspan itself */
		zbuf_free_span(bs->zspan);
		zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
	}

	bs->rectx = bs->ibuf->x;
	bs->recty = bs->ibuf->y;
	bs->rect = bs->ibuf->rect;
	bs->rect_colorspace = bs->ibuf->rect_colorspace;
	bs->rect_float = bs->ibuf->rect_float;
	bs->vcol = NULL;
	bs->quad = 0;
	bs->rect_mask = NULL;
	bs->displacement_buffer = NULL;

	if (bs->use_mask || bs->use_displacement_buffer) {
		BakeImBufuserData *userdata = bs->ibuf->userdata;
		if (userdata == NULL) {
			BLI_lock_thread(LOCK_CUSTOM1);
			userdata = bs->ibuf->userdata;
			if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */
				userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData");

			if (bs->use_mask) {
				if (userdata->mask_buffer == NULL) {
					userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask");
				}
			}

			if (bs->use_displacement_buffer) {
				if (userdata->displacement_buffer == NULL) {
					userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
				}
			}

			bs->ibuf->userdata = userdata;

			BLI_unlock_thread(LOCK_CUSTOM1);
		}

		bs->rect_mask = userdata->mask_buffer;
		bs->displacement_buffer = userdata->displacement_buffer;
	}
	
	/* get pixel level vertex coordinates */
	for (a = 0; a < 4; a++) {
		/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
		 * where a pixel gets in between 2 faces or the middle of a quad,
		 * camera aligned quads also have this problem but they are less common.
		 * Add a small offset to the UVs, fixes bug #18685 - Campbell */
		vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f);
		vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f);
	}

	/* UV indices have to be corrected for possible quad->tria splits */
	i1 = 0; i2 = 1; i3 = 2;
	vlr_set_uv_indices(vlr, &i1, &i2, &i3);
	bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
	zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
	
	if (vlr->v4) {
		bs->quad = 1;
		bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
		zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
	}
}
Пример #29
0
/* if all is good tag image and return true */
static bool bake_object_check(Object *ob, ReportList *reports)
{
	Image *image;
	void *lock;
	int i;

	if (ob->type != OB_MESH) {
		BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
		return false;
	}
	else {
		Mesh *me = (Mesh *)ob->data;

		if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
			BKE_reportf(reports, RPT_ERROR,
			            "No active UV layer found in the object \"%s\"", ob->id.name + 2);
			return false;
		}
	}

	for (i = 0; i < ob->totcol; i++) {
		bNodeTree *ntree = NULL;
		bNode *node = NULL;
		ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);

		if (image) {
			ImBuf *ibuf;

			if (node) {
				if (BKE_node_is_connected_to_output(ntree, node)) {
					/* we don't return false since this may be a false positive
					 * this can't be RPT_ERROR though, otherwise it prevents
					 * multiple highpoly objects to be baked at once */
					BKE_reportf(reports, RPT_INFO,
					            "Circular dependency for image \"%s\" from object \"%s\"",
					            image->id.name + 2, ob->id.name + 2);
				}
			}

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

			if (ibuf) {
				BKE_image_release_ibuf(image, ibuf, lock);
			}
			else {
				BKE_reportf(reports, RPT_ERROR,
				            "Uninitialized image \"%s\" from object \"%s\"",
				            image->id.name + 2, ob->id.name + 2);

				BKE_image_release_ibuf(image, ibuf, lock);
				return false;
			}
		}
		else {
			if (ob->mat[i]) {
				BKE_reportf(reports, RPT_ERROR,
				            "No active image found in material \"%s\" (%d) for object \"%s\"",
				            ob->mat[i]->id.name + 2, i, ob->id.name + 2);
			}
			else if (((Mesh *) ob->data)->mat[i]) {
				BKE_reportf(reports, RPT_ERROR,
				            "No active image found in material \"%s\" (%d) for object \"%s\"",
				            ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2);
			}
			else {
				BKE_reportf(reports, RPT_ERROR,
				            "No active image found in material (%d) for object \"%s\"",
				            i, ob->id.name + 2);
			}
			return false;
		}

		image->id.tag |= LIB_TAG_DOIT;
	}
	return true;
}
Пример #30
0
/* returns 0 if nothing was handled */
int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
{
	BakeShade *handles;
	ListBase threads;
	Image *ima;
	int a, vdone = false, result = BAKE_RESULT_OK;
	bool use_mask = false;
	bool use_displacement_buffer = false;
	
	re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
	
	/* initialize render global */
	R = *re;
	R.bakebuf = NULL;

	/* initialize static vars */
	get_next_bake_face(NULL);
	
	/* do we need a mask? */
	if (re->r.bake_filter)
		use_mask = true;

	/* do we need buffer to store displacements  */
	if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
		if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) ||
		    (type == RE_BAKE_DERIVATIVE))
		{
			use_displacement_buffer = true;
			use_mask = true;
		}
	}

	/* baker uses this flag to detect if image was initialized */
	if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
		for (ima = G.main->image.first; ima; ima = ima->id.next) {
			ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);
			ima->id.flag |= LIB_DOIT;
			ima->flag &= ~IMA_USED_FOR_RENDER;
			if (ibuf) {
				ibuf->userdata = NULL; /* use for masking if needed */
			}
			BKE_image_release_ibuf(ima, ibuf, NULL);
		}
	}

	if (R.r.bake_flag & R_BAKE_VCOL) {
		/* untag all meshes */
		tag_main_lb(&G.main->mesh, false);
	}

	BLI_init_threads(&threads, do_bake_thread, re->r.threads);

	handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade");

	/* get the threads running */
	for (a = 0; a < re->r.threads; a++) {
		/* set defaults in handles */
		handles[a].ssamp.shi[0].lay = re->lay;

		if (type == RE_BAKE_SHADOW) {
			handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW;
		}
		else {
			handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED;
		}
		handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC);
		handles[a].ssamp.shi[0].thread = a;
		handles[a].ssamp.tot = 1;

		handles[a].type = type;
		handles[a].actob = actob;
		if (R.r.bake_flag & R_BAKE_VCOL)
			handles[a].zspan = NULL;
		else
			handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
		
		handles[a].use_mask = use_mask;
		handles[a].use_displacement_buffer = use_displacement_buffer;

		handles[a].do_update = do_update; /* use to tell the view to update */
		
		handles[a].displacement_min = FLT_MAX;
		handles[a].displacement_max = -FLT_MAX;

		BLI_insert_thread(&threads, &handles[a]);
	}
	
	/* wait for everything to be done */
	a = 0;
	while (a != re->r.threads) {
		PIL_sleep_ms(50);

		/* calculate progress */
		for (vdone = false, a = 0; a < re->r.threads; a++)
			vdone += handles[a].vdone;
		if (progress)
			*progress = (float)(vdone / (float)re->totvlak);

		for (a = 0; a < re->r.threads; a++) {
			if (handles[a].ready == false) {
				break;
			}
		}
	}

	/* filter and refresh images */
	if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
		float displacement_min = FLT_MAX, displacement_max = -FLT_MAX;

		if (use_displacement_buffer) {
			for (a = 0; a < re->r.threads; a++) {
				displacement_min = min_ff(displacement_min, handles[a].displacement_min);
				displacement_max = max_ff(displacement_max, handles[a].displacement_max);
			}
		}

		for (ima = G.main->image.first; ima; ima = ima->id.next) {
			if ((ima->id.flag & LIB_DOIT) == 0) {
				ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA);
				BakeImBufuserData *userdata;

				if (ima->flag & IMA_USED_FOR_RENDER)
					result = BAKE_RESULT_FEEDBACK_LOOP;

				if (!ibuf)
					continue;

				userdata = (BakeImBufuserData *)ibuf->userdata;
				if (userdata) {
					if (use_displacement_buffer) {
						if (type == RE_BAKE_DERIVATIVE) {
							float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f;
							RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
							                        displacement_min, displacement_max, user_scale);
						}
						else {
							RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
							                                    displacement_min, displacement_max);
						}
					}

					RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
				}

				ibuf->userflags |= IB_BITMAPDIRTY;
				BKE_image_release_ibuf(ima, ibuf, NULL);
			}
		}

		/* calculate return value */
		for (a = 0; a < re->r.threads; a++) {
			zbuf_free_span(handles[a].zspan);
			MEM_freeN(handles[a].zspan);
		}
	}

	MEM_freeN(handles);
	
	BLI_end_threads(&threads);

	if (vdone == 0) {
		result = BAKE_RESULT_NO_OBJECTS;
	}

	return result;
}