8
$\begingroup$

I created an addon to use the colormaps from Matplotlib

enter image description here

You can get it here

https://github.com/TheJeran/Blender-Colormaps/

Original Question

Does anyone have an efficient method for importing color maps into a color ramp?

At the moment I have to get the hex codes for each step in a colorramp.

enter image description here

enter image description here

Anyone know a better idea?

$\endgroup$
4

3 Answers 3

7
$\begingroup$

enter image description here

Run script to add ColorRamp to specify material

Hex version

import bpy, math

material_name = "Material"  # choose your material_name here

color = [
(0xE76254, 1),  # red = 231, green = 98, blue = 84, alpha = 1, allow lower case
(0xEF8A47, 1),
(0xF7AA58, 1),
(0xFFD06F, 1),
(0xFFE6B7, 1),
(0xAADCE0, 1),
(0x72BCD5, 1),
(0x528FAD, 1),
(0x376795, 1),
(0x1E466E, 1),
]

def to_blender_color(c):    # gamma correction
    c = min(max(0, c), 255) / 255
    return c / 12.92 if c < 0.04045 else math.pow((c + 0.055) / 1.055, 2.4)

blend_color = [(
    to_blender_color(c[0] >> 16),
    to_blender_color(c[0] >> 8 & 0xff), 
    to_blender_color(c[0] & 0xff),
    c[1]) for c in color]
color_count = len(color)

for e in blend_color:
    print(e)

mat     = bpy.data.materials[material_name] # choose material name here
tree    = mat.node_tree
nodes   = tree.nodes
node    = nodes.new(type='ShaderNodeValToRGB') # add color ramp node

ramp    = node.color_ramp
el      = ramp.elements

dis     = 1 / (color_count - 1)
x       = dis
for r in range(color_count - 2):
    el.new(x)
    x += dis

for i, e in enumerate(el):
    e.color = blend_color[i]

Dec Version

import bpy, math

material_name = "Material"  # choose your material_name here

color = [
(231, 98, 84, 1),
(247, 170, 88  1),
(..., 1),
]

def to_blender_color(c):    # gamma correction
    c = min(max(0, c), 255) / 255
    return c / 12.92 if c < 0.04045 else math.pow((c + 0.055) / 1.055, 2.4)

blend_color = [(
    to_blender_color(c[0]),
    to_blender_color(c[1]), 
    to_blender_color(c[2]),
    c[3]) for c in color]
color_count = len(color)

for e in blend_color:
    print(e)

mat     = bpy.data.materials[material_name] # choose material name here
tree    = mat.node_tree
nodes   = tree.nodes
node    = nodes.new(type='ShaderNodeValToRGB') # add color ramp node

ramp    = node.color_ramp
el      = ramp.elements

dis     = 1 / (color_count - 1)
x       = dis
for r in range(color_count - 2):
    el.new(x)
    x += dis

for i, e in enumerate(el):
    e.color = blend_color[i]
$\endgroup$
4
$\begingroup$

Of course you have the possibility to use an image as color reference.

But if you really want to transfer your color values directly into a ColorRamp without knowing their HEX values, a small Python script will help you.

enter image description here

It simply references an image (previously imported into Blender) by name, determines the color values of the pixels at certain positions and transfers them to a ColorRamp.

All you need for this example is that the color gradient runs horizontally and that you know the number of your colors and enter them into the script.

Furthermore, you have to enter the name of the previously imported image, as well as the name of your material.

In detail the following happens here:

  1. First the dimensions of the image are determined.

  2. Then a reference to the specified material is created and a new node of the type ColorRamp is created there.

  3. In the loop, using the number of color values you specified, the pixel for reading the color is determined.

    These color values are then transferred directly to the new positions of the ColorRamp created at the same time.

import bpy
from bpy import data as D

imageFile = "colorramp.png"
materialName = "Material"
colorCount = 10

# Get the reference to the specified image
img = D.images[imageFile]

# Determine height and width of the image
width = img.size[0]
height = img.size[1]

# Get the reference to the specified material
material = bpy.data.materials[materialName]

# Get the node collection of the material
nodes = material.node_tree.nodes

# Create a color ramp node
color_ramp = material.node_tree.nodes.new("ShaderNodeValToRGB")

# Get a reference to the colorRamp node
cr=D.materials[materialName].node_tree.nodes["ColorRamp"].color_ramp

# Set interpolation between color stops to "CONSTANT"
cr.interpolation = "CONSTANT"

# Convert sRGB to linear RGB
def sRGB2linear(s):
    if s <= 0.0404482362771082:
        lin = s / 12.92
    else:
        lin = ((s + 0.055) / 1.055) ** 2.4
    return lin

# Iterate through the colors
for x in range(colorCount):
    # Define the position of the pixel we want to read out
    target = [round(x * (width / colorCount) + width / colorCount/2), round(height / 2)]
    # Determine the index of the pixel to be read out (#RGBA)
    index = (target[1] * width + target[0]) * 4
    if (x > 0 and x < colorCount -1):
        # Add a new position to the ColorRamp
        cr.elements.new(position = 1 / (colorCount - 1) * x)
    
    # Read the color at the given index and set the color in the ColorRamp
    cr.elements[x].color=(
        sRGB2linear(img.pixels[index]), # R
        sRGB2linear(img.pixels[index + 1]), #G
        sRGB2linear(img.pixels[index + 2]), #B
        1, #A
    )

UPDATE: Added conversion from sRGB to linear.

$\endgroup$
4
  • $\begingroup$ This looks pretty interesting. I will let you know how it works for me when I try it. Will probably be in two weeks when I return to that task. $\endgroup$
    – TheJeran
    Apr 22 at 18:53
  • $\begingroup$ @TheJeran I assume that it even fits perfectly for you ;-) You asked for a better and more efficient method, and it doesn't really get much easier than determining the color values automatically. $\endgroup$ Apr 22 at 19:41
  • $\begingroup$ Finally tested this today. Works brilliantly. Very nice my dude. $\endgroup$
    – TheJeran
    Jun 1 at 8:12
  • $\begingroup$ @TheJeran ...Thanks for testing! I'm just wondering why you then got happy with an answer where you have to enter the values again by hand. ;-) $\endgroup$ Jun 1 at 8:21
0
$\begingroup$

I created an addon to use the colormaps from Matplotlib

enter image description here

You can get it here

https://github.com/TheJeran/Blender-Colormaps/

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.