Russian Qt Forum
Ноябрь 23, 2024, 08:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: операторы для ARGB  (Прочитано 32678 раз)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #15 : Сентябрь 02, 2010, 18:14 »

Если я правильно понял, то при сложении двух цветов c1 и c2 их альфа канал должен также складываться, но не выходить за пределы 1.0f

Например, можно так:
Код
C++ (Qt)
   result.r = 0.5 * (c1.r + c2.r);
   result.g = 0.5 * (c1.g + c2.g);
   result.b = 0.5 * (c1.b + c2.b);
   result.alpha = (c1.alpha + c2.alpha > 1.0) ? 1.0f : c1.alpha + c2.alpha;
 

Но мне это не нравится)
« Последнее редактирование: Сентябрь 02, 2010, 18:20 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
BRE
Гость
« Ответ #16 : Сентябрь 02, 2010, 18:58 »

Давайте переведем "литры" в ARGB модель. Для красной краски имеем

1-литр  Red = 1.0f, Alpha = 0.8f
2-литр  Red = 1.0f, Alpha = 0.5f
--------------------------
смесь: Red = 1.0f, Alpha = 0.65f

Т.е. предложенная Вами модель никак не учитывает интенсивность самого R(G, B)
Давай посмотрим так.
Есть две точки образующие ребро. Обе одного цвета, скажем красного. Цвет любой точки на этом ребре должен быть красным.
Или такой пример. Две точки, одна белая вторая черная. Для них установили альфу == 0, точки полностью прозрачны. Интерполировали точку по середине ребра. Должна получиться точка серого цвета. После этого устанавливаем альфу для всех трех точек == 1, точки полностью не прозрачны. Рисуем сцену и видим все как нужно, черную-серую-белую точки.
Если использовать твою функцию AverageARGB для точек с альфой == 0, то результирующая точка всегда будет черной. Какая-то это не правильная интерполяция.
IMHO, альфа задает только прозрачность при наложении этой точки на фон, т.е. только при рендеринге.
Записан
Denjs
Гость
« Ответ #17 : Сентябрь 02, 2010, 19:17 »

Давайте переведем "литры" в ARGB модель. Для красной краски имеем

1-литр  Red = 1.0f, Alpha = 0.8f
2-литр  Red = 1.0f, Alpha = 0.5f
--------------------------
смесь: Red = 1.0f, Alpha = 0.65f

Да, все верно, если вы считали как
литр1= 800 мл краски  Red=1.0f + 200 мл воды
литр2= 500 мл краски  Red=1.0f + 500 мл воды
смесь: 2литра: 1300 мл краски  Red=1.0f + 700 мл воды
что в пересчете на 1 литр 650 мл краски  Red=1.0f + 350 мл воды

Цитировать
Т.е. предложенная Вами модель никак не учитывает интенсивность самого R(G, B)
Ну это не моя модель не учитывает, а формула, которая (да, признаю ошибся) справедлива только когда R1=R2 )))).
И частный случай рассмотренный выше.

Для того что бы модель была понятнее, рассмотрим другие случаи:

Предположим, вы хотите получить краску соответсвующую не Red=1.0f , а скажем Red=0.3f,  что делать?
Будьте добры смешать 300 мл Красной краски + 700 мл Черной - тогда вы получите 1 литр темно-красной краски,
т.е. красный значением R=0.3f
Где прозрачность? её нет. Краска не прозрачная.
т.е. (300 мл Красной краски + 700 мл Черной)  = (R=0.3f, Alpha = 1.0f)

Для того что бы получить 1 литр полупрозрачной смесси, скажем ( R=0.3f, Alpha = 0.8f)
возьмите 800 мл не прозрачной смеси, и смешайте его с 200 мл. воды.
т.е. получим 240 мл красной ( 300*0.8 ), 560 черной ( 700*0.8 ), и 200 мл. воды. - это ( R=0.3f Alpha = 0.8f )



Просчитайте смешение 2-х растворов одинакового объема далее самостоятельно, и выведите полную формулу расчета прозрачности конечного раствора и "интенсивности красного" в конечном растворе.

Там будет и зависимость от интенсивности которую вы так хотите видеть, и ( вроде как) красивая зависимость похожая на расчет вероятностей 2-х событий. А вот прозрачность по прежнему будет рассчитываться по среднему.

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

Делать это за вас я не буду, потому что вы уже второй день не хотите создать модель физического процесса и просчитать его, а тыкаете пальцем в стиле "очевидно-не-очевидно" .
И меня на это дурной подход подсадили. (оттуда и формула в последнем посте появиась и ряд других ошибок).

« Последнее редактирование: Сентябрь 02, 2010, 19:52 от Denjs » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Сентябрь 02, 2010, 20:46 »

Если использовать твою функцию AverageARGB для точек с альфой == 0, то результирующая точка всегда будет черной. Какая-то это не правильная интерполяция.
Это просто крайний/граничный случай. Типа "в 1 литре воды НОЛЬ красной краски" (?) Эта ситуация не определена, нельзя говорить что краска красная если нет самой краски. Результат "черный" для этой ситуации единственно возможный.

Если я правильно понял, то при сложении двух цветов c1 и c2 их альфа канал должен также складываться, но не выходить за пределы 1.0f
Альфа канал должен просто осредняться, а не складываться, с этой компонентой все ясно. Пример: есть 2 одинаковых ARGB, результат любой интерполяции должен быть тем же значением (мы не комбинируем слои а интерполируем точки 1-го слоя).

а тыкаете пальцем в стиле "очевидно-не-очевидно" .
И меня на это дурной подход подсадили.
Ну вот, оказывается я дурно влияю на подрастающее поколение  Улыбающийся  Давайте вместо того чтобы горячиться рассмотрим  простой пример (взвешиваем прямолинейно):

С1:  A = 1.0f,  R = 0.0f, G = 0.0f, B = 0.0f    (видимый RGB = 0.0f, 0.0f, 0.0f)
С2:  A = 0.01f, R = 0.0f, G = 0.0f, B = 1.0f   (видимый RGB = 0.0f, 0.0f, 0.01f)
------------------------
result A = 0.505f, R = 0.0f, G = 0.0f, B = 0.5f   (видимый RGB = 0.0f, 0.0f, 0.25f)

Почему же в результате интерполяции мы увидим куда больше синего чем было в обоих исходных точках? (как в том анекдоте где "ребенок накакал больше собственного веса"?  Улыбающийся ) Разве это не есть очевидно?

Просчитайте смешение 2-х растворов одинакового объема далее самостоятельно, и выведите полную формулу расчета прозрачности конечного раствора и "интенсивности красного" в конечном растворе.
Да я давно все посчитал и привел в своем посте #6 этой темы. Вопрос был по технике C++ (как сделать удобно)
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #19 : Сентябрь 02, 2010, 20:53 »

а расскажите анекдот:)
Записан
spectre71
Гость
« Ответ #20 : Сентябрь 02, 2010, 21:44 »

С синтаксисом проблем нет, я спрашиваю как сделать операторы чтобы они давали разумный/корректный результат. Пример:

Код
C++ (Qt)
ARGB c1, c2;
...
// теперь мне надо получить среднее значение
// хорошо бы записать так
ARGB average = (c1 + c2) * 0.5f;
 
Но что должен делать + ?

В данной модели отсутствует дистрибутивность.
Та что бинарными операциями не получится объеднить цвета.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Сентябрь 03, 2010, 19:41 »

В данной модели отсутствует дистрибутивность.
Та что бинарными операциями не получится объеднить цвета.
Это просто другая формулировка того что прямолинейное использование арифметики (+. * . / ) не проходит для ARGB (в отличие от напр RGB). Но можно действовать и по-другому, напр.

Код
C++ (Qt)
// просто суммируем компоненты
inline ARGB operator + ( const ARGB & c1, const ARGB & c2 )
{
return ARGB(c1.a + c2.a, c1.r + c2.r, c1.g + c2.g, c1.b + c2.b);
}
 
// умножаем альфу на t, RGB на t * alpha
inline ARGB operator * ( const ARGB & c, float t )
{
float t2 = c.a * t;
return ARGB(t2, c.r * t2, c.g * t2, c.b * t2);
}
 
// делим альфу на t, RGB на t * alpha
inline ARGB operator / ( const ARGB & c, float t )
{
float t2 = MAX(c.a * t, 1.0e-4f);
return ARGB(c.a / t, c.r / t2, c.g / t2, c.b / t2);
}
 
После этого
Код
C++ (Qt)
ARGB result1 = (c1 + c2) / 2;  // так ничего хорошего не получится ;-)
ARGB result2 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;  // a так ?
ARGB result3 = (c1 * 0.125f + c2 * 0.5f + с3 * 0.375f) / 1.0f;  // или так ?
 
Не уверен что это правильно/элегантно. Критикуем, улучшаем
Записан
spectre71
Гость
« Ответ #22 : Сентябрь 03, 2010, 20:01 »

Так дейсвительно ничего путного не получится.
Нужна либо
- тринарная операция f(C1, C2, IntermediateFactor)
либо
- использовать не ARGB, а свой промежуточный класс.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #23 : Сентябрь 04, 2010, 10:41 »

Так дейсвительно ничего путного не получится.
Это утверждение голословно до тех пор пока Вы не укажете ошибку (я ее пока не вижу).
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #24 : Сентябрь 04, 2010, 11:22 »

Не знаю как остальные, но я уже совсем запутался)
Надо внести ясность..
Я мыслю так:
1) любой цвет в представлении ARGB - это точка в 4-пространстве (4-куб с ребром = 1)
2) Если определёна операция "+" для любых двух цветов, то очевидно
    c = a + b - результат тоже точка в этом же 4-кубе
3) Скорее наводящий вопрос:
    a + b = b + a ?
это важно, поскольку отражает суть процесса смешения двух цветов.

4) тож вопрос для уяснения:
Что по Вашей логике должно получиться при сложении следующих цветов:
a)
   с1=с1(1, 0, 0, 1) (A, R, G, B)
   c2 = c2(0.5, 0, 0, 1) (A, R, G, B)
   res1 = c1 + c2 ?
   res2 = c2 + c1 ?
---------------------------------------------
b)
   c1=c1(0.5, 0, 0, 1)
   c2=c2(0.5, 0, 0, 0.5)
   res1 = c1 + c2 ?
   res2 = c2 + c1 ?

 Непонимающий
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Сентябрь 04, 2010, 13:10 »

Я мыслю так:
1) любой цвет в представлении ARGB - это точка в 4-пространстве (4-куб с ребром = 1)
Нет. эта аналогия неуместна, т.к. в n-мерном пространстве все измерения "равноправны". А здесь альфа канал специфичен

4) тож вопрос для уяснения:
Что по Вашей логике должно получиться при сложении следующих цветов:
a)
   с1=с1(1, 0, 0, 1) (A, R, G, B)
   c2 = c2(0.5, 0, 0, 1) (A, R, G, B)
   res1 = c1 + c2 ?
   res2 = c2 + c1 ?
res1 = res2 = (0.75. 0, 0, 1) (A, R, G, B)

b)
   c1=c1(0.5, 0, 0, 1)
   c2=c2(0.5, 0, 0, 0.5)
   res1 = c1 + c2 ?
   res2 = c2 + c1 ?
res1 = res2 = (0.5. 0, 0, 0.75) (A, R, G, B)
Ну и как обсуждалось выше, просто + не пройдет, предлагается

res1 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #26 : Сентябрь 04, 2010, 14:12 »

Цитировать
Я мыслю так:
1) любой цвет в представлении ARGB - это точка в 4-пространстве (4-куб с ребром = 1)

Нет. эта аналогия неуместна, т.к. в n-мерном пространстве все измерения "равноправны". А здесь альфа канал специфичен

И в чём же его специфичность, если операция сложения двух цветов у Вас - просто среднее?
Цитировать
res1 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;

Цитировать
Ну и как обсуждалось выше, просто + не пройдет, предлагается res1 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;
Пройдёт, если определить оператор "+":
Код
C++ (Qt)
inline const ARGB operator+(const ARGB &c1, const ARGB &c2)
{
   ARGB  res;
   res.alpha = 0.5f * (c1.alpha + c2.alpha);
   res.r = 0.5f * (c1.r + c2.r);
   res.g = 0.5f * (c1.g + c2.g);
   res.b = 0.5f * (c1.b + c2.b);
   return res;
}
 

Кстати, а зачем здесь:
Цитировать
res1 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;
нужно делить на единицу? Без деления получится другой результат? Непонимающий

Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Сентябрь 04, 2010, 14:22 »

И в чём же его специфичность, если операция сложения двух цветов у Вас - просто среднее?
Не просто как обсуждалось в посте #18. В частных случаях (как в Ваших примерах где A или RGB одинаковы) просто сложение дает правильный результат, но в общем случае нет

Кстати, а зачем здесь:
Цитировать
res1 = (c1 * 0.5f + c2 * 0.5f) / 1.0f;
нужно делить на единицу? Без деления получится другой результат? Непонимающий
Да. другой, см. оператор деления предложенный в посте #21
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #28 : Сентябрь 04, 2010, 15:03 »

Ладненько, тогда следуя Вашей логике, можно оставить только лишь один оператор "+" определённый след. образом:
Код
C++ (Qt)
inline const ARGB operator+(const ARGB &c1, const ARGB &c2)
{
   ARGB  res;
   float x = 0.5f * (1.0 - c1.alpha + c2.alpha);
 
   res.alpha = 0.5f * (c1.alpha + c2.alpha);
   res.r = c1.r * (1.0f - x) + x * c2.r;
   res.g = c1.g * (1.0f - x) + x * c2.g;
   res.b = c1.b * (1.0f - x) + x * c2.b;
   return res;
}
 

Очевидно как получается эта формула?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #29 : Сентябрь 04, 2010, 16:02 »

Немного опечатался: нужно писать
Код
C++ (Qt)
inline const ARGB operator+(const ARGB &c1, const ARGB &c2)
{
   ARGB  res;
   float x = 0.5f * (1.0 - c1.alpha + c2.alpha);
 
   res.alpha = c1.alpha * (1.0f - x) + x * c2.alpha; // <--- вот здесь))
   res.r = c1.r * (1.0f - x) + x * c2.r;
   res.g = c1.g * (1.0f - x) + x * c2.g;
   res.b = c1.b * (1.0f - x) + x * c2.b;
   return res;
}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.232 секунд. Запросов: 23.