Blender V5.0
rna_image_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10#include <cstring>
11#include <ctime>
12#include <fcntl.h>
13
14#include "BLI_path_utils.hh"
15
16#include "RNA_define.hh"
17#include "RNA_enum_types.hh"
18
19#include "BKE_packedFile.hh"
20
21#include "rna_internal.hh" /* own include */
22
23#ifdef RNA_RUNTIME
24
25# include "BLI_math_base.h"
26# include "BLI_string.h"
27
28# include "BKE_context.hh"
29# include "BKE_image.hh"
30# include "BKE_image_format.hh"
31# include "BKE_image_save.hh"
32# include "BKE_library.hh"
33# include "BKE_main.hh"
34# include "BKE_report.hh"
35# include "BKE_scene.hh"
36
37# include "IMB_imbuf.hh"
38
39# include "DNA_image_types.h"
40# include "DNA_scene_types.h"
41
42# include "MEM_guardedalloc.h"
43
44# include "WM_api.hh"
45
46static void rna_ImagePackedFile_save(ImagePackedFile *imapf, Main *bmain, ReportList *reports)
47{
49 reports, BKE_main_blendfile_path(bmain), imapf->filepath, imapf->packedfile) != RET_OK)
50 {
51 BKE_reportf(reports, RPT_ERROR, "Could not save packed file to disk as '%s'", imapf->filepath);
52 }
53}
54
55static void rna_Image_save_render(Image *image,
56 bContext *C,
57 ReportList *reports,
58 const char *path,
59 Scene *scene,
60 const int quality)
61{
62 Main *bmain = CTX_data_main(C);
63
64 if (scene == nullptr) {
65 scene = CTX_data_scene(C);
66 }
67
69
70 if (BKE_image_save_options_init(&opts, bmain, scene, image, nullptr, false, true)) {
71 opts.save_copy = true;
72 STRNCPY(opts.filepath, path);
73 if (quality != 0) {
74 opts.im_format.quality = clamp_i(quality, 0, 100);
75 }
76
77 if (!BKE_image_save(reports, bmain, image, nullptr, &opts)) {
79 reports, RPT_ERROR, "Image '%s' could not be saved to '%s'", image->id.name + 2, path);
80 }
81 }
82 else {
83 BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
84 }
85
87
89}
90
91static void rna_Image_save(Image *image,
92 Main *bmain,
93 bContext *C,
94 ReportList *reports,
95 const char *path,
96 const int quality,
97 const bool save_copy)
98{
99 Scene *scene = CTX_data_scene(C);
100 ImageSaveOptions opts;
101
102 if (BKE_image_save_options_init(&opts, bmain, scene, image, nullptr, false, false)) {
103 if (path && path[0]) {
104 STRNCPY(opts.filepath, path);
105 }
106 if (quality != 0) {
107 opts.im_format.quality = clamp_i(quality, 0, 100);
108 }
109 opts.save_copy = save_copy;
110 if (!BKE_image_save(reports, bmain, image, nullptr, &opts)) {
111 BKE_reportf(reports,
112 RPT_ERROR,
113 "Image '%s' could not be saved to '%s'",
114 image->id.name + 2,
115 image->filepath);
116 }
117 }
118 else {
119 BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
120 }
121
123
125}
126
127static void rna_Image_pack(
128 Image *image, Main *bmain, bContext *C, ReportList *reports, const char *data, int data_len)
129{
131
132 if (data) {
133 char *data_dup = MEM_malloc_arrayN<char>(size_t(data_len), __func__);
134 memcpy(data_dup, data, size_t(data_len));
135 BKE_image_packfiles_from_mem(reports, image, data_dup, size_t(data_len));
136 }
137 else if (BKE_image_is_dirty(image)) {
139 }
140 else {
141 BKE_image_packfiles(reports, image, ID_BLEND_PATH(bmain, &image->id));
142 }
143
145}
146
147static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int method)
148{
149 if (!BKE_image_has_packedfile(image)) {
150 BKE_report(reports, RPT_ERROR, "Image not packed");
151 return;
152 }
153
154 if (!ID_IS_EDITABLE(&image->id)) {
155 BKE_report(reports, RPT_ERROR, "Image is not editable");
156 return;
157 }
158
160 BKE_report(reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
161 return;
162 }
163
164 /* reports its own error on failure */
165 BKE_packedfile_unpack_image(bmain, reports, image, ePF_FileStatus(method));
166}
167
168static void rna_Image_reload(Image *image, Main *bmain)
169{
170 BKE_image_signal(bmain, image, nullptr, IMA_SIGNAL_RELOAD);
172}
173
174static void rna_Image_update(Image *image, ReportList *reports)
175{
176 ImBuf *ibuf = BKE_image_acquire_ibuf(image, nullptr, nullptr);
177
178 if (ibuf == nullptr) {
179 BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
180 return;
181 }
182
183 if (ibuf->byte_buffer.data) {
185 }
186
189
190 BKE_image_release_ibuf(image, ibuf, nullptr);
191}
192
193static void rna_Image_scale(
194 Image *image, ReportList *reports, int width, int height, int frame, int tile_index)
195{
196 ImageUser iuser{};
197 BKE_imageuser_default(&iuser);
198 iuser.framenr = frame;
199 if (image->source == IMA_SRC_TILED) {
200 const ImageTile *tile = static_cast<ImageTile *>(BLI_findlink(&image->tiles, tile_index));
201 if (tile != nullptr) {
202 iuser.tile = tile->tile_number;
203 }
204 }
205
206 if (!BKE_image_scale(image, width, height, &iuser)) {
207 BKE_reportf(reports, RPT_ERROR, "Image '%s' failed to load image buffer", image->id.name + 2);
208 return;
209 }
212}
213
214static int rna_Image_gl_load(
215 Image *image, ReportList *reports, int frame, int layer_index, int pass_index)
216{
217 ImageUser iuser;
218 BKE_imageuser_default(&iuser);
219 iuser.framenr = frame;
220 iuser.layer = layer_index;
221 iuser.pass = pass_index;
222 if (image->rr != nullptr) {
223 BKE_image_multilayer_index(image->rr, &iuser);
224 }
225
227
228 if (tex == nullptr) {
229 BKE_reportf(reports, RPT_ERROR, "Failed to load image texture '%s'", image->id.name + 2);
230 /* TODO(fclem): this error code makes no sense for vulkan. */
231 return 0x0502; /* GL_INVALID_OPERATION */
232 }
233
234 return 0; /* GL_NO_ERROR */
235}
236
237static int rna_Image_gl_touch(
238 Image *image, ReportList *reports, int frame, int layer_index, int pass_index)
239{
240 int error = 0; /* GL_NO_ERROR */
241
242 BKE_image_tag_time(image);
243
244 if (image->gputexture[TEXTARGET_2D][0] == nullptr) {
245 error = rna_Image_gl_load(image, reports, frame, layer_index, pass_index);
246 }
247
248 return error;
249}
250
251static void rna_Image_gl_free(Image *image)
252{
254
255 /* Remove the no-collect flag, image is available for garbage collection again. */
256 image->flag &= ~IMA_NOCOLLECT;
257}
258
259static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, char *filepath)
260{
261 BKE_image_user_file_path(image_user, image, filepath);
262}
263
264static void rna_Image_buffers_free(Image *image)
265{
266 BKE_image_free_buffers_ex(image, true);
267}
268
269#else
270
272{
273 FunctionRNA *func;
274
275 func = RNA_def_function(srna, "save", "rna_ImagePackedFile_save");
276 RNA_def_function_ui_description(func, "Save the packed file to its filepath");
278}
279
281{
282 FunctionRNA *func;
283 PropertyRNA *parm;
284
285 func = RNA_def_function(srna, "save_render", "rna_Image_save_render");
287 "Save image to a specific path using a scenes render settings");
289 parm = RNA_def_string_file_path(func, "filepath", nullptr, 0, "", "Output path");
291 RNA_def_pointer(func, "scene", "Scene", "", "Scene to take image parameters from");
292 RNA_def_int(func,
293 "quality",
294 0,
295 0,
296 100,
297 "Quality",
298 "Quality for image formats that support lossy compression, uses default quality if "
299 "not specified",
300 0,
301 100);
302
303 func = RNA_def_function(srna, "save", "rna_Image_save");
304 RNA_def_function_ui_description(func, "Save image");
307 "filepath",
308 nullptr,
309 0,
310 "",
311 "Output path, uses image data-block filepath if not specified");
312 RNA_def_int(func,
313 "quality",
314 0,
315 0,
316 100,
317 "Quality",
318 "Quality for image formats that support lossy compression, uses default quality if "
319 "not specified",
320 0,
321 100);
322 RNA_def_boolean(func,
323 "save_copy",
324 false,
325 "Save Copy",
326 "Save the image as a copy, without updating current image's filepath");
327
328 func = RNA_def_function(srna, "pack", "rna_Image_pack");
329 RNA_def_function_ui_description(func, "Pack an image as embedded data into the .blend file");
331 parm = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING);
332 RNA_def_property_ui_text(parm, "data", "Raw data (bytes, exact content of the embedded file)");
333 RNA_def_int(func,
334 "data_len",
335 0,
336 0,
337 INT_MAX,
338 "data_len",
339 "length of given data (mandatory if data is provided)",
340 0,
341 INT_MAX);
342
343 func = RNA_def_function(srna, "unpack", "rna_Image_unpack");
344 RNA_def_function_ui_description(func, "Save an image packed in the .blend file to disk");
347 func, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "method", "How to unpack");
348
349 func = RNA_def_function(srna, "reload", "rna_Image_reload");
351 RNA_def_function_ui_description(func, "Reload the image from its source path");
352
353 func = RNA_def_function(srna, "update", "rna_Image_update");
354 RNA_def_function_ui_description(func, "Update the display image from the floating-point buffer");
356
357 func = RNA_def_function(srna, "scale", "rna_Image_scale");
358 RNA_def_function_ui_description(func, "Scale the buffer of the image, in pixels");
360 parm = RNA_def_int(func, "width", 1, 1, INT_MAX, "", "Width", 1, INT_MAX);
362 parm = RNA_def_int(func, "height", 1, 1, INT_MAX, "", "Height", 1, INT_MAX);
364 RNA_def_int(func, "frame", 0, 0, INT_MAX, "Frame", "Frame (for image sequences)", 0, INT_MAX);
366 func, "tile_index", 0, 0, INT_MAX, "Tile", "Tile index (for tiled images)", 0, INT_MAX);
367
368 func = RNA_def_function(srna, "gl_touch", "rna_Image_gl_touch");
370 func, "Delay the image from being cleaned from the cache due inactivity");
373 func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
374 RNA_def_int(func,
375 "layer_index",
376 0,
377 0,
378 INT_MAX,
379 "Layer",
380 "Index of layer that should be loaded",
381 0,
382 INT_MAX);
383 RNA_def_int(func,
384 "pass_index",
385 0,
386 0,
387 INT_MAX,
388 "Pass",
389 "Index of pass that should be loaded",
390 0,
391 INT_MAX);
392 /* return value */
393 parm = RNA_def_int(
394 func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
395 RNA_def_function_return(func, parm);
396
397 func = RNA_def_function(srna, "gl_load", "rna_Image_gl_load");
399 func,
400 "Load the image into an OpenGL texture. On success, image.bindcode will contain the "
401 "OpenGL texture bindcode. Colors read from the texture will be in scene linear color space "
402 "and have premultiplied or straight alpha matching the image alpha mode.");
405 func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
406 RNA_def_int(func,
407 "layer_index",
408 0,
409 0,
410 INT_MAX,
411 "Layer",
412 "Index of layer that should be loaded",
413 0,
414 INT_MAX);
415 RNA_def_int(func,
416 "pass_index",
417 0,
418 0,
419 INT_MAX,
420 "Pass",
421 "Index of pass that should be loaded",
422 0,
423 INT_MAX);
424 /* return value */
425 parm = RNA_def_int(
426 func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
427 RNA_def_function_return(func, parm);
428
429 func = RNA_def_function(srna, "gl_free", "rna_Image_gl_free");
430 RNA_def_function_ui_description(func, "Free the image from OpenGL graphics memory");
431
432 /* path to an frame specified by image user */
433 func = RNA_def_function(srna, "filepath_from_user", "rna_Image_filepath_from_user");
435 func,
436 "Return the absolute path to the filepath of an image frame specified by the image user");
438 func, "image_user", "ImageUser", "", "Image user of the image to get filepath for");
439 parm = RNA_def_string_file_path(func,
440 "filepath",
441 nullptr,
442 FILE_MAX,
443 "File Path",
444 "The resulting filepath from the image and its user");
446 parm, PROP_THICK_WRAP, ParameterFlag(0)); /* needed for string return value */
447 RNA_def_function_output(func, parm);
448
449 func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free");
450 RNA_def_function_ui_description(func, "Free the image buffers from memory");
451
452 /* TODO: pack/unpack, maybe should be generic functions? */
453}
454
455#endif
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
bool BKE_image_scale(Image *image, int width, int height, ImageUser *iuser)
RenderPass * BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_user_file_path(const ImageUser *iuser, const Image *ima, char *filepath)
void BKE_image_tag_time(Image *ima)
bool BKE_image_memorypack(Image *ima)
void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
void BKE_image_free_buffers_ex(Image *image, bool do_lock)
bool BKE_image_is_dirty(Image *image)
void BKE_imageuser_default(ImageUser *iuser)
void BKE_image_free_gputextures(Image *ima)
Definition image_gpu.cc:581
#define IMA_SIGNAL_RELOAD
Definition BKE_image.hh:168
bool BKE_image_has_packedfile(const Image *image)
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
blender::gpu::Texture * BKE_image_get_gpu_texture(Image *image, ImageUser *iuser)
Definition image_gpu.cc:496
void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, size_t data_len)
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
void BKE_image_free_packedfiles(Image *image)
bool BKE_image_save(ReportList *reports, Main *bmain, Image *ima, ImageUser *iuser, const ImageSaveOptions *opts)
bool BKE_image_save_options_init(ImageSaveOptions *opts, Main *bmain, Scene *scene, Image *ima, ImageUser *iuser, const bool guess_path, const bool save_as_render)
Definition image_save.cc:51
void BKE_image_save_options_free(ImageSaveOptions *opts)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
int BKE_packedfile_unpack_image(Main *bmain, ReportList *reports, Image *ima, enum ePF_FileStatus how)
#define RET_OK
int BKE_packedfile_write_to_file(ReportList *reports, const char *ref_file_name, const char *filepath_rel, PackedFile *pf)
ePF_FileStatus
@ PF_USE_LOCAL
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
MINLINE int clamp_i(int value, int min, int max)
#define FILE_MAX
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define ELEM(...)
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:685
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
@ IMA_SRC_MOVIE
@ IMA_SRC_TILED
@ IMA_SRC_SEQUENCE
@ IMA_NOCOLLECT
@ TEXTARGET_2D
void IMB_byte_from_float(ImBuf *ibuf)
@ IB_DISPLAY_BUFFER_INVALID
Read Guarded memory(de)allocation.
ParameterFlag
Definition RNA_types.hh:544
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ FUNC_USE_REPORTS
Definition RNA_types.hh:914
@ FUNC_USE_MAIN
Definition RNA_types.hh:912
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:913
@ PROP_STRING
Definition RNA_types.hh:165
PropertyFlag
Definition RNA_types.hh:300
@ PROP_THICK_WRAP
Definition RNA_types.hh:423
@ PROP_BYTESTRING
Definition RNA_types.hh:240
#define C
Definition RandGen.cpp:29
#define NA_EDITED
Definition WM_types.hh:584
#define NC_IMAGE
Definition WM_types.hh:384
BMesh const char void * data
const ccl_global KernelWorkTile * tile
const int tile_index
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
static void error(const char *str)
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
FunctionRNA * RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
PropertyRNA * RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description)
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
void RNA_def_function_flag(FunctionRNA *func, int flag)
PropertyRNA * RNA_def_string_file_path(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_function_output(FunctionRNA *, PropertyRNA *ret)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
void RNA_api_image(StructRNA *srna)
void RNA_api_image_packed_file(StructRNA *srna)
const EnumPropertyItem rna_enum_unpack_method_items[]
char name[258]
Definition DNA_ID.h:432
ImBufByteBuffer byte_buffer
struct PackedFile * packedfile
char filepath[1024]
ImageFormatData im_format
GPUTexture * gputexture[3][2]
char filepath[1024]
ListBase tiles
short source
struct RenderResult * rr
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)