Blender V4.5
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,
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,
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)) {
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{
130 const bool is_packed = BKE_image_has_packedfile(image);
131 const bool is_dirty = BKE_image_is_dirty(image);
132
133 if (is_packed && !is_dirty && !data) {
134 /* Image is already packed and considered unmodified, do not attempt to repack it, since:
135 * - Its original file may not be available anymore on the current FS.
136 * - Repacking from the current runtime buffer will force the packedfile format to OpenEXR or
137 * PNG (see code of #image_memorypack_imbuf).
138 *
139 * See #152638.
140 */
141 return;
142 }
143
145
146 if (data) {
147 char *data_dup = MEM_malloc_arrayN<char>(size_t(data_len), __func__);
148 memcpy(data_dup, data, size_t(data_len));
149 BKE_image_packfiles_from_mem(reports, image, data_dup, size_t(data_len));
150 }
151 else if (is_dirty) {
153 }
154 else {
155 BKE_image_packfiles(reports, image, ID_BLEND_PATH(bmain, &image->id));
156 }
157
159}
160
161static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int method)
162{
163 if (!BKE_image_has_packedfile(image)) {
164 BKE_report(reports, RPT_ERROR, "Image not packed");
165 return;
166 }
167
168 if (!ID_IS_EDITABLE(&image->id)) {
169 BKE_report(reports, RPT_ERROR, "Image is not editable");
170 return;
171 }
172
174 BKE_report(reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
175 return;
176 }
177
178 /* reports its own error on failure */
179 BKE_packedfile_unpack_image(bmain, reports, image, ePF_FileStatus(method));
180}
181
182static void rna_Image_reload(Image *image, Main *bmain)
183{
184 BKE_image_signal(bmain, image, nullptr, IMA_SIGNAL_RELOAD);
186}
187
188static void rna_Image_update(Image *image, ReportList *reports)
189{
190 ImBuf *ibuf = BKE_image_acquire_ibuf(image, nullptr, nullptr);
191
192 if (ibuf == nullptr) {
193 BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
194 return;
195 }
196
197 if (ibuf->byte_buffer.data) {
199 }
200
203
204 BKE_image_release_ibuf(image, ibuf, nullptr);
205}
206
207static void rna_Image_scale(
208 Image *image, ReportList *reports, int width, int height, int frame, int tile_index)
209{
210 ImageUser iuser{};
211 BKE_imageuser_default(&iuser);
212 iuser.framenr = frame;
213 if (image->source == IMA_SRC_TILED) {
214 const ImageTile *tile = static_cast<ImageTile *>(BLI_findlink(&image->tiles, tile_index));
215 if (tile != nullptr) {
216 iuser.tile = tile->tile_number;
217 }
218 }
219
220 if (!BKE_image_scale(image, width, height, &iuser)) {
221 BKE_reportf(reports, RPT_ERROR, "Image '%s' failed to load image buffer", image->id.name + 2);
222 return;
223 }
226}
227
228static int rna_Image_gl_load(
229 Image *image, ReportList *reports, int frame, int layer_index, int pass_index)
230{
231 ImageUser iuser;
232 BKE_imageuser_default(&iuser);
233 iuser.framenr = frame;
234 iuser.layer = layer_index;
235 iuser.pass = pass_index;
236 if (image->rr != nullptr) {
237 BKE_image_multilayer_index(image->rr, &iuser);
238 }
239
240 GPUTexture *tex = BKE_image_get_gpu_texture(image, &iuser);
241
242 if (tex == nullptr) {
243 BKE_reportf(reports, RPT_ERROR, "Failed to load image texture '%s'", image->id.name + 2);
244 /* TODO(fclem): this error code makes no sense for vulkan. */
245 return 0x0502; /* GL_INVALID_OPERATION */
246 }
247
248 return 0; /* GL_NO_ERROR */
249}
250
251static int rna_Image_gl_touch(
252 Image *image, ReportList *reports, int frame, int layer_index, int pass_index)
253{
254 int error = 0; /* GL_NO_ERROR */
255
256 BKE_image_tag_time(image);
257
258 if (image->gputexture[TEXTARGET_2D][0] == nullptr) {
259 error = rna_Image_gl_load(image, reports, frame, layer_index, pass_index);
260 }
261
262 return error;
263}
264
265static void rna_Image_gl_free(Image *image)
266{
268
269 /* Remove the no-collect flag, image is available for garbage collection again. */
270 image->flag &= ~IMA_NOCOLLECT;
271}
272
273static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, char *filepath)
274{
275 BKE_image_user_file_path(image_user, image, filepath);
276}
277
278static void rna_Image_buffers_free(Image *image)
279{
280 BKE_image_free_buffers_ex(image, true);
281}
282
283#else
284
286{
287 FunctionRNA *func;
288
289 func = RNA_def_function(srna, "save", "rna_ImagePackedFile_save");
290 RNA_def_function_ui_description(func, "Save the packed file to its filepath");
292}
293
295{
296 FunctionRNA *func;
297 PropertyRNA *parm;
298
299 func = RNA_def_function(srna, "save_render", "rna_Image_save_render");
301 "Save image to a specific path using a scenes render settings");
303 parm = RNA_def_string_file_path(func, "filepath", nullptr, 0, "", "Output path");
305 RNA_def_pointer(func, "scene", "Scene", "", "Scene to take image parameters from");
306 RNA_def_int(func,
307 "quality",
308 0,
309 0,
310 100,
311 "Quality",
312 "Quality for image formats that support lossy compression, uses default quality if "
313 "not specified",
314 0,
315 100);
316
317 func = RNA_def_function(srna, "save", "rna_Image_save");
318 RNA_def_function_ui_description(func, "Save image");
321 "filepath",
322 nullptr,
323 0,
324 "",
325 "Output path, uses image data-block filepath if not specified");
326 RNA_def_int(func,
327 "quality",
328 0,
329 0,
330 100,
331 "Quality",
332 "Quality for image formats that support lossy compression, uses default quality if "
333 "not specified",
334 0,
335 100);
336 RNA_def_boolean(func,
337 "save_copy",
338 false,
339 "Save Copy",
340 "Save the image as a copy, without updating current image's filepath");
341
342 func = RNA_def_function(srna, "pack", "rna_Image_pack");
343 RNA_def_function_ui_description(func, "Pack an image as embedded data into the .blend file");
345 parm = RNA_def_property(func, "data", PROP_STRING, PROP_BYTESTRING);
346 RNA_def_property_ui_text(parm, "data", "Raw data (bytes, exact content of the embedded file)");
347 RNA_def_int(func,
348 "data_len",
349 0,
350 0,
351 INT_MAX,
352 "data_len",
353 "length of given data (mandatory if data is provided)",
354 0,
355 INT_MAX);
356
357 func = RNA_def_function(srna, "unpack", "rna_Image_unpack");
358 RNA_def_function_ui_description(func, "Save an image packed in the .blend file to disk");
361 func, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "method", "How to unpack");
362
363 func = RNA_def_function(srna, "reload", "rna_Image_reload");
365 RNA_def_function_ui_description(func, "Reload the image from its source path");
366
367 func = RNA_def_function(srna, "update", "rna_Image_update");
368 RNA_def_function_ui_description(func, "Update the display image from the floating-point buffer");
370
371 func = RNA_def_function(srna, "scale", "rna_Image_scale");
372 RNA_def_function_ui_description(func, "Scale the buffer of the image, in pixels");
374 parm = RNA_def_int(func, "width", 1, 1, INT_MAX, "", "Width", 1, INT_MAX);
376 parm = RNA_def_int(func, "height", 1, 1, INT_MAX, "", "Height", 1, INT_MAX);
378 RNA_def_int(func, "frame", 0, 0, INT_MAX, "Frame", "Frame (for image sequences)", 0, INT_MAX);
380 func, "tile_index", 0, 0, INT_MAX, "Tile", "Tile index (for tiled images)", 0, INT_MAX);
381
382 func = RNA_def_function(srna, "gl_touch", "rna_Image_gl_touch");
384 func, "Delay the image from being cleaned from the cache due inactivity");
387 func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
388 RNA_def_int(func,
389 "layer_index",
390 0,
391 0,
392 INT_MAX,
393 "Layer",
394 "Index of layer that should be loaded",
395 0,
396 INT_MAX);
397 RNA_def_int(func,
398 "pass_index",
399 0,
400 0,
401 INT_MAX,
402 "Pass",
403 "Index of pass that should be loaded",
404 0,
405 INT_MAX);
406 /* return value */
407 parm = RNA_def_int(
408 func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
409 RNA_def_function_return(func, parm);
410
411 func = RNA_def_function(srna, "gl_load", "rna_Image_gl_load");
413 func,
414 "Load the image into an OpenGL texture. On success, image.bindcode will contain the "
415 "OpenGL texture bindcode. Colors read from the texture will be in scene linear color space "
416 "and have premultiplied or straight alpha matching the image alpha mode.");
419 func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
420 RNA_def_int(func,
421 "layer_index",
422 0,
423 0,
424 INT_MAX,
425 "Layer",
426 "Index of layer that should be loaded",
427 0,
428 INT_MAX);
429 RNA_def_int(func,
430 "pass_index",
431 0,
432 0,
433 INT_MAX,
434 "Pass",
435 "Index of pass that should be loaded",
436 0,
437 INT_MAX);
438 /* return value */
439 parm = RNA_def_int(
440 func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
441 RNA_def_function_return(func, parm);
442
443 func = RNA_def_function(srna, "gl_free", "rna_Image_gl_free");
444 RNA_def_function_ui_description(func, "Free the image from OpenGL graphics memory");
445
446 /* path to an frame specified by image user */
447 func = RNA_def_function(srna, "filepath_from_user", "rna_Image_filepath_from_user");
449 func,
450 "Return the absolute path to the filepath of an image frame specified by the image user");
452 func, "image_user", "ImageUser", "", "Image user of the image to get filepath for");
453 parm = RNA_def_string_file_path(func,
454 "filepath",
455 nullptr,
456 FILE_MAX,
457 "File Path",
458 "The resulting filepath from the image and its user");
460 parm, PROP_THICK_WRAP, ParameterFlag(0)); /* needed for string return value */
461 RNA_def_function_output(func, parm);
462
463 func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free");
464 RNA_def_function_ui_description(func, "Free the image buffers from memory");
465
466 /* TODO: pack/unpack, maybe should be generic functions? */
467}
468
469#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:570
#define IMA_SIGNAL_RELOAD
Definition BKE_image.hh:161
bool BKE_image_has_packedfile(const Image *image)
GPUTexture * BKE_image_get_gpu_texture(Image *image, ImageUser *iuser)
Definition image_gpu.cc:486
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
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:45
void BKE_image_save_options_free(ImageSaveOptions *opts)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:877
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
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
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:688
#define ELEM(...)
@ 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:510
@ PARM_REQUIRED
Definition RNA_types.hh:511
@ FUNC_USE_REPORTS
Definition RNA_types.hh:805
@ FUNC_USE_MAIN
Definition RNA_types.hh:803
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:804
@ PROP_STRING
Definition RNA_types.hh:153
PropertyFlag
Definition RNA_types.hh:286
@ PROP_THICK_WRAP
Definition RNA_types.hh:397
@ PROP_BYTESTRING
Definition RNA_types.hh:228
#define C
Definition RandGen.cpp:29
#define NA_EDITED
Definition WM_types.hh:581
ReportList * reports
Definition WM_types.hh:1025
#define NC_IMAGE
Definition WM_types.hh:381
BMesh const char void * data
#define ID_BLEND_PATH(_bmain, _id)
#define ID_IS_EDITABLE(_id)
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[66]
Definition DNA_ID.h:415
ImBufByteBuffer byte_buffer
struct PackedFile * packedfile
char filepath[1024]
ImageFormatData im_format
char filepath[1024]
ListBase tiles
struct GPUTexture * gputexture[3][2]
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)