Оттенки и тоны цветов hex цветов python

Есть hex цвет задача получить все: оттенки, тоны, линейный градиент и монохромные цвета, как в примере на картинке. Совершенно не понимаю, как это сделать

пример работы программы


Ответы (2 шт):

Автор решения: CrazyElf

Ну если тупо разделить переходы по каждой цветовой компоненте на одинаковое кол-во отрезков, то можно примерно так подойти к самим вычислениям:

def from_to(a, b, n, title):
    print(title)
    for i in range(n):
        print(tuple(hex(x+(y-x)*i//(n-1)) for x, y in zip(a, b)))

a = (0xf2, 0xd2, 0xd5)
b = (0xff, 0xff, 0xff)
from_to(a, b, 7, 'В белый')

a = (0xf2, 0xd2, 0xd5)
b = (0x43, 0xd2, 0xff)
from_to(a, b, 7, 'Градиент')

Вывод:

В белый
('0xf2', '0xd2', '0xd5')
('0xf4', '0xd9', '0xdc')
('0xf6', '0xe1', '0xe3')
('0xf8', '0xe8', '0xea')
('0xfa', '0xf0', '0xf1')
('0xfc', '0xf7', '0xf8')
('0xff', '0xff', '0xff')
Градиент
('0xf2', '0xd2', '0xd5')
('0xd4', '0xd2', '0xdc')
('0xb7', '0xd2', '0xe3')
('0x9a', '0xd2', '0xea')
('0x7d', '0xd2', '0xf1')
('0x60', '0xd2', '0xf8')
('0x43', '0xd2', '0xff')

Это просто заготовка для демонстрации идеи.

→ Ссылка
Автор решения: Alex Krass

Если вопрос касается получения цветов, это вам нужно изучить теорию цвета и как одни цвета преобразуется в другие в различных цветовых моделях: RGB, HSL, HSV, CMYK. К примеру в вашем примере с градиентом проще работать в RGB, а вот со всем остальным проще работать в HSL.

Для градиента выполняется просто дополнение всех цветовых составляющих пошагово от одного цвета к другому в модели RGB. Для остального проще перейти в модель HSL и не трогая параметр оттенка Hue, двигать только тени Shadow и светлота Lightness. Потом обратно переходя в RGB.

Полезные ссылки:

Ниже код на JS, поскольку мне проще на нем написать и сразу вывести в браузер результат, чем искать куда вывести цвета в Python. Надеюсь общая идея понятна и перевод из одного языка в другой не доставит проблем. Убрав весь вспомогательный код, алгоритмы разбиты по функциям и их не сложно повторить.

let color = "#f2d250";
let secondColor = "#43d2ff";
let colors = fromHexRGB(color);
let secondColors = fromHexRGB(secondColor);
    
$(`<div>${color}</div>`)
      .addClass("color")
      .css("background-color", color)   
      .appendTo(".colors");
$(`<div>${secondColor}</div>`)
      .addClass("color")
      .css("background-color", secondColor) 
      .appendTo(".colors");
$("<br>Градиент<br>").appendTo(".colors");
grad(colors, secondColors); 
$("<br>Монохромный ряд<br>").appendTo(".colors");
mono(colors);
$("<br>Добавляем тень в виде серого<br>").appendTo(".colors");
toGrey(colors);
$("<br>Переходим в светлые тона<br>").appendTo(".colors");
toLight(colors);
$("<br>Переходим в темные тона<br>").appendTo(".colors");
toDark(colors);

// Функция градиента просто двигает всю цветовую схему от одного цвета к другому
function grad(colors, secondColor) {
    for(let i = 0; i < 8; i++) {
        let rgb = [colors.r + i * (secondColor.r - colors.r) / 7, 
                   colors.g + i * (secondColor.g - colors.g) / 7, 
                   colors.b + i * (secondColor.b - colors.b) / 7];
    
        $("<div>", {
            class : "color",    
            style : "background-color: " + getHexRGB(Math.floor(rgb[0]), Math.floor(rgb[1]), Math.floor(rgb[2]))
        }).appendTo(".colors");
    }
}

// Для получения светлых тонов двигаем в HSL третье значение Lightness в сторону белого
function toLight(colors) {
    let hsl = rgbToHsl(colors.r, colors.g, colors.b);
    let step = (1 - hsl[2]) / 7;
    
    for(let i = 0; i < 8; i++) {
        let rgb = hslToRgb(hsl[0],hsl[1],hsl[2] + step * i);
    
        $("<div>", {
            class : "color",    
            style : "background-color: " + getHexRGB(Math.floor(rgb[0]), Math.floor(rgb[1]), Math.floor(rgb[2]))
        }).appendTo(".colors");
    }
}

// Для получения темных тонов двигаем в HSL третье значение Lightness в сторону черного
function toDark(colors) {
    let hsl = rgbToHsl(colors.r, colors.g, colors.b);
    let step = hsl[2] / 7;
    
    for(let i = 0; i < 8; i++) {
        let rgb = hslToRgb(hsl[0],hsl[1],hsl[2] - step * i);
    
        $("<div>", {
            class : "color",    
            style : "background-color: " + getHexRGB(Math.floor(rgb[0]), Math.floor(rgb[1]), Math.floor(rgb[2]))
        }).appendTo(".colors");
    }
}

// Для получения теней двигаем в HSL второе значение Shadow в сторону темно-серого
function toGrey(colors) {
    let hsl = rgbToHsl(colors.r, colors.g, colors.b);
    let step = hsl[1] / 7;
    
    for(let i = 0; i < 8; i++) {
        let rgb = hslToRgb(hsl[0],hsl[1] - step * i, hsl[2]);
    
        $("<div>", {
            class : "color",    
            style : "background-color: " + getHexRGB(Math.floor(rgb[0]), Math.floor(rgb[1]), Math.floor(rgb[2]))
        }).appendTo(".colors");
    }
}

// Для получения монохромных цветов, мы изменяем в HSL значение Lightness и Shadow, не трогая оттенок Hue 
function mono(colors) {
    let hsl = rgbToHsl(colors.r, colors.g, colors.b);
    
    for(let i = 0; i < 8; i++) {
        let rgb = hslToRgb(hsl[0], 0.5 + i * 0.05, 0.5 + i * 0.05);
    
        $("<div>", {
            class : "color",    
            style : "background-color: " + getHexRGB(Math.floor(rgb[0]), Math.floor(rgb[1]), Math.floor(rgb[2]))
        }).appendTo(".colors");
    }
}

// Вспомогательные функции
function rgbToHsl(r, g, b) {
  r /= 255, g /= 255, b /= 255;

  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if (max == min) {
    h = s = 0; // achromatic
  } else {
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

    switch (max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }

    h /= 6;
  }

  return [ h, s, l ];
}

function hslToRgb(h, s, l) {
  var r, g, b;

  if (s == 0) {
    r = g = b = l; // achromatic
  } else {
    function hue2rgb(p, q, t) {
      if (t < 0) t += 1;
      if (t > 1) t -= 1;
      if (t < 1/6) return p + (q - p) * 6 * t;
      if (t < 1/2) return q;
      if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
      return p;
    }

    var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    var p = 2 * l - q;

    r = hue2rgb(p, q, h + 1/3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1/3);
  }

  return [ r * 255, g * 255, b * 255 ];
}

function getHexRGB(r,g,b) {
    return "#"+(r).toString(16).padStart(2,'0')+(g).toString(16).padStart(2,'0')+(b).toString(16).padStart(2,'0');
}

function fromHexRGB(color) {
    let r = parseInt(color.substr(1,2), 16);
    let g = parseInt(color.substr(3,2), 16);
    let b = parseInt(color.substr(5,2), 16);
    return { r: r, g: g, b: b}
}
.color {
    width: 70px;
    height: 20px;
    border: 1px solid black;
    display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="colors"></div>

→ Ссылка