# Batch image library to Asset Browser

So I have a library of 556 HDRIs, and I would like to add them to the Blender Asset Browser. The way I've seen many people do it is to create a new scene for each HDRI and name it accordingly, then mark the scene as an asset. This won't do, as my HDRI library is absolutely huge. Is there a way to do a batch import or something like that, to add all of them to the asset browser at once, or in a quick way? Keep in mind that all of these are not in separate blend files, and are only in the .exr format.

Thanks so much!

• Do you mean World instead of Scene? A scene cannot be marked as an asset (i.stack.imgur.com/gEIsg.jpg) Aug 16 at 21:43
• You first need to import the hdris as Blender Images, and then batch mark these images as assets (with the latest beta version). You can't add regular images as assets in Blender. Aug 17 at 5:38
• I wrote a little script that does exactly this but also creates worlds as assets. You can drag and drop them into the viewport, just like you can with materials, and you can categorize them. That's really nice. I can post an answer later if needed. Aug 17 at 8:29
• @Blunder I would love for you to post an answer! Aug 18 at 1:00

Here is a script that imports HDR images, creates world settings (worlds), marks them as asset and creates a preview for them.

The script requires a few things.

• Blender 3.3. For Blender 3.2, you need a little patch. Increase the number in line 37, e.g. return 1.0 and comment out lines 19 to 21 by adding a # at the beginning of the line. For the technical details see the linked questions at the end of this answer.

• It also requires a template node setup in the World setttings named "World (template") (line 53). There must be an Environment Texture node so the image can be defined there. The name of the node (Environment Texture) is important, not the label. (The values can be changed in the N-panel, just in case you have more than one of these nodes.)

• the generated default preview images for HDRIs look very odd for some reason. So I used a plane as a preview object with a simple material (see screenshot). The plane object must be in the XZ plane (add a plane, rotate it by 90° along X-axis, and apply Rotation) because Blender uses automatically a certain point of view to render a preview image from the plane. It does not use the camera as it does for poses.

The script looks for HDR images with *.hdr and *.exr file extensions (line 70+71) in the folder that is defined in line 68. If you want to search in subfolders you can set recursive = True and specify a folder something like C:/blender/projects/**/hdri. Then it will look for HDRIs in every subfolder named hdri that is in C:/blender/projects. Of course, C:/blender/projects/** works as well to search all subfolders in the given base folder. For the file path separator use a / not a \.

To run the script, go to Scripting workplace, create a new text data block (menu Text > New Alt+N), copy & paste the code and press the run button.

For messages and errors check the system console. Use main menu entry Window > Toggle System Console if the window is not open.

import bpy
import glob
from os import path
import functools

basename = path.basename(image_path)
img = bpy.data.images.get(basename)
if img is None:
try:
except:
print("ERROR: Cannot load image %s" % image_path)

return img

def create_hdri_previews(assets, callback):
if bpy.app.is_job_running('RENDER_PREVIEW'):     # Blender 3.3!
print("Waiting for render...")
return 0.2  # waiting time

while assets:  # generate next preview
world = assets.pop()
print(f"Creating preview for world {world.name}...")

# set image in the preview object's material
obj = bpy.context.active_object
image = world.node_tree.nodes['Environment Texture'].image
obj.material_slots[0].material.node_tree.nodes['Image Texture'].image = image

# start preview render
override = bpy.context.copy()
override["id"] = world
with bpy.context.temp_override(**override):
bpy.ops.ed.lib_id_generate_preview_from_object()
return 0.2

callback()
return None

def create_world(image_path):
if image is None: return

worldname = image.name.lower().replace('_', ' ')
worldname = worldname.replace('.exr', '').replace('.hdr', '')
worldname = worldname.title()

world = bpy.data.worlds.get(worldname)
if world is None:
template = bpy.data.worlds.get('World (template)')   # <------ World template
world = template.copy()
world.name = worldname

world.node_tree.nodes['Environment Texture'].image = image
world.asset_mark()

return world

def message_end():
print('All previews have been generated!')

if __name__ == "__main__":
data_path = 'C:/tmp'     #  <-------------------- HDRI files

hdri_files = glob.glob(f"{data_path}/*.hdr", recursive = False)
hdri_files.extend(glob.glob(f"{data_path}/*.exr", recursive = False))

assets = []
for image_path in hdri_files:

print(image_path)
assets.append(create_world(image_path))

print(f"{len(hdri_files)} files processed.")

# create preview images
bpy.app.timers.register(
functools.partial(
create_hdri_previews,
assets,
message_end
)
)


Related questions about the preview generation. Kudos to Gorgious.

• This is a handy script ! I'm pleased to see my answers helped you ;) Would you mind if I used a modified version of your script in my asset utilities addon with proper credit, of course ? Aug 21 at 20:47
• @Gorgious Hi. Yes, your answers helped a lot with the preview images. I am happy if my script is of any use. Feel free to use and modify it for your addon. Aug 22 at 23:10
• Everything seems to work fine, except that it crashes after it finishes creating everything, resulting in nothing being saved. The error is pretty long, but it starts with: Calloc returns null: len=134217728 in imb_addrectfloatImBuf, total 605046876. Blender 3.3 Aug 29 at 22:50
• @Zany_Zachary1 are you using blender 3.3+ ? Aug 30 at 5:40
• O-oh, memory errors! >.< What happens if you disable the generation of the preview images? (Comment out (#) or remove the last block of lines of the script). I haven't tested with that many files. Maybe it's too many files at once or they are too big. Try a folder with only 100 images. The script loads image files only once. Same for the world settings. Aug 30 at 11:26