Help making interface for add-on. Dominant colors in image, like in Adobe Kuler.

Hi guys!
I am trying to create interface for this code (look bottom) in Blender.

Python code helps find dominant colors in image. It would be great if color data from program send to colorpicker elements on panel (Blender interface). But I couldn’t find information about colorpicker elements and how send data to it.
I am using sys.path.append() to import Pillow (PIL for Pithon 3.X), NumPy and SciPy from Python 3.3 dir.

import struct
from PIL import Image
import scipy
import codecs
import scipy.misc
import scipy.cluster

NUM_CLUSTERS = 5
print ('reading image')
im = Image.open("C:\\Users\\User\\Desktop\\maxresdefault.jpg") #path to your pics
im = im.resize((150, 150))      # resize pics, to reduce time
ar = scipy.misc.fromimage(im)
shape = ar.shape
ar = ar.reshape(scipy.product(shape[:2]), shape[2])

print ('finding clusters')
codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS)
print ('cluster centres:
', (codes))

vecs, dist = scipy.cluster.vq.vq(ar, codes)         # assign codes
counts, bins = scipy.histogram(vecs, len(codes))    # count occurrences

index_max = scipy.argmax(counts)                    # find most frequent
peak = codes[index_max]
colour = codecs.encode(peak, 'hex_codec').decode('ascii')
print ('most frequent is %s (#%s)' % (peak, colour))

Summing up I want to ask you:

  1. How to create 5 or more colorpicker elements on panel?
  2. How to send data from program to colorpickers? In hex for example…

I would be grateful for any help!

Here’s what I came up with:

import bpy
from bpy.types import PropertyGroup, Operator
from bpy.props import FloatProperty, FloatVectorProperty, PointerProperty

default_colors = (
    (1.0, 0.0, 0.01),
    (1.0, 0.26, 0.0),
    (0.9, 1.0, 0.0),
    (0.0, 1.0, 0.03),
    (0.0, 0.54, 1.0),
)

def color1_cb(self, context):
    update_color(self.color1, 1)

def color2_cb(self, context):
    update_color(self.color2, 2)

def color3_cb(self, context):
    update_color(self.color3, 3)

def color4_cb(self, context):
    update_color(self.color4, 4)

def color5_cb(self, context):
    update_color(self.color5, 5)

def update_color(color, index):
    wm = bpy.context.window_manager
    if Kuler.update:
        Kuler.update = False
        for i in range(1, 6):
            if i != index:
                colprop = "color%i" % i
                col = getattr(wm.kuler, colprop)
                new_col = col.copy()
                new_col.v = color.v
                setattr(wm.kuler, "color%i" % i, new_col)
        Kuler.update = True

def shift_cb(self, context):
    wm = context.window_manager
    Kuler.update = False
    for i in range(1, 6):
        colprop = "color%i" % i
        col = getattr(wm.kuler, colprop)
        new_col = col.copy()
        new_col.h = new_col.h + 0.01 % 1.0
        setattr(wm.kuler, "color%i" % i, new_col)
    Kuler.update = True
    
    
class Kuler(PropertyGroup):
    color1 = FloatVectorProperty(subtype='COLOR', min=0, max=1, update=color1_cb)
    color2 = FloatVectorProperty(subtype='COLOR', min=0, max=1, update=color2_cb)
    color3 = FloatVectorProperty(subtype='COLOR', min=0, max=1, update=color3_cb)
    color4 = FloatVectorProperty(subtype='COLOR', min=0, max=1, update=color4_cb)
    color5 = FloatVectorProperty(subtype='COLOR', min=0, max=1, update=color5_cb)
    shift = FloatProperty(min=0, max=1000, update=shift_cb)

Kuler.update = True


class WM_OT_kuler_default_colors(Operator):
    bl_idname = "wm.kuler_default_colors"
    bl_label = "Default Colors"
    
    def execute(self, context):
        wm = context.window_manager
        
        Kuler.update = False
        for i, col in zip(range(1,6), default_colors):
            setattr(wm.kuler, "color%i" % i, col)
        Kuler.update = True
        
        return {'FINISHED'}
        

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        wm = context.window_manager

        row = layout.row(align=True)
        row.prop(wm.kuler, "color1", text="")
        row.prop(wm.kuler, "color2", text="")
        row.prop(wm.kuler, "color3", text="")
        row.prop(wm.kuler, "color4", text="")
        row.prop(wm.kuler, "color5", text="")
        
        layout.prop(wm.kuler, "shift")
        
        layout.operator(WM_OT_kuler_default_colors.bl_idname)

    

def register():
    bpy.utils.register_module(__name__)
    bpy.types.WindowManager.kuler = PointerProperty(type=Kuler)


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.WindowManager.kuler


if __name__ == "__main__":
    register()


The color shifting isn’t that great, it’s not based on perceived color and the float property is only used to add to the hue, no matter what value it is actually set to.