Add documentation about Image/ImBuf to python/RNA API.

Related to T95616, the relationship between Image ID and ImBuf 'cached'
buffers can be fairly confusing when using the RNA API.

Reviewed By: campbellbarton, jbakker

Differential Revision: https://developer.blender.org/D14833
This commit is contained in:
Bastien Montagne 2022-05-06 11:08:10 +02:00
parent 62450e8485
commit 84756b68e6
4 changed files with 82 additions and 16 deletions

View File

@ -0,0 +1,47 @@
"""
Image Data
++++++++++
The Image data-block is a shallow wrapper around image or video file(s)
(on disk, as packed data, or generated).
All actual data like the pixel buffer, size, resolution etc. is
cached in an :class:`imbuf.types.ImBuf` image buffer (or several buffers
in some cases, like UDIM textures, multi-views, animations...).
Several properties and functions of the Image data-block are then actually
using/modifying its image buffer, and not the Image data-block itself.
.. warning::
One key limitation is that image buffers are not shared between different
Image data-blocks, and they are not duplicated when copying an image.
So until a modified image buffer is saved on disk, duplicating its Image
data-block will not propagate the underlying buffer changes to the new Image.
This example script generates an Image data-block with a given size,
change its first pixel, rescale it, and duplicates the image.
The duplicated image still has the same size and colors as the original image
at its creation, all editing in the original image's buffer is 'lost' in its copy.
"""
import bpy
image_src = bpy.data.images.new('src', 1024, 102)
print(image_src.size)
print(image_src.pixels[0:4])
image_src.scale(1024, 720)
image_src.pixels[0:4] = (0.5, 0.5, 0.5, 0.5)
image_src.update()
print(image_src.size)
print(image_src.pixels[0:4])
image_dest = image_src.copy()
image_dest.update()
print(image_dest.size)
print(image_dest.pixels[0:4])

View File

@ -1073,22 +1073,31 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Depth", "Image bit depth");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_int_vector(srna,
"size",
2,
NULL,
0,
0,
"Size",
"Width and height in pixels, zero when image data can't be loaded",
0,
0);
prop = RNA_def_int_vector(
srna,
"size",
2,
NULL,
0,
0,
"Size",
"Width and height of the image buffer in pixels, zero when image data can't be loaded",
0,
0);
RNA_def_property_subtype(prop, PROP_PIXEL);
RNA_def_property_int_funcs(prop, "rna_Image_size_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_float_vector(
srna, "resolution", 2, NULL, 0, 0, "Resolution", "X/Y pixels per meter", 0, 0);
prop = RNA_def_float_vector(srna,
"resolution",
2,
NULL,
0,
0,
"Resolution",
"X/Y pixels per meter, for the image buffer",
0,
0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_float_funcs(prop, "rna_Image_resolution_get", "rna_Image_resolution_set", NULL);
@ -1105,7 +1114,7 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "pixels", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_multi_array(prop, 1, NULL);
RNA_def_property_ui_text(prop, "Pixels", "Image pixels in floating-point values");
RNA_def_property_ui_text(prop, "Pixels", "Image buffer pixels in floating-point values");
RNA_def_property_dynamic_array_funcs(prop, "rna_Image_pixels_get_length");
RNA_def_property_float_funcs(prop, "rna_Image_pixels_get", "rna_Image_pixels_set", NULL);

View File

@ -316,7 +316,7 @@ void RNA_api_image(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
func = RNA_def_function(srna, "scale", "rna_Image_scale");
RNA_def_function_ui_description(func, "Scale the image in pixels");
RNA_def_function_ui_description(func, "Scale the buffer of the image, in pixels");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_int(func, "width", 1, 1, INT_MAX, "", "Width", 1, INT_MAX);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);

View File

@ -559,7 +559,11 @@ static PyMethodDef IMB_methods[] = {
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(IMB_doc, "This module provides access to Blender's image manipulation API.");
PyDoc_STRVAR(IMB_doc,
"This module provides access to Blender's image manipulation API.\n"
"\n"
"It provides access to image buffers outside of Blender's\n"
":class:`bpy.types.Image` data-block context.\n");
static struct PyModuleDef IMB_module_def = {
PyModuleDef_HEAD_INIT,
"imbuf", /* m_name */
@ -596,7 +600,13 @@ PyObject *BPyInit_imbuf(void)
* for docs and the ability to use with built-ins such as `isinstance`, `issubclass`.
* \{ */
PyDoc_STRVAR(IMB_types_doc, "This module provides access to image buffer types.");
PyDoc_STRVAR(IMB_types_doc,
"This module provides access to image buffer types.\n"
"\n"
".. note::\n"
"\n"
" Image buffer is also the structure used by :class:`bpy.types.Image`\n"
" ID type to store and manipulate image data at runtime.\n");
static struct PyModuleDef IMB_types_module_def = {
PyModuleDef_HEAD_INIT,