8
$\begingroup$

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
  • $\begingroup$ blender.stackexchange.com/questions/211601/… $\endgroup$ Commented Apr 22, 2022 at 9:09
  • $\begingroup$ @DuarteFarrajotaRamos I don't think he wants to use a color palette as a ColorRamp here, but wants to convert a color palette into a ColorRamp. The answers should therefore be different. $\endgroup$
    – quellenform
    Commented Apr 22, 2022 at 9:21
  • $\begingroup$ blog.michelanders.nl/2016/12/… $\endgroup$ Commented Apr 22, 2022 at 9:25
  • $\begingroup$ @TheJeran Take a closer look at my answer. With this solution you don't need to know HEX values or enter them manually somewhere. $\endgroup$
    – quellenform
    Commented Apr 22, 2022 at 13:14

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
    Commented Apr 22, 2022 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$
    – quellenform
    Commented Apr 22, 2022 at 19:41
  • $\begingroup$ Finally tested this today. Works brilliantly. Very nice my dude. $\endgroup$
    – TheJeran
    Commented Jun 1, 2022 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$
    – quellenform
    Commented Jun 1, 2022 at 8:21
1
$\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$
1
  • $\begingroup$ Hi thanks for the answer. This is not a regular forum, according to site rules links to answers are not answers if the link goes missing your answer becomes an empty shell without content. Answers should be substantial and stand on their own without relying on external data like links, videos or images. Instead of having users go through external links could you post your addon as a code snippet here so we don't risk it getting lost. A short description of how it works would be welcome. $\endgroup$ Commented Jul 17, 2023 at 15:25

You must log in to answer this question.

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