SR2D: Разные вопросы

Работа с 2D и 3D графикой, видео, звуком.

Модератор: Mikle

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

SR2D: Разные вопросы

Сообщение arthur2 » 01.07.2019 (Пн) 7:23

Mikle
Есть серая маска, символизирующая альфа-канал. Как её наложить на существующую картинку. И обратная операция - есть картинка с альфа-каналом - как выделить серую картинку, пиксели которой символизировали бы альфа-канал? Можно просто перебором, но мне кажется, что что-то подобное уже встроено?

И как лучше - все вопросы по SR2D складывать в одну тему или лучше для каждого вопроса создать свою?
Последний раз редактировалось arthur2 28.07.2019 (Вс) 9:18, всего редактировалось 1 раз.
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение Mikle » 01.07.2019 (Пн) 8:35

arthur2 писал(а):Есть серая маска, символизирующая альфа-канал. Как её наложить на существующую картинку.

То есть сделать, чтобы пиксели с заданным цветом стали прозрачными? Если я верно понял вопрос, то тебе нужен метод AddColorKey.
arthur2 писал(а):обратная операция - есть картинка с альфа-каналом - как выделить серую картинку, пиксели которой символизировали бы альфа-канал?

Тут лучше всего подойдёт MaskClearBuffer:
Код: Выделить всё
SprBack.MaskClearBuffer SprA, 0, 0, Color, ARGB(128, 0, 0, 0), NotMask

SprA - исходный спрайт с альфаканалом.
Color - цвет, которым закрашиваем.
Чтобы закрасить SprBack там, где в SprA непрозрачные участки, NotMask = False или вообще пропускаем. Чтобы прозрачные NotMask = True.
arthur2 писал(а):все вопросы по SR2D складывать в одну тему или лучше для каждого вопроса создать свою?

Если небольшие вопросы, типа этих, то можно всё спрашивать в одной (этой) теме.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение arthur2 » 01.07.2019 (Пн) 8:53

Не, я имею ввиду постепенное изменение прозрачности. Есть серая 8-битная картинка массивом байтов, каждый из которых символизирует А в АRGB.
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение Mikle » 01.07.2019 (Пн) 9:11

Можно любой цветовой канал перемещать между спрайтами:
Код: Выделить всё
Spr1.MoveByte Spr2, 0, 0, ChRed, ChAlpha

Красный канал спрайта Spr2 помещается в альфаканал спрайта Spr1.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение arthur2 » 01.07.2019 (Пн) 9:21

Круто!!!
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение arthur2 » 01.07.2019 (Пн) 9:25

А если у картинок разные размеры, это сработает? И если маска меньше картинки, какими тогда станут не перекрытые маской области?
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение Mikle » 01.07.2019 (Пн) 11:57

Картинки могут быть разных размеров, метод сработает только для перекрывающейся части с учётом входных параметров-координат, например, так:
Изображение
Это касается всех методов SR2D, оперирующих двумя или тремя спрайтами. Исключение, вполне понятное - SRCCol в DrawEBM.
Неперекрытые области не меняются.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Как непрозрачной картинке добавить альфа-маску?

Сообщение arthur2 » 01.07.2019 (Пн) 19:35

Огромное спасибо! И за объяснение, и особенно за саму библиотеку :)
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Есть ли возможность сделать серую картинку?

Сообщение arthur2 » 28.07.2019 (Вс) 9:23

Есть ли возможность сделать серую картинку?

Понятно, что можно сделать перебором пикселей (кстати, какой алгоритм предпочтительней - просто для каждого пикселя среднее арифметическое от R, G, и B?)

Вопрос, есть ли встроенный вариант?
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 28.07.2019 (Вс) 11:25

arthur2 писал(а):просто для каждого пикселя среднее арифметическое от R, G, и B

Более правильно так:
Код: Выделить всё
  Col = ((B * 28 + G * 150 + R * 77) \ 255) * &H10101

В SR2D нет специального способа, но можно сделать с небольшой потерей точности так:
Код: Выделить всё
  Spr.MulAddS2X Spr, 0, 0, ARGB(0, 64, 64, 64), ARGB(0, 192, 192, 192)
  Spr.DrawDPBM Spr, 0, 0, 77, 150, 28, 0.675

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Разные вопросы

Сообщение arthur2 » 28.07.2019 (Вс) 13:02

Mikle писал(а):Более правильно так
А в чем тут математический принцип, что именно делает формула?

Mikle писал(а):но можно сделать с небольшой потерей точности так
А как это работает?
С помощью метода MulAddS2X можно изменять яркость и контрастность. Значение из источника
умножается покомпонентно на параметр Mul, к произведению добавляется значение Add, далее из
него вычитается 128 (как будто Add - число со знаком) и полученная величина умножается на 2.
Здесь 64- это на сколько каждый из RGB становится ярче, а 192 - контрастней? Точнее, наверное, 64 - это -64, а 192 - это +64, так?
DrawDPBM - это мы картинку как бы освещаем?
Попробовал так (fn - это спрайт фона):
Код: Выделить всё
s.MulAddS2X s, 0, 0, ARGB(0, 64, 64, 64), ARGB(0, 192, 192, 192)
s.DrawDPBM s, 0, 0, 77, 150, 28, 0.675
fn.Draw s, 0, 0, OpAlphaBlend
fn.PaintToDevice hdc
Получил вроде черно-белую, но полупрозрачную картинку.
Попробовал так:
Код: Выделить всё
s.MulAddS2X s, 0, 0, ARGB(0, 64, 64, 64), ARGB(0, 192, 192, 192)
fn.DrawDPBM s, 0, 0, 77, 150, 28, 0.675
fn.PaintToDevice hdc
Да, картинка черно-белая. Но так не рисуется альфа-канал.
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Разные вопросы

Сообщение arthur2 » 28.07.2019 (Вс) 13:32

Послеs.MulAddS2X s, 0, 0, ARGB(0, 64, 64, 64), ARGB(0, 192, 192, 192) - альфа-канал, я так понимаю, обнуляется?
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 28.07.2019 (Вс) 13:37

arthur2 писал(а):DrawDPBM - это мы картинку как бы освещаем?

Да, но освещение, использующее нормали и вектор света, совпадает по формуле с нужной нам - сумма трёх произведений.
arthur2 писал(а):Здесь 64- это на сколько каждый из RGB становится ярче, а 192 - контрастней?

Вектора используют числа со знаком, а у нас - без знака. Мы просто упаковывает байт из диапазона 0..255 в диапазон 128..255, чтобы число подходило к DPBM, скалярному произведению векторов.
arthur2 писал(а):А в чем тут математический принцип, что именно делает формула?

Учитывает весовые коэффициенты компонентов. Синий полной яркости темнее, чем красный, и обе темнее, чем зелёный.
arthur2 писал(а):Но так не рисуется альфа-канал.

А нужно было?
Просто перекинь любой канал из RGB (они теперь одинаковые) в альфу с помощью MoveByte.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 28.07.2019 (Вс) 13:39

arthur2 писал(а):Послеs.MulAddS2X s, 0, 0, ARGB(0, 64, 64, 64), ARGB(0, 192, 192, 192) - альфа-канал, я так понимаю, обнуляется?

Да. Можно написать так, чтобы не изменился:
Код: Выделить всё
ARGB(128, 64, 64, 64), ARGB(128, 192, 192, 192)

Но перед DPBM это не имеет смысла.
Опиши полностью задачу.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Разные вопросы

Сообщение arthur2 » 28.07.2019 (Вс) 15:49

Mikle писал(а):Учитывает весовые коэффициенты компонентов.
Понял :)
Mikle писал(а):Да, но освещение, использующее нормали и вектор света, совпадает по формуле с нужной нам

Получается, что освещение работает по формуле Col = ((B * Lz+ G * Ly+ R * Lx) \ 255) * &H10101 ?

Mikle писал(а):Вектора используют числа со знаком
Ага, догадался, после того, как послал вопрос. И даже пост исправил. Но, кажется, понял не совсем :) Картинка становится менее яркой (-64), но более контрастной (+64)? Или наоборот?
Mikle писал(а):Просто перекинь любой канал из RGB (они теперь одинаковые) в альфу с помощью MoveByte
Это будет не оригинальный альфа-канал. Я, как догадался, что альфа обнуляется, сделал, сохранив изначальный альфа-канал во временный спрайт.
Mikle писал(а):Опиши полностью задачу.
Ну, полностью задача ещё не сформировалась :) Пока примеряюсь, как использовать то, до чего удаётся дотянуться пониманием.
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 28.07.2019 (Вс) 16:39

arthur2 писал(а):Картинка становится менее яркой (-64), но более контрастной (+64)? Или наоборот?

Наоборот.
arthur2 писал(а):Получается, что освещение работает по формуле Col = ((B * Lz+ G * Ly+ R * Lx) \ 255) * &H10101 ?

Скорее, так:
Код: Выделить всё
Brite = N.z * L.z+ N.y * L.y+ N.x * L.x

Где N иL - нормализованные вектора нормали и направления на источник света.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Разные вопросы

Сообщение arthur2 » 28.07.2019 (Вс) 22:31

Mikle писал(а):Где N иL - нормализованные вектора нормали и направления на источник света.
А где про это почитать? В других темах встретил:
Mikle писал(а):Я это более-менее подробно в книге описывал.
А что за книга? Где её можно посмотреть? По форуму не нашел
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: SR2D: Разные вопросы

Сообщение arthur2 » 28.07.2019 (Вс) 22:51

Со знаковым байтом я как-то вроде что-то напутал и недопонял.
H80=-128
Hff=-1
Так? Значит, моё
arthur2 писал(а):наверное, 64 - это -64, а 192 - это +64, так?
неправильно. А правильно, что 64 так +64и есть, а вот 192 как раз -64. Так?
Артур
 
   

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 29.07.2019 (Пн) 9:38

arthur2 писал(а):что за книга?

Первая тема в этом разделе.
arthur2 писал(а):где про это почитать?

Это стандартный Diffuse Light.
H80=-128
Hff=-1

Нет. В байтах обычно применяют другой принцип:
Код: Выделить всё
UnSigned:    0 127 128 255
Signed  : -128  -1   0 127

По крайней мере так кодируются вектора через цвет в D3D. Точнее, при переводе знакового байта в float ещё идёт деление на 128.

С.Т.
Начинающий
Начинающий
 
Сообщения: 3
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D: Разные вопросы

Сообщение С.Т. » 17.04.2023 (Пн) 20:05

Вот настоящий инструмент! Сейчас, найдя SR2D, переписываю на него всю программу (раньше в ней использовал AlphaImgCtl и AlphaShape, но когда много изображений на форме, она тормозит до такой степени, что при любом изменении (к примеру масштаба) пользователю приходится реально ждать, даже если убрать видимость элемента-приёмника на время его загрузки).

SR2D - чудо! Всё просто, быстро, понятно, очень мало кто из программистов умеет держать этот баланс - простоты, эффективности, быстродействия и богатства возможностей. Всё по максимуму!

Для удобства я добавил в SR2D_Sprite.cls множество функций, например покажу одну из них - наложение на спрайт цветового градиента из заданных цветов (включая градиент прозрачности) :
Код: Выделить всё
       
Sub DrawGradient(cARGB1 As Long, cARGB2 As Long, Optional Vert As Boolean, Optional Left As Long, Optional Top As Long, Optional Width As Long, Optional Height As Long, Optional IsXor As Boolean)
    If meWidth = 0 Or meHeight = 0 Then
        Init Width, Height
    Else
        If Width = 0 Then Width = meWidth
        If Height = 0 Then Height = meHeight
    End If
    If Vert Then
        For i = 0 To Height
            DrawLine Left, i + Top, Left + Width, i + Top, ColLerp(cARGB2, cARGB1, i / Height), , IsXor
        Next
    Else
        For i = 0 To Width
            DrawLine Left + i, Top, Left + i, Height + Top, ColLerp(cARGB2, cARGB1, i / Width), , IsXor
        Next
    End If
End Sub
        Private Function ColLerp(ByVal c1 As Long, ByVal c2 As Long, ByVal k As Single) As Long
            Dim A As Integer, R As Integer, G As Integer, B As Integer, a1plus As Long, a2plus As Long
            'Подправляем сбой на минус лонг при A>127:
                If c1 < 0 Then 'значит, A>127 и, как следствие, Long отрицательный
                    c1 = c1 + 2147483647 + 1& 'прибавляем МаксЛонг, который вообще-то есть половина действит.макса (столько же ниже нуля)
                    a1plus = 128&
                End If
                If c2 < 0 Then 'значит, A>127 и, как следствие, Long отрицательный
                    c2 = c2 + 2147483647 + 1& 'прибавляем МаксЛонг, который вообще-то есть половина действит.макса (столько же ниже нуля)
                    a2plus = 128&
                End If
            'Составляем цвет из двух:
                A = (((c1 \ 16777216) And 255&) + a1plus) * k + (((c2 \ 16777216) And 255&) + a2plus) * (1 - k)
                R = ((c1 \ 65536) And 255&) * k + ((c2 \ 65536) And 255&) * (1 - k)
                G = ((c1 \ 256&) And 255&) * k + ((c2 \ 256&) And 255&) * (1 - k)
                B = (c1 And 255&) * k + (c2 And 255&) * (1 - k)
                ColLerp = ARGB(A, R, G, B)
        End Function

                   

ColLerp я взял тоже из Ваших ответов кому-то, но подправил его для длинного Long ARGB, который выходит за рамки положительного числа и потому требует коррекции. Наверно, это можно было сделать грамотнее, но я не математик и сделал по интуиции.

А вопрос разрешите?
Я сделал функцию, по которой берётся изображение, выполненное в оттенках серого, и красится в выбранный цвет.
Получилось вот так:
Код: Выделить всё
            Public Sub DrawGreyColored(src As SR2D_Sprite, Optional ByVal A As Byte = 128, Optional ByVal R As Byte = 128, Optional ByVal G As Byte = 128, Optional ByVal B As Byte = 128, Optional Left As Long = 0, Optional Top As Long = 0, Optional И_ЗАПОМНИ As Enum_Draw = False, Optional Tag, Optional Tag2, Optional Tag3)
                'Спрайт src должен быть в серых тонах (тона вокруг RGB(128,128,128). На него накладывается цвет.
                If Height = 0 Or Width = 0 Then Init src.Width, src.Height
                MulAddS2X src, Left, Top, ARGB(255 - A, 255 - R, 255 - G, 255 - B), ARGB(A, R, G, B)
               
                If И_ЗАПОМНИ Then Проверь_запоминание src, Tag, Tag2, Tag3
            End Sub


Она работает, действительно засвечивает изображение нужным цветом. Но! Проблема с альфа-каналом. Во-первых, цвета-то он усредняет, а вот альфа-канал нет. Если я хочу задать изображению нужную прозрачность, то такая функция не работает, и я не смог её запустить спонтанными подправками. Во-вторых, если применить эту функцию к спрайту, который нарисован уже ею же, т.е. уже расцвеченный, то при вторичном изменении его цвета меняется и альфа-канал, например пропадает прозрачность (появляется фон) и т.д. В общем, не могу разобраться с альфа-каналом, может можно сделать функцию объединения цветов иначе?

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D: Разные вопросы

Сообщение Mikle » 17.04.2023 (Пн) 20:55

Сильно пока не смотрел, навскидку - заменить эту строку:
Код: Выделить всё
MulAddS2X src, Left, Top, ARGB(255 - A, 255 - R, 255 - G, 255 - B), ARGB(A, R, G, B)

на такую:
Код: Выделить всё
MulAddS2X src, Left, Top, ARGB(128, 255 - R, 255 - G, 255 - B), ARGB(128, R, G, B)

Это чтобы сохранить прозрачность исходника без изменений.

С.Т.
Начинающий
Начинающий
 
Сообщения: 3
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D: Разные вопросы

Сообщение С.Т. » 18.04.2023 (Вт) 9:15

Нашёл!
Код: Выделить всё
MulAddS2X src, Left, Top, ARGB(128, 255 - R, 255 - G, 255 - B), ARGB(A, R, G, B)

Контрастность альфа-канала менять нельзя - только яркость. Тогда всё работает, и прозрачность отлично регулируется по всему диапазону!
Как только меняешь Mul именно альфа-канала, при дальнейшем наложении происходят непонятные мне вещи. Просто не делать этого, и всё.
Огромное спасибо! Какой-то волшебный инструмент! Два-три слова - и он понимает!

По ходу развития программы дорабатываю и движок, точней его классовую оболочку, потом выложу!


Вернуться в Мультимедиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList  
cron