7
$\begingroup$

is it possible to display an image within the blender UI interface ?

let say that i want to display a 500x500px image in the N panel in layout.box().column(), how to do that ?

blender can already do that when clicking on an enum with preview so it must be possible within the api right ? enter image description here

$\endgroup$

3 Answers 3

14
+50
$\begingroup$

Easy Way

Have you looked at template_preview

tex = bpy.data.textures['.hidden']
col = layout.box().column()
col.template_preview(tex)

Hard Way

So this works, but it requires a lot of finesse to make it usable. Not figured out yet how to create a layout of a fixed size to append to the panel layout for rendering over the top of. This code will render over the top of the properties panel, as opposed to the Panel UI element.

import bpy
import gpu
import bgl
from gpu_extras.batch import batch_for_shader

def draw():

    x1 = 0
    x2 = 200
    y1 = 0
    y2 = 200
   
    shader = gpu.shader.from_builtin('2D_IMAGE')
    batch = batch_for_shader(
        shader, 'TRI_FAN',
        {
            "pos": ((x1, y1), (x2, y1), (x2, y2), (x1, y2)),
            "texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
        },
    )
    
    image = bpy.data.images['logo']

    if image.gl_load():
        return # an exception happened
    
    bgl.glActiveTexture(bgl.GL_TEXTURE0)
    bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
    shader.bind()
    shader.uniform_int("image", 0)
    batch.draw(shader)
    
    image.gl_free()
    
handler = bpy.types.SpaceProperties.draw_handler_add(draw,(),'WINDOW','POST_PIXEL')

# then remove the handler with ...
bpy.types.SpaceProperties.draw_handler_remove(handler, 'WINDOW')

The hard way is maybe not the best way

$\endgroup$
5
  • $\begingroup$ Thanks a lot for te answer. I’ll try this tonight :) is it possible to an image from an os folder ? I don’t like the fact that I will need to import all image of the folder into blender first to generate This image only in the ui. The user don’t need to see this data ? Maybe it’s possible to hide it ? $\endgroup$
    – Fox
    Commented Oct 17, 2019 at 16:28
  • $\begingroup$ prefix the texture name with a . so that it is hidden $\endgroup$
    – Moog
    Commented Oct 17, 2019 at 17:52
  • $\begingroup$ wait it only works with textures list ? not images ? $\endgroup$
    – Fox
    Commented Oct 18, 2019 at 11:24
  • $\begingroup$ There's also this docs.blender.org/api/blender2.8/bpy.utils.previews.html $\endgroup$
    – Moog
    Commented Oct 18, 2019 at 16:28
  • $\begingroup$ There is a way to control the opacity of the added image? $\endgroup$ Commented Mar 3, 2020 at 16:52
6
$\begingroup$

if the quality desired is not important this technique may work (icons) this script will display all the .jpg file of the directory folder in the n panel


import os
import bpy
import bpy.utils.previews

directory   = os.path.join(bpy.utils.user_resource('SCRIPTS'), "presets", "scatter_presets_custom\\")
list_raw = []

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(directory) if isfile(join(directory, f))]

for f in onlyfiles:
    if f[-4:] == ".jpg":
        list_raw.append(f)

class Panel(bpy.types.Panel):
    """Creates a Panel in the 3D view Tools panel"""
    bl_idname = "TEST_PT_Panel" 
    bl_label = "Scatter Icon test"
    bl_category = "Scatter BETA"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_context = "objectmode"

    def draw(self, context):
        global custom_icons

        for z in list_raw:
            self.layout.template_icon(icon_value=custom_icons[z[:-4]].icon_id,scale=10)

# global variable to store icons in
custom_icons = None

def register():
    global custom_icons
    custom_icons = bpy.utils.previews.new()

    for z in list_raw:
        custom_icons.load(z[:-4], os.path.join(directory, z), 'IMAGE')


    bpy.utils.register_class(Panel)

def unregister():
    global custom_icons
    bpy.utils.previews.remove(custom_icons)

    bpy.utils.unregister_class(Panel)

if __name__ == "__main__":
    register()
```
$\endgroup$
1
  • $\begingroup$ Is it possible to change the size of the icons via this method? $\endgroup$
    – Increality
    Commented Jun 23, 2022 at 18:37
3
$\begingroup$

To the "Easy Way" from Moog i would add how to load the image and create the texture using an image:

img = bpy.data.images.load(path, check_existing=True) # load img from disk 
img = bpy.data.images['test2.png'] # load from within blend file
texture = bpy.data.textures.new(name="previewTexture", type="IMAGE")
texture.image = img
tex = bpy.data.textures['previewTexture']
tex.extension = 'CLIP'  #EXTEND # CLIP # CLIP_CUBE # REPEAT # CHECKER

# In draw():
col = self.layout.box().column()
col.template_preview(self.tex) # if tex is a variable in the same class
# or
col.template_preview(bpy.data.textures['previewTexture'])
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .