Blender  V3.3
blender/image.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "MEM_guardedalloc.h"
5 
6 #include "blender/image.h"
7 #include "blender/session.h"
8 #include "blender/util.h"
9 
10 #include "util/half.h"
11 
13 
14 /* Packed Images */
15 
17  const int frame,
18  const int tile_number,
19  const bool is_preview_render)
20  : b_image(b_image),
21  frame(frame),
22  tile_number(tile_number),
23  /* Don't free cache for preview render to avoid race condition from T93560, to be fixed
24  * properly later as we are close to release. */
25  free_cache(!is_preview_render && !b_image.has_data())
26 {
27 }
28 
30 {
31  if (b_image.source() != BL::Image::source_TILED) {
32  /* Image sequence might have different dimensions, and hence needs to be handled in a special
33  * manner.
34  * NOTE: Currently the sequences are not handled by this image loader. */
35  assert(b_image.source() != BL::Image::source_SEQUENCE);
36 
37  metadata.width = b_image.size()[0];
38  metadata.height = b_image.size()[1];
39  metadata.channels = b_image.channels();
40  }
41  else {
42  /* Different UDIM tiles might have different resolutions, so get resolution from the actual
43  * tile. */
44  BL::UDIMTile b_udim_tile = b_image.tiles.get(tile_number);
45  if (b_udim_tile) {
46  metadata.width = b_udim_tile.size()[0];
47  metadata.height = b_udim_tile.size()[1];
48  metadata.channels = b_udim_tile.channels();
49  }
50  else {
51  metadata.width = 0;
52  metadata.height = 0;
53  metadata.channels = 0;
54  }
55  }
56 
57  metadata.depth = 1;
58 
59  if (b_image.is_float()) {
60  if (metadata.channels == 1) {
61  metadata.type = IMAGE_DATA_TYPE_FLOAT;
62  }
63  else if (metadata.channels == 4) {
64  metadata.type = IMAGE_DATA_TYPE_FLOAT4;
65  }
66  else {
67  return false;
68  }
69 
70  /* Float images are already converted on the Blender side,
71  * no need to do anything in Cycles. */
72  metadata.colorspace = u_colorspace_raw;
73  }
74  else {
75  /* In some cases (e.g. T94135), the colorspace setting in Blender gets updated as part of the
76  * metadata queries in this function, so update the colorspace setting here. */
77  PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
78  metadata.colorspace = get_enum_identifier(colorspace_ptr, "name");
79 
80  if (metadata.channels == 1) {
81  metadata.type = IMAGE_DATA_TYPE_BYTE;
82  }
83  else if (metadata.channels == 4) {
84  metadata.type = IMAGE_DATA_TYPE_BYTE4;
85  }
86  else {
87  return false;
88  }
89  }
90 
91  return true;
92 }
93 
95  void *out_pixels,
96  const size_t out_pixels_size,
97  const bool associate_alpha)
98 {
99  const size_t num_pixels = ((size_t)metadata.width) * metadata.height;
100  const int channels = metadata.channels;
101 
102  if (metadata.type == IMAGE_DATA_TYPE_FLOAT || metadata.type == IMAGE_DATA_TYPE_FLOAT4) {
103  /* Float. */
105 
106  if (in_pixels && num_pixels * channels == out_pixels_size) {
107  /* Straight copy pixel data. */
108  memcpy(out_pixels, in_pixels, out_pixels_size * sizeof(float));
109  }
110  else {
111  /* Missing or invalid pixel data. */
112  if (channels == 1) {
113  memset(out_pixels, 0, num_pixels * sizeof(float));
114  }
115  else {
116  const size_t num_pixels_safe = out_pixels_size / channels;
117  float *out_pixel = (float *)out_pixels;
118  for (int i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
119  out_pixel[0] = 1.0f;
120  out_pixel[1] = 0.0f;
121  out_pixel[2] = 1.0f;
122  if (channels == 4) {
123  out_pixel[3] = 1.0f;
124  }
125  }
126  }
127  }
128 
129  if (in_pixels) {
130  MEM_freeN(in_pixels);
131  }
132  }
133  else if (metadata.type == IMAGE_DATA_TYPE_HALF || metadata.type == IMAGE_DATA_TYPE_HALF4) {
134  /* Half float. Blender does not have a half type, but in some cases
135  * we up-sample byte to half to avoid precision loss for colorspace
136  * conversion. */
137  unsigned char *in_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
138 
139  if (in_pixels && num_pixels * channels == out_pixels_size) {
140  /* Convert uchar to half. */
141  const uchar *in_pixel = in_pixels;
142  half *out_pixel = (half *)out_pixels;
143  if (associate_alpha && channels == 4) {
144  for (size_t i = 0; i < num_pixels; i++, in_pixel += 4, out_pixel += 4) {
145  const float alpha = util_image_cast_to_float(in_pixel[3]);
146  out_pixel[0] = float_to_half_image(util_image_cast_to_float(in_pixel[0]) * alpha);
147  out_pixel[1] = float_to_half_image(util_image_cast_to_float(in_pixel[1]) * alpha);
148  out_pixel[2] = float_to_half_image(util_image_cast_to_float(in_pixel[2]) * alpha);
149  out_pixel[3] = float_to_half_image(alpha);
150  }
151  }
152  else {
153  for (size_t i = 0; i < num_pixels; i++) {
154  for (int c = 0; c < channels; c++, in_pixel++, out_pixel++) {
155  *out_pixel = float_to_half_image(util_image_cast_to_float(*in_pixel));
156  }
157  }
158  }
159  }
160  else {
161  /* Missing or invalid pixel data. */
162  if (channels == 1) {
163  memset(out_pixels, 0, num_pixels * sizeof(half));
164  }
165  else {
166  const size_t num_pixels_safe = out_pixels_size / channels;
167  half *out_pixel = (half *)out_pixels;
168  for (int i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
169  out_pixel[0] = float_to_half_image(1.0f);
170  out_pixel[1] = float_to_half_image(0.0f);
171  out_pixel[2] = float_to_half_image(1.0f);
172  if (channels == 4) {
173  out_pixel[3] = float_to_half_image(1.0f);
174  }
175  }
176  }
177  }
178 
179  if (in_pixels) {
180  MEM_freeN(in_pixels);
181  }
182  }
183  else {
184  /* Byte. */
185  unsigned char *in_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
186 
187  if (in_pixels && num_pixels * channels == out_pixels_size) {
188  /* Straight copy pixel data. */
189  memcpy(out_pixels, in_pixels, out_pixels_size * sizeof(unsigned char));
190 
191  if (associate_alpha && channels == 4) {
192  /* Premultiply, byte images are always straight for Blender. */
193  unsigned char *out_pixel = (unsigned char *)out_pixels;
194  for (size_t i = 0; i < num_pixels; i++, out_pixel += 4) {
195  out_pixel[0] = (out_pixel[0] * out_pixel[3]) / 255;
196  out_pixel[1] = (out_pixel[1] * out_pixel[3]) / 255;
197  out_pixel[2] = (out_pixel[2] * out_pixel[3]) / 255;
198  }
199  }
200  }
201  else {
202  /* Missing or invalid pixel data. */
203  if (channels == 1) {
204  memset(out_pixels, 0, out_pixels_size * sizeof(unsigned char));
205  }
206  else {
207  const size_t num_pixels_safe = out_pixels_size / channels;
208  unsigned char *out_pixel = (unsigned char *)out_pixels;
209  for (size_t i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
210  out_pixel[0] = 255;
211  out_pixel[1] = 0;
212  out_pixel[2] = 255;
213  if (channels == 4) {
214  out_pixel[3] = 255;
215  }
216  }
217  }
218  }
219 
220  if (in_pixels) {
221  MEM_freeN(in_pixels);
222  }
223  }
224 
225  /* Free image buffers to save memory during render. */
226  if (free_cache) {
227  b_image.buffers_free();
228  }
229 
230  return true;
231 }
232 
234 {
235  return BL::Image(b_image).name();
236 }
237 
238 bool BlenderImageLoader::equals(const ImageLoader &other) const
239 {
240  const BlenderImageLoader &other_loader = (const BlenderImageLoader &)other;
241  return b_image == other_loader.b_image && frame == other_loader.frame &&
242  tile_number == other_loader.tile_number;
243 }
244 
246 {
247  return tile_number;
248 }
249 
250 /* Point Density */
251 
253  BL::ShaderNodeTexPointDensity b_node)
254  : b_depsgraph(b_depsgraph), b_node(b_node)
255 {
256 }
257 
259 {
260  metadata.channels = 4;
261  metadata.width = b_node.resolution();
262  metadata.height = metadata.width;
263  metadata.depth = metadata.width;
264  metadata.type = IMAGE_DATA_TYPE_FLOAT4;
265  return true;
266 }
267 
269  void *pixels,
270  const size_t,
271  const bool)
272 {
273  int length;
274  b_node.calc_point_density(b_depsgraph, &length, (float **)&pixels);
275  return true;
276 }
277 
279 {
280  /* Force builtin images to be loaded along with Blender data sync. This
281  * is needed because we may be reading from depsgraph evaluated data which
282  * can be freed by Blender before Cycles reads it.
283  *
284  * TODO: the assumption that no further access to builtin image data will
285  * happen is really weak, and likely to break in the future. We should find
286  * a better solution to hand over the data directly to the image manager
287  * instead of through callbacks whose timing is difficult to control. */
289  Device *device = session->device;
290  manager->device_load_builtin(device, session->scene, session->progress);
291 }
292 
294 {
295  return BL::ShaderNodeTexPointDensity(b_node).name();
296 }
297 
299 {
300  const BlenderPointDensityLoader &other_loader = (const BlenderPointDensityLoader &)other;
301  return b_node == other_loader.b_node && b_depsgraph == other_loader.b_depsgraph;
302 }
303 
unsigned char uchar
Definition: BLI_sys_types.h:70
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Image Image
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
BlenderImageLoader(BL::Image b_image, const int frame, const int tile_number, const bool is_preview_render)
bool equals(const ImageLoader &other) const override
int get_tile_number() const override
string name() const override
bool equals(const ImageLoader &other) const override
BL::ShaderNodeTexPointDensity b_node
BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node)
string name() const override
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
void builtin_images_load()
Session * session
void device_load_builtin(Device *device, Scene *scene, Progress &progress)
ImageDataType type
Device * device
Progress progress
Scene * scene
Definition: half.h:41
ustring u_colorspace_raw
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
static unsigned char * image_get_pixels_for_frame(BL::Image &image, int frame, int tile)
static string get_enum_identifier(PointerRNA &ptr, const char *name)
static float * image_get_float_pixels_for_frame(BL::Image &image, int frame, int tile)
float util_image_cast_to_float(T value)
ccl_device_inline half float_to_half_image(float f)
Definition: half.h:74
ccl_gpu_kernel_postfix ccl_global float int num_pixels
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static unsigned c
Definition: RandGen.cpp:83
T length(const vec_base< T, Size > &a)
static void free_cache(bNodeTree *ntree)
ImageManager * image_manager
Definition: scene.h:222
@ IMAGE_DATA_TYPE_BYTE
Definition: util/texture.h:34
@ IMAGE_DATA_TYPE_FLOAT
Definition: util/texture.h:33
@ IMAGE_DATA_TYPE_FLOAT4
Definition: util/texture.h:30
@ IMAGE_DATA_TYPE_HALF
Definition: util/texture.h:35
@ IMAGE_DATA_TYPE_BYTE4
Definition: util/texture.h:31
@ IMAGE_DATA_TYPE_HALF4
Definition: util/texture.h:32