Image Format Add-ons
My proposal is to add the ability for users to create Python add-ons that load custom image formats "natively" within Blender.
Motivation
Working with non-standard or proprietary image formats within Blender (of which there are countless) is a pain, requiring the user to convert the images to more common formats outside of Blender before working with them.
Though it's currently possible to write an operator to load an image of a custom format, the loaded image isn't treated as a "first-class" image because it:
- Cannot be natively reloaded from its the source file
- Cannot natively save the image in its original format
Being able to treat custom image formats as first-class images would allow a much smoother and natural workflow, as well as enabling the community to provide support for new and emerging formats.
API
Adding a new file format should be as simple as possible, with the user needing only to provide a few key methods (mirroring the existing requirements for
ImFileType
struct).
I propose a new
bpy.types.ImageFormat
class with stub methods to be filled out by the user (
load_bytes
,
save
etc.). The Python interface would look something like this (not an exhaustive implementation):
(Apologies for the wacky formatting, this site doesn't like indentation apparently).
class FOOBAR_IF_MyImageFormat(bpy.types.ImageFormat):
bl_name = None # Name of file format (eg. WebP)
bl_description = None # Brief description of format (eg. WebP Image)
bl_extensions = [] # List of extensions (eg. ['.webp'])
bl_default_role = None # The color role default (either `byte` or `float`)
@classmethod
def init(cls):
'''
Initialization logic, if needed.
'''
pass
@classmethod
def exit(cls):
'''
Tear-down logic, if needed.
'''
pass
@classmethod
def is_a_bytes(cls, bytes: bytes) -> bool:
'''
Returns True if the bytes indicate they are of this image
format type (eg. checking FourCC).
'''
return False
@classmethod
def is_a_filename(cls, filepath: str) -> bool:
'''
Returns True if the file path indicates that it is
of this image format type (eg. checking file extension).
'''
return False
@classmethod
def load_bytes(cls, bytes: bytes, flags: int, colorspace: imbuf.ColorSpace) -> ImBuf:
'''
Returns a new ImBuf instance given a byte array.
If an error occurs, raise an Exception.
'''
raise NotImplementedError()
@classmethod
def load_filepath(cls, filepath: str, flags: int, colorspace: imbuf.ColorSpace): -> ImBuf:
'''
Returns a new ImBuf instance given a filepath.
If an error occurs, raise an Exception.
'''
raise NotImplementedError()
@classmethod
def load_tile(cls, imbuf: ImBuf, bytes: bytes, tile: Tuple[int], bytes: bytearray):
'''
Loads a tile from the image buffer.
'''
raise NotImplementedError()
@classmethod
def save(cls, imbuf: ImBuf, filepath: str, flags: int):
'''
Saves an image to the given file path.
'''
raise NotImplementedError()
Registering the image format add-on can be done the same way other add-ons (eg. operators) are already registered currently (note the
IF
acronym (for "Image Format").
# Register
bpy.utils.register_class(FOOBAR_IF_MyImageFormat)
# Unregister
bpy.utils.unregister_class(FOOBAR_IF_MyImageFormat)
Technical Notes
-
Some additional work will be required to get started. For example, the relatively new
imbufmodule would need to have its Python bridge extended to allow for key bits of functionality to be exposed (eg. I/O of pixel data, color space information etc.) -
Currently, the image file types are listed out in the
IMB_FILE_TYPESstatic-array, which is immutable. This will need to be changed to a dynamic array so that new file formats can be registered and unregistered at run-time. -
File types are stored in hard-coded enumerations throughout the code (eg.
emImbTypes,R_IMF_IMTYPE_PNG). These values are stored in DNA data, so a forward compatible solution will need to be devised to account for this. For example, a newR_IMF_IMTYPE_ADDONcould be added to indicate that the file type is associated with an add-on. There may be issues with that approach, but I might need some input from someone more familiar with the systems in play.
Comments?
I'm looking for input before I begin; any showstoppers I might be missing etc. Thank you for your time.
4 Comments
I often dream of using KRITA images natively in Blender, with layers.
Just curious why not using multi channel EXR format? It goes up to 32bit
This comment is missing the point.
There are loads of image formats outside of the ones that Blender supports that are domain specific . For example, video games, GIS systems etc. all use specialized image formats that are not supported by Blender. If you want to use them in Blender, you need to convert them to a supported format before importing. Allowing users to make their own addons for supporting different image types is the only way to accomplish what is described above.
Awesome idea!