Как перебирать колесо RGB?

Я не могу найти библиотеку, которая реализует какой-то итератор RGB, который выполняет итерацию от красного (255-0-0) к желтому (255-255-0) и т. д. Возможно ли это реализовать?

Его структура должна реализовывать Iterator<Item=(u8,u8,u8)> и, возможно, содержать max_iters для изменения ее длины.

Ища функции/методы в библиотеках, я не нашел их реализации.

Я думаю, что было бы довольно просто перебрать HSV (или подобное цветовое пространство); просто увеличьте значение оттенка и используйте функцию hsv_to_rgb для сопоставления с цветовым пространством RGB.

kmdreko 27.06.2024 05:17
(255-0-0), (f64,f64,f64) - обычно f64 находится от 0.0 до 1.0. Только цвета на основе uint8_t от 0 до 255.
Finomnis 27.06.2024 08:44

ой, я имел в виду (u8, u8, u8)

Umar Siregar 28.06.2024 03:48
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
3
83
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я сделал реализацию:

pub struct RainbowIterator {
    max: usize,
    current: usize,
}

impl RainbowIterator {
    pub fn new(max: usize) -> Self {
        Self { max, current: 0 }
    }
}

impl Iterator for RainbowIterator {
    type Item = (u8, u8, u8);
    fn next(&mut self) -> Option<Self::Item> {
        let mut ret = (255, 255, 255);
        if self.current >= self.max {
            return None;
        }
        let progress: f64 = self.current as f64 / self.max as f64;
        let subprogress = progress % (1.0 / 6.0);
        let phase = (progress * 6.0) as u8;
        if phase == 0 {
            ret.2 *= 0;
            ret.1 = (255.0 * progress) as u8;
        } else if phase == 1 {
            ret.2 *= 0;
            ret.0 = 255 - (255.0 * progress) as u8;
        } else if phase == 2 {
            ret.0 *= 0;
            ret.2 = (255.0 * progress) as u8;
        } else if phase == 3 {
            ret.0 *= 0;
            ret.1 = 255 - (255.0 * progress) as u8;
        } else if phase == 4 {
            ret.1 *= 0;
            ret.0 = (255.0 * progress) as u8;
        } else {
            ret.1 *= 0;
            ret.2 = 255 - (255.0 * progress) as u8;
        }
        self.current += 1;
        return Some(ret);
    }
}

Вы можете использовать совпадение вместо if else...

8192K 27.06.2024 07:49
Ответ принят как подходящий

Эти компоненты RGB представляют собой отдельные циклические треугольные волны с разными смещениями, ограниченными от 0 до 255. Небольшая арифметика дает нам относительно компактную формулу: используйте модуль для получения циклов, абсолютное значение дает нам треугольную волну, .min() и .max() фиксируют значение.

struct Rainbow(isize);

impl Rainbow {
    fn eval(&self, offset: isize) -> u8 {
        let x = 255 * 2 - ((self.0 + offset * 255) % (255 * 6) - 255 * 3).abs();
        x.min(255).max(0) as u8
    }
}

impl Iterator for Rainbow {
    type Item = (u8, u8, u8);
    fn next(&mut self) -> Option<Self::Item> {
        let rgb = (self.eval(3), self.eval(1), self.eval(5));
        self.0 += 1;
        Some(rgb)
    }
}

fn main() {
    for (r, g, b) in Rainbow(0).take(1024) {
        println!("({r}, {g}, {b})");
    }
}

Детская площадка

Я принимаю это как ответ, так как я неправильно набрал (u8, u8, u8) как (f64, f64, f64), но я бы принял ответ кмдреко, если бы я на самом деле имел в виду (f64, f64, f64)

Umar Siregar 28.06.2024 03:51

Идея состоит в том, чтобы просто увеличить значение «оттенка» и использовать функцию для сопоставления HSV (или аналогичного цветового пространства) с RGB. Функция преобразования адаптирована из здесь. Затем вы можете реализовать итератор следующим образом:

fn hsv_to_rgb(h: f64, s: f64, v: f64) -> (f64, f64, f64) {
    let i = (h * 6.0).floor();
    let f = h * 6.0 - i;
    let p = v * (1.0 - s);
    let q = v * (1.0 - f * s);
    let t = v * (1.0 - (1.0 - f) * s);

    match (i as u32) % 6 {
        0 => (v, t, p),
        1 => (q, v, p),
        2 => (p, v, t),
        3 => (p, q, v),
        4 => (t, p, v),
        _ => (v, p, q),
    }
}

fn rainbow_wheel(steps: usize) -> impl Iterator<Item = (f64, f64, f64)> {
    (0..steps).map(move |i| hsv_to_rgb(i as f64 / (steps - 1) as f64, 1.0, 1.0))
}

Другие вопросы по теме