Что нового

Плавный переход от одного цвета к другому

musicstashall

Знающий
Сообщения
322
Репутация
7
Всем доброго.
Хотел реализовать функцию для плавного изменения цвета и понял, что не так просто. Сделал тупо и получилось что-то не то:
Код:
Global $GUI = GUICreate('', 200, 200)
GUISetState()
GUISetBkColor(0x0093BC, $GUI)
For $i = 0x0093BC To 0x7F4200 Step 12
   ;ConsoleWrite($i&@CR)
   GUISetBkColor('0x'&Hex($i, 6), $GUI)
Next


Кто знает, поделитесь пожалуйста. Мне нужно получать непосредственно промежуточные числа цвета (например в 100 шагов), а не рисовать на окне, поэтому GDIP наверное не подойдет, хотя рассмотрю любые варианты.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Для улучшения визуального восприятия увеличьте шаг и добавьте задержку
Код:
Global $GUI = GUICreate('', 200, 200)
GUISetState()
GUISetBkColor(0x0093BC, $GUI)
For $i = 0x0093BC To 0x7F4200 Step 500
   ConsoleWrite('0x'&Hex($i, 6)&@CR)
   GUISetBkColor($i, $GUI)
   If GUIGetMsg() = -3 Then Exit
   Sleep(111)
Next


А если нужно изменение "по радуге", то вы уже спрашивали здесь: https://www.autoitscript.com/forum/topic/189130-colorization-custom-sliders/
Код:
GUICreate("", 200, 200)
GUISetState()
For $h = 0 To 360
    $iRGB = HSLToRGB($h / 360, 1, 0.5)
    GUISetBkColor($iRGB)
    ConsoleWrite(Hex($iRGB) & @CRLF)
    If GUIGetMsg() = -3 Then Exit
    Sleep(11)
Next

Func HSLToRGB($h, $s, $l)
    If Not $s Then Return BitShift(0xFF * $l, -16) + BitShift(0xFF * $l, -8) + BitShift(0xFF * $l, 0)
    Local Const $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s
    Local Const $p = 2 * $l - $q
    Return BitShift(0xFF * HUEtoRGB($p, $q, $h - 0.33333333), -16) + BitShift(0xFF * HUEtoRGB($p, $q, $h), -8) + BitShift(0xFF * HUEtoRGB($p, $q, $h + 0.33333333), 0)
EndFunc

Func HUEtoRGB($p, $q, $t)
    If($t < 0) Then $t += 1
    If($t > 1) Then $t -= 1
    If($t < 0.16666666) Then Return $p + ($q - $p) * 6 * $t
    If($t < 0.5) Then Return $q
    If($t < 0.66666666) Then Return $p + ($q - $p) * (0.66666666 - $t) * 6
    Return $p
EndFunc
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Для улучшения визуального восприятия увеличьте шаг и добавьте задержку

Как-то грубо получается, цвет прыгает. Сначала плавно меняется, а потом прыжок и цвет резко другой. Наверное, в такой схеме движение в RGB кубе не линейное получается.

А если нужно изменение "по радуге", то вы уже спрашивали

О, я спрашивал совсем другие вещи :smile: Здесь вы показали изменение только по шкале оттенка, а мне нужно получить схему преобразования цвета во всех его параметрах: H, S, L — движение точки внутри RGB куба. По сути, нужна формула. Сейчас опять начну изобретать, а потом окажется, что это всегда было :laugh:
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
musicstashall [?]
Сначала плавно меняется, а потом прыжок и цвет резко другой
И это правильно. Вот смотрите.
В десятичной системе: 205 + 100 = 305
В шестнадцатеричной: 0x0000CD + 0x000064 = 0x000131
В "цветах": к ярко синему прибавили шаг 100 и получили почти чёрный ;)

движение точки внутри RGB куба
Разложите цвет на компоненты RGB. Переместите точку. Пересчитайте компоненты. Сложите компоненты в новый цвет.
Фактически, это похоже на выбор цвета в диалоге цветов путём ручного ввода компонентов.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Разложите цвет на компоненты RGB. Переместите точку. Пересчитайте компоненты. Сложите компоненты в новый цвет.
Фактически, это похоже на выбор цвета в диалоге цветов путём ручного ввода компонентов.

Я так и думал, придется опять заниматься математикой :smile:


Добавлено:
Сообщение автоматически объединено:

Ну вот, если «топором», то так:

Код:
#include <Color.au3>
#include <Array.au3>

Global $GUI = GUICreate('', 200, 200)
GUISetState()

_FlowColor(0x426D79, 0x5C4124, 100, 1, 'GUISetBkColor')

Func _FlowColor($Color1, $Color2, $_To, $_Sleep, $_Func)
   Local $Color, $_Rmax, $_Rmin = 0, $_Gmax, $_Gmin = 0, $_Bmax, $_Bmin = 0
   Local $RGB1 = _ColorGetRGB($Color1)
   Local $RGB2 = _ColorGetRGB($Color2)
   Local $RGB[2][3] = [[$RGB1[0], $RGB1[1], $RGB1[2]], [$RGB2[0], $RGB2[1], $RGB2[2]]]
   $_Rmax = _ArrayMaxIndex($RGB, 1, -1, -1, 0)
   If $_Rmax = 0 Then $_Rmin = 1
   $_Gmax = _ArrayMaxIndex($RGB, 1, -1, -1, 1)
   If $_Gmax = 0 Then $_Gmin = 1
   $_Bmax = _ArrayMaxIndex($RGB, 1, -1, -1, 2)
   If $_Bmax = 0 Then $_Bmin = 1
   $_R_step = ($RGB[$_Rmax][0] - $RGB[$_Rmin][0])/$_To
   If $_Rmax = 0 Then $_R_step = - $_R_step
   $_G_step = ($RGB[$_Gmax][1] - $RGB[$_Gmin][1])/$_To
   If $_Gmax = 0 Then $_G_step = - $_G_step
   $_B_step = ($RGB[$_Bmax][2] - $RGB[$_Bmin][2])/$_To
   If $_Bmax = 0 Then $_B_step = - $_B_step
   For $i = 1 To $_To
	  $R = $RGB[0][0] + $_R_step*$i
	  $G = $RGB[0][1] + $_G_step*$i
	  $B = $RGB[0][2] + $_B_step*$i
	  $Color = '0x'&StringFormat("%02X%02X%02X", Int($R), Int($G), Int($B))
	  Call($_Func, $Color)
	  Sleep(Int($_Sleep))
   Next
EndFunc
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Так меньше кода
Код:
Func _FlowColor($Color1, $Color2, $_To, $_Sleep, $_Func)
   Local $RGB1 = _ColorGetRGB($Color1)
   Local $RGB2 = _ColorGetRGB($Color2)
   Local $_R_step = ($RGB1[0] - $RGB2[0]) / $_To
   Local $_G_step = ($RGB1[1] - $RGB2[1]) / $_To
   Local $_B_step = ($RGB1[2] - $RGB2[2]) / $_To
   For $i = 1 To $_To
      $RGB1[0] -= $_R_step
      $RGB1[1] -= $_G_step
      $RGB1[2] -= $_B_step
      Call($_Func, Dec(StringFormat("%02X%02X%02X", $RGB1[0], $RGB1[1], $RGB1[2])))
      Sleep($_Sleep)
   Next
EndFunc


Только сейчас понял, о чём вы хотели спросить :smile:
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Код:
Local $_R_step = ($RGB1[0] - $RGB2[0]) / $_To
Local $_G_step = ($RGB1[1] - $RGB2[1]) / $_To
Local $_B_step = ($RGB1[2] - $RGB2[2]) / $_To


А разве не важно, чтобы находить разницу между бо́льшим и меньшим значением, вычитая из бо́льшего меньшее? Но ведь работает :laugh: Удивительно
Ах, ну да, понятно. Знак то меняется потом. Спс
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Еще усовершенствовал, сделал для многих цветов одновременно:

Код:
#include <Color.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>
Global $MATRIX[0][2], $__To = 0

Global $hGUI = GUICreate('', 300, 100)
Global $lab1 = GUICtrlCreateLabel('', 0, 0, 100, 100)
GUICtrlSetBkColor(-1, 0xf8640c)
Global $index1 = _AddColorsToMatrix(0xf8640c, 0x00ae57, 100)
Global $lab2 = GUICtrlCreateLabel('', 100, 0, 100, 100)
GUICtrlSetBkColor(-1, 0x0046ff)
Global $index2 = _AddColorsToMatrix(0x0046ff, 0xf8640c, 100)
Global $lab3 = GUICtrlCreateLabel('', 200, 0, 100, 100)
GUICtrlSetBkColor(-1, 0xd73539)
Global $index3 = _AddColorsToMatrix(0xd73539, 0x0000ff, 100)
GUISetState(@SW_SHOW, $hGUI)

_RunFlowMatrix('Flow', 50)

Func Flow($Color)
   ConsoleWrite($Color[$index1]&', '&$Color[$index2]&', '&$Color[$index3]&@CR)
   GUICtrlSetBkColor($lab1, $Color[$index1])
   GUICtrlSetBkColor($lab2, $Color[$index2])
   GUICtrlSetBkColor($lab3, $Color[$index3])
EndFunc

While 1
   Switch GUIGetMsg()
	  Case $GUI_EVENT_CLOSE
			ExitLoop

   EndSwitch
WEnd


Func _AddColorsToMatrix($Color1, $Color2, $_To)
	Local $RGB1 = _ColorGetRGB($Color1)
	Local $RGB2 = _ColorGetRGB($Color2)
	Local $_step[3]
	$__To = $_To
	For $i = 0 To 2
		$_step[$i] = ($RGB1[$i] - $RGB2[$i]) / $__To
	Next
	Return _ArrayAdd($MATRIX, _ArrayToString($RGB1)&'::'&_ArrayToString($_step), Default, '::')
EndFunc

Func _RunFlowMatrix($__Func, $_Sleep)
	Local $_Color[0], $_RGB, $_step
	For $i = 0 To $__To
		For $a = 0 To UBound($MATRIX) - 1
			$_RGB = StringSplit($MATRIX[$a][0], '|', $STR_NOCOUNT)
			$_step = StringSplit($MATRIX[$a][1], '|', $STR_NOCOUNT)
			For $j = 0 To 2
				$_RGB[$j] -= $_step[$j]
				If $_RGB[$j] < 0 Then $_RGB[$j] = 0
				If $_RGB[$j] > 255 Then $_RGB[$j] = 255
			Next
			$MATRIX[$a][0] = _ArrayToString($_RGB)
			_ArrayAdd($_Color, '0x'&StringFormat("%02X%02X%02X", Int($_RGB[0]), Int($_RGB[1]), Int($_RGB[2])))
		Next
		Call($__Func, $_Color)
		Sleep($_Sleep)
		Dim $_Color[0]
	Next
	Dim $MATRIX[0][2], $__To = 0
EndFunc
 
Верх