Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > двухмерное цветового поле


Автор: _Y_ 12.8.2012, 18:55
Имеем прямоугольное поле. Четыре угла соответствуют четырем цветам. Переход цветов плавный.
Как посчитать цвета промежуточных пикселей?

Вот, вроде, такая схема http://forum.vingrad.ru/index.php?showtopic=149140&view=findpost&p=1119106. Но я, что-то не нашел как в CMYK смешать четыре цвета.

Спасибо.


Автор: Pavia 13.8.2012, 05:33
Можно делать по разному. 
Как билинейную интерполяцию. 
http://en.wikipedia.org/wiki/Bilinear_interpolation


Или обратную средне взвешенное расстояние. 
http://en.wikipedia.org/wiki/Inverse_distance_weighting

У билинейной есть тонкости.


Автор: Pavia 13.8.2012, 07:48
CMYK используется для моделирования смешивания цветов красок.  А RGB для смешивания цветов как на мониторе. 

Автор: ksnk 13.8.2012, 09:33
_Y_, Вероятно, лучше пользоваться HSL - три независимых числовых параметра вместо 4-х, кроме того, что именно HSL обычно используется при манипуляциях с цветом.

Вот одно из решений, для того, чтобы понять его принцип - для каждой части "цвета" (для определенности возьмем H) строится 4 точки пространства, соответствующие координатам X,Y,H. 

Вообразим себе китайскую циновку - комплект тонких палочек, провязанных друг с другом, и "приложим" край циновки к одной паре точек, а другой - к противоположной и сильно его растянем, без провисаний. Циновка, вероятно, перекрутится и , местами, растянется smile, тем не менее - поверхность циновки и будет поверхностью решения.

Как вычислить значение H на одной из планок циновки? Достаточно вычислить значения H на концах и изменить, пропорционльно расстоянию от конца "планки".  
Как вычислить значения H на концах планок? Все концы планок располагаются на одной прямой и значения H изменяется равномерно. Значения Р в углах - известны.

Выводить точные формулы мне не очень интересно  smile 

Автор: baldina 13.8.2012, 10:26
_Y_, линейно интерполируйте

Цитата(ksnk @  13.8.2012,  09:33 Найти цитируемый пост)
_Y_, Вероятно, лучше пользоваться HSL - три независимых числовых параметра вместо 4-х

странно, как ему это поможет? задача была
Цитата(_Y_ @  12.8.2012,  18:55 Найти цитируемый пост)
Имеем прямоугольное поле. Четыре угла соответствуют четырем цветам. Переход цветов плавный.


Цитата(ksnk @  13.8.2012,  09:33 Найти цитируемый пост)
Вообразим себе китайскую циновку

это и будет линейная (билинейная) интерполяция
а с провисаниями - кривые безье (которые суть функция от линейной интерполяции)

Цитата(Pavia @  13.8.2012,  05:33 Найти цитируемый пост)
У билинейной есть тонкости.

какие?

Цитата(Pavia @  13.8.2012,  05:33 Найти цитируемый пост)
Как билинейную интерполяцию. 

Цитата(Pavia @  13.8.2012,  05:33 Найти цитируемый пост)
Или обратную средне взвешенное расстояние. 

второе суть NURBS и при размерности 2 превращается в первое

Автор: _Y_ 13.8.2012, 21:47
Папа, а с кем это ты разговариваешь?

ЗЫ: Спасибо. Есть с чего начать думать smile 

Автор: Earnest 14.8.2012, 09:28
Цитата(baldina @  13.8.2012,  11:26 Найти цитируемый пост)
странно, как ему это поможет? 

Ну, возможно, имелось в виду, что RGB пространство нелинейное и расстояние между цветами там считать некорректно (соответственно, и перетекание). Т.е. некорректно с точки зрения перцепции, а если это не важно, то пофиг. А если важно, то лучше тогда использовать LAB или производные - там расстояние линейно почти.
А интерполировать цвета, согласна, проще всего билинейной интерполяцией. Или проективным преобразованием.

Автор: baldina 14.8.2012, 10:12
Цитата(Earnest @  14.8.2012,  09:28 Найти цитируемый пост)
RGB пространство нелинейное

это еще почему? при расчете яркости компоненты складываются с разными коэффициентами, но зависимость остается линейной

Автор: Pavia 14.8.2012, 18:19
Пространство RGB изначально было линейным и таким и остаётся.

Автор: _Y_ 15.8.2012, 23:31
Подумал я над вашими ответами. Получилось, что от многой мудрости много печали. Взял и сделал вот так - линейнее некуда:

Разобрал угловые цвета на RGB компоненты. Потом для каждого объекта (в идеале - пикселя) линейно смешивал каждую компоненту по такой схеме
  • Смешиваю точки 00 и 0С получаю 0X
  • Смешиваю  R0 и RC получаю RX
  • Смешиваю  0X и RX получаю желанную XY
  • Получив эту точку на всех трех RGB осях собираю три оси в цвет
user posted image
Как видите, выглядит достойно. Что мне еще нужно?

Спасибо, что подсказали - навели на мысли.

ЗЫ: Все это сделано вот этим грязноватым Java кодом. Если запустите, нажимайте на угловые кнопки - откроются диалоги выбора цвета.
Код

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;

public class ColorGradient extends JFrame {

    private static final int ROWS = 6, COLS = 9, SCALE = 50;
    private JButton[][] buttonArray = new JButton[ROWS][COLS];

    public ColorGradient() {

        this.setLayout(new GridLayout(ROWS, COLS));

        for (int r = 0; r < ROWS; r++) {
            for (int c = 0; c < COLS; c++) {
                if (((r == 0) || (r == ROWS - 1))
                        && ((c == 0) || (c == COLS - 1))) {
                    buttonArray[r][c] = new activeButton();
                } else {
                    buttonArray[r][c] = new JButton();
                }
                this.add(buttonArray[r][c]);
            }
        }

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(COLS * SCALE, ROWS * SCALE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new ColorGradient();
    }

    private void repaintAllButtons() {

        int[] rgb00 = extractRGB(buttonArray[0][0]), rgb0C = extractRGB(buttonArray[0][COLS - 1]), rgbR0 = extractRGB(buttonArray[ROWS - 1][0]), rgbRC = extractRGB(buttonArray[ROWS - 1][COLS - 1]);

        int cr, cg, cb;

        float kR, kC;

        for (int r = 0; r < ROWS; r++) {
            for (int c = 0; c < COLS; c++) {
                if (!(buttonArray[r][c] instanceof activeButton)) {

                    kR = ((float) r) / (ROWS - 1);
                    kC = ((float) c) / (COLS - 1);

                    cr = calculateOneOfRGB(rgb00[0], rgb0C[0], rgbR0[0],
                            rgbRC[0], kR, kC);
                    cg = calculateOneOfRGB(rgb00[1], rgb0C[1], rgbR0[1],
                            rgbRC[1], kR, kC);
                    cb = calculateOneOfRGB(rgb00[2], rgb0C[2], rgbR0[2],
                            rgbRC[2], kR, kC);

                    buttonArray[r][c].setBackground(new Color(cr, cg, cb));
                }
            }
        }
    }

    private int calculateOneOfRGB(int p00, int p0C, int pR0, int pRC, float kR,
            float kC) {
        float r0 = p00 * (1f - kC) + p0C * kC, rR = pR0 * (1f - kC) + pRC * kC;
        float clr = r0 * (1f - kR) + rR * kR;
        return (int) clr;
    }

    private int[] extractRGB(JButton button) {
        int[] rgb = new int[3];
        Color color = button.getBackground();
        rgb[0] = color.getRed();
        rgb[1] = color.getGreen();
        rgb[2] = color.getBlue();
        return rgb;
    }

    private class activeButton extends JButton {

        public activeButton() {

            this.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    buttonClicked();
                }
            });

        }

        private void buttonClicked() {
            this.setBackground(JColorChooser.showDialog(this, "",
                    getBackground()));
            repaintAllButtons();
        }
    }
}


Автор: Earnest 16.8.2012, 09:00
Цитата(Pavia @  14.8.2012,  19:19 Найти цитируемый пост)
Пространство RGB изначально было линейным и таким и остаётся. 

Я же написала, относительно восприятия человеческого. Т.е. одинаковая разность цветов в разных углах пространства воспринимается по-разному.
А формула "субъективной" цветовой разницы многоэтажная. А вот пространства типа LAB специально строились для обеспечения большей равномерности цветовой разницы. 

Автор: maxim1000 16.8.2012, 10:15
Цитата(_Y_ @  15.8.2012,  23:31 Найти цитируемый пост)
Разобрал угловые цвета на RGB компоненты. Потом для каждого объекта (в идеале - пикселя) линейно смешивал каждую компоненту по такой схеме

    Смешиваю точки 00 и 0С получаю 0X
    Смешиваю  R0 и RC получаю RX
    Смешиваю  0X и RX получаю желанную XY
    Получив эту точку на всех трех RGB осях собираю три оси в цвет


что и является билинейной интерполяцией...

Автор: _Y_ 17.8.2012, 19:27
Цитата(maxim1000 @  16.8.2012,  10:15 Найти цитируемый пост)
что и является билинейной интерполяцией...
 Спасибо. Очень люблю умные названия. К сожалению, сам я их почти сразу забываю smile 

Автор: maxim1000 18.8.2012, 08:27
Цитата(_Y_ @  17.8.2012,  19:27 Найти цитируемый пост)
Спасибо. Очень люблю умные названия. К сожалению, сам я их почти сразу забываю

да просто её посоветовали в первом же ответе, можно было бы время сэкономить

Автор: _Y_ 18.8.2012, 09:56
Цитата(maxim1000 @  18.8.2012,  08:27 Найти цитируемый пост)
можно было бы время сэкономить

Спасибо. Но этот проект не критичный по времени у меня. Что-то среднее между хобби и самообразованием.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)