It is currently March 28th, 2024, 11:01 am

Color Manipulation code

Discuss the use of Lua in Script measures.
Post Reply
DollarD
Posts: 16
Joined: March 2nd, 2013, 5:56 pm

Color Manipulation code

Post by DollarD »

Since I so egregiously abused lua for what is a simple regex adjustment, here's some actual code I use in my skins to get contrasting colors against a background. Essentially HexRGB to HSL, the adjust, then back.

To randomize the colors a bit, I have this measure in the skin:

Code: Select all

[MeasureColorizerRandom]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=0
HighBound=100
UpdateDivider=-1
And then, my a bit more worthy lua addition than previously:

Code: Select all

function Initialize()
	
	-- Constants
	ColorGranularity = 1 -- digits after decimal
	
	-- Fix Constants :)
	ColorGranularity = math.pow(10, 1)
	
end

function Update()
	local Config = " * "
	
	-- Rainmeter Data
	ColorMain = tostring(SKIN:GetVariable('ColorMain', '262524'))
	WinBG = SKIN:GetMeasure('MeasureSplitPaletteBG'):GetStringValue()
	WinAcc = SKIN:GetMeasure('MeasureSplitSysColor'):GetStringValue()
	RandomHue = SKIN:GetMeasure('MeasureColorizerRandom'):GetValue()
	
	if WinBG == '' then return end
	
	-- Reticulating Splines
	
	ColorBG = string.sub(WinBG, 1,6)
	ColorMain = ContrastColor(ColorBG) .. ""
	ColorMainAcc = WinAcc
	
	ColorMainShd = ShadeColor(ColorMain, 0.5)
	ColorMainTnT = TintColor(ColorMain, 0.5)
	
	ColorMainAcc = TintColor(WinAcc, 0.5)
	ColorMainAlt = ColorCpl(ColorMain)
	
	-- Save Data
	SKIN:Bang('!WriteKeyValue Variables ColorBG      "' .. string.upper(ColorBG)        .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorMain    "' .. string.upper(ColorMain)      .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorCplA    "' .. string.upper(ColorMainAcc)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorCplB    "' .. string.upper(ColorMainAlt)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorShade   "' .. string.upper(ColorMainShd)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorTint    "' .. string.upper(ColorMainTnT)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	
	SKIN:Bang('!SetVariable ColorBG      "' .. string.upper(ColorBG)       .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorMain    "' .. string.upper(ColorMain)     .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorCplA    "' .. string.upper(ColorMainAcc)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorCplB    "' .. string.upper(ColorMainAlt)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorShade   "' .. string.upper(ColorMainShd)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorTint    "' .. string.upper(ColorMainTnT)  .. '" ' .. Config)
	
	return
end

function ContrastColor(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	if H == 0 then H = RandomHue * 3.6
		else
		H = (360 + (H - 15 + (RandomHue * 3 / 10))) % 360
	end
	S = 1 - (S * 0.4)
	L = 0.75 - (L * 0.5)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function ColorCpl(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	local AltHue = 50 - RandomHue
	
	if AltHue > 0 then H = (360 + H + (135 + (AltHue * 30 / 50))) % 360
		elseif AltHue < 0 then H = (360 + H + (225 + (AltHue * 30 / 50))) % 360
		else H = (180 + (H - 15 + (RandomHue * 3 / 10))) % 360
	end
	S = S 
	L = L 
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function ShadeColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	H = H
	S = S 
	L = L - (L * Factor)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function TintColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	H = H
	S = S 
	L = L + ((1 - L) * Factor)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function HexToRGB(HexString)
	
	local R = tonumber( "0x" .. string.sub(HexString, 1,2) ) / 255
	local G = tonumber( "0x" .. string.sub(HexString, 3,4) ) / 255
	local B = tonumber( "0x" .. string.sub(HexString, 5,6) ) / 255
	
	return R, G, B
	
end

function RGBToHex(R, G, B)
	
	local R = math.max(math.min(math.floor(R * 255), 255), 0)
	local G = math.max(math.min(math.floor(G * 255), 255), 0)
	local B = math.max(math.min(math.floor(B * 255), 255), 0)
	
	local HexR = string.format("%02X", R) .. ""
	local HexG = string.format("%02X", G) .. ""
	local HexB = string.format("%02X", B) .. ""
	
	return HexR .. HexG .. HexB
	
end

function RGBToHSV(R, G, B)
	
	local H, S, V, Delta	
	local MAX = math.max(R, G, B)
	local MIN = math.min(R, G, B)
	
	V = MAX
	Delta = MAX - MIN
	
	if MAX ~= 0 then S = Delta / MAX
		else     S = 0
	end
	
	if Delta == 0 then
		H = 0
		else
		if     MAX == R then H = ((G - B) / Delta) % 6
			elseif MAX == G then H = 2 + (B - R) / Delta
			else 		     H = 4 + (R - G) / Delta
		end		
	end
	
	H = H * 60
	
	if H < 0 then H = H + 360 end
	
	-- Granularity
	
	H = math.floor( H * (ColorGranularity)       ) / (ColorGranularity)
	S = math.floor( S * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	V = math.floor( V * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return H, S, V
	end
	
	function HSVToRGB(H, S, V)
		
		local R, G, B
		
		local C = V * S
		local X = C * (1 - math.abs(((H / 60) % 2) - 1))
		local m = V - C
		
		local Hi = math.floor(H / 60)
		
		if Hi == 0 then     R, G, B = C, X, 0
			elseif Hi == 1 then R, G, B = X, C, 0
			elseif Hi == 2 then R, G, B = 0, C, X
			elseif Hi == 3 then R, G, B = 0, X, C
			elseif Hi == 4 then R, G, B = X, 0, C
			elseif Hi == 5 then R, G, B = C, 0, X
		end
		
		R, G, B = R + m, G + m, B + m
		
		-- Granularity
		
		R = math.floor( R * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
		G = math.floor( G * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
		B = math.floor( B * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
		
		return R, G, B
		
		end
		
		function RGBToHSL(R, G, B)
			
			local H, S, L, Delta	
			local MAX = math.max(R, G, B)
			local MIN = math.min(R, G, B)
			
			Delta = MAX - MIN
			
			L = (MAX + MIN) / 2
			
			if Delta == 0 then
				H, S = 0, 0
				else
				S = Delta / (1 - math.abs((L * 2) - 1))
				if     MAX == R then H = ((G - B) / Delta) % 6
					elseif MAX == G then H = 2 + (B - R) / Delta
					else 		     H = 4 + (R - G) / Delta
				end		
			end
			
			H = H * 60
			
			if H < 0 then H = H + 360 end
			
			-- Granularity
			
			H = math.floor( H * (ColorGranularity)       ) / (ColorGranularity)
			S = math.floor( S * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
			L = math.floor( L * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
			
			return H, S, L
			
		end
		
		function HSLToRGB(H, S, L)
			
			local R, G, B
			
			local C = (1 - math.abs((L * 2) - 1)) * S
			local X = C * (1 - math.abs(((H / 60) % 2) - 1))
			local m = L - C / 2
			
			local Hi = math.floor(H / 60)
			
			if Hi == 0 then     R, G, B = C, X, 0
				elseif Hi == 1 then R, G, B = X, C, 0
				elseif Hi == 2 then R, G, B = 0, C, X
				elseif Hi == 3 then R, G, B = 0, X, C
				elseif Hi == 4 then R, G, B = X, 0, C
				elseif Hi == 5 then R, G, B = C, 0, X
			end
			
			R, G, B = R + m, G + m, B + m
			
			-- Granularity
			
			R = math.floor( R * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
			G = math.floor( G * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
			B = math.floor( B * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
			
			return R, G, B
			
		end
As you can see, I experimented with HSV a bit as well. Hopefully this is of use to someone.
DollarD
Posts: 16
Joined: March 2nd, 2013, 5:56 pm

Re: Color Manipulation code

Post by DollarD »

Here's an update to the lua script, along with a sample skin you can construct to take a look:

The lua script grabs the color as measured by SysColor and extracted from the registry, and outputs:

ColorBG - Background Color as per registry
ColorMain - A contrasting color to the background, via HSL color transformation and varying the hue by 15 degrees
ColorCplA - A complement of the accent color, via adjusting the HSL hue by +-30 to 60 degrees
ColorCplB - A complement of the accent color, via adjusting the HSL hue by +-135 to 165 degrees
ColorShade - A darker version of the contrating color, adjusted via Luminance in HSL
ColorTint - A lighter version of the contrating color, adjusted via Luminance in HSL

It also measures the background brightness via a HCY transformation, and brightens or darkens these colors so they can contrast properly.

Color functions included:
HexToRGB(HexString)
RGBToHex(R, G, B)
RGBToHSV(R, G, B)
HSVToRGB(H, S, V)
RGBToHSL(R, G, B)
HSLToRGB(H, S, L)
RGBToHCY(R, G, B)
HCYToRGB(H, C, Y)

I have a .inc file to save the calculated colors etc. so the other meters can simply load from there.

D10Variables.inc :

Code: Select all

[Variables]
FontSize=12
FontName="Segoe UI"
ColorBG=86AFC5
ColorMain=005489
ColorCplA=062C93
ColorCplB=99001E
ColorShade=002944
ColorTint=44B6FF
The base color control skin then uses the SysColor plugin to detect when the accent color changes, and fetches it from the registry via the RunCommand plugin as the Registry measure doesn't read binary registry entries. A regex then splits it into RGB and feeds it to the lua script.

D10Control.ini :

Code: Select all

[Rainmeter]
Update=1000
MiddleMouseDownAction=[!UpdateMeasure "MeasureColorizerRandom"][!CommandMeasure MeasurePaletteRegistry Run][!UpdateMeasure "MeasureColorScript"]
....................................................................................................................................................

[Variables]
@Include="#CURRENTPATH#D10Variables.inc"
IncFile="#CURRENTPATH#D10Variables.inc"

FromAlpha=FF
MidRAlpha=AF
MidLAlpha=9F
ToAlpha=00
........................................................................................................................................................

[MeasureColorizerRandom]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=0
HighBound=100
UpdateDivider=-1

[MeasureColorTrigger]
Measure=String
OnUpdateAction=[!UpdateMeasure "MeasureColorizerRandom"][!SetOption "MeasureSysColor" "UpdateDivider" "1"][!UpdateMeasure "MeasureSysColor"]
DynamicVariables=1
UpdateDivider=-1

[MeasureSysColor]
Measure=Plugin
Plugin=Plugin\SysColor.dll
ColorType=WIN8 
Hex=1
DisplayType=RGB
OnChangeAction=[!CommandMeasure MeasurePaletteRegistry Run]
DynamicVariables=1
UpdateDivider=-1

[MeasurePaletteRegistry]
Measure=Plugin
Plugin=Plugin\RunCommand.dll
Parameter=C:\Windows\System32\reg.exe query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent /v AccentPalette
OutputType=ANSI
FinishAction=[!UpdateMeasure "MeasureSplitPaletteBG"]
DynamicVariables=1
UpdateDivider=-1

[MeasureSplitPaletteBG]
Measure=String
String=[MeasurePaletteRegistry]
DynamicVariables=1
RegExpSubstitute=1
Substitute="(?siU).*REG_BINARY\s*([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2}).*":"\21\22\23"
; Select a palette entry from
; "\1\2\3\4 \5\6\7\8 \9\10\11\12 \13\14\15\16 \17\18\19\20 \21\22\23\24 \25\26\27\28 \29\30\31\32"
OnChangeAction=[!UpdateMeasure "MeasureColorScript"]
UpdateDivider=-1

[MeasureColorScript]
Measure=Script
ScriptFile=D10Color.lua
OnUpdateAction=[!SetOption "MeasureSysColor" "UpdateDivider" "-1"][!ActivateConfig "DDWin10\UpdRegistry"][!Redraw *] 
UpdateDivider=-1

.................................................................................................................................................................

[BackgroundRRight]
Meter=Image
SolidColor=#ColorBG##FromAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-200)
Y=0
W=(200 - 62)
H=(#SCREENAREAHEIGHT#-250)
DynamicVariables=1

[BackgroundRMid]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-375)
Y=0
W=175
H=(#WORKAREAHEIGHT#-250)
DynamicVariables=1

[BackgroundRLeft]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##ToAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-450)
Y=0
W=75
H=(#SCREENAREAHEIGHT#-250)
DynamicVariables=1

[BackgroundRightTop]
Meter=Image
SolidColor=#ColorBG##FromAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-250)
W=(200 - 62)
H=75
ImageAlpha=127
DynamicVariables=1
BevelType=

[BackgroundTopRight]
Meter=Image
SolidColor=#ColorBG##ToAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-250)
W=(200 - 62)
H=75
ImageAlpha=127
DynamicVariables=1

[BackgroundRightMid]
Meter=Image
SolidColor=#ColorBG##FromAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-175)
W=(200 - 62)
H=100
DynamicVariables=1
ImageAlpha=127
BevelType=

[BackgroundMidRight]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-175)
W=(200 - 62)
H=100
ImageAlpha=127
DynamicVariables=1

[BackgroundBigCurveLeftTop]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##ToAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-250)
W=75
H=75
DynamicVariables=1
ImageAlpha=127
;BevelType=1

[BackgroundBigCurveTopLeft]
Meter=Image
SolidColor=#ColorBG##ToAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-250)
W=75
H=75
ImageAlpha=127
DynamicVariables=1

[BackgroundBigCurveLeftMid]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##ToAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-175)
W=75
H=100
ImageAlpha=127
DynamicVariables=1
;BevelType=1

[BackgroundBigCurveMidLeft]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-175)
W=75
H=100
ImageAlpha=127
DynamicVariables=1

[BackgroundBigCurveTopMid]
Meter=Image
SolidColor=#ColorBG##ToAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-250)
W=175
H=75
DynamicVariables=1
ImageAlpha=127
;BevelType=1

[BackgroundBigCurveMidTop]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-250)
W=175
H=75
DynamicVariables=1
ImageAlpha=127
;BevelType=1

[BackgroundCornerMidR]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-175)
W=175
H=100
ImageAlpha=127
DynamicVariables=1
;BevelType=1

[BackgroundCornerMidB]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-175)
W=175
H=100
ImageAlpha=127
DynamicVariables=1
;BevelType=1

[BackgroundBTop]
Meter=Image
SolidColor=#ColorBG##ToAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=90
X=0
Y=(#SCREENAREAHEIGHT#-250)
W=(#SCREENAREAWIDTH#-450)
H=75
DynamicVariables=1

[BackgroundBMid]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=90
X=0
Y=(#SCREENAREAHEIGHT#-175)
W=(#SCREENAREAWIDTH#-450)
H=100
DynamicVariables=1

[BackgroundBBottom]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##FromAlpha#
GradientAngle=90
X=0
Y=(#SCREENAREAHEIGHT#-75)
W=(#SCREENAREAWIDTH#-450)
H=75
DynamicVariables=1

[BackgroundLeftBottom]
Meter=Image
SolidColor=#ColorBG##MidLAlpha#
SolidColor2=#ColorBG##ToAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-75)
W=75
H=75
ImageAlpha=127
DynamicVariables=1

[BackgroundBottomLeft]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##FromAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-450)
Y=(#SCREENAREAHEIGHT#-75)
W=75
H=75
DynamicVariables=1
ImageAlpha=127

[BackgroundMidBottom]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##MidLAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-75)
W=175
H=75
ImageAlpha=127
DynamicVariables=1


[BackgroundBottomMid]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##FromAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-375)
Y=(#SCREENAREAHEIGHT#-75)
W=175
H=75
DynamicVariables=1
ImageAlpha=127

[BackgroundCornerRightBottom]
Meter=Image
SolidColor=#ColorBG##FromAlpha#
SolidColor2=#ColorBG##MidRAlpha#
GradientAngle=180
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-75)
W=(200 - 62)
H=75
DynamicVariables=1
ImageAlpha=127

[BackgroundCornerBottomRight]
Meter=Image
SolidColor=#ColorBG##MidRAlpha#
SolidColor2=#ColorBG##FromAlpha#
GradientAngle=90
X=(#SCREENAREAWIDTH#-200)
Y=(#SCREENAREAHEIGHT#-75)
W=(200 - 62)
H=75
DynamicVariables=1
ImageAlpha=127

...................................................................................................................................................


D10Color.lua :

Code: Select all

function Initialize()
	
	-- Constants
	ColorGranularity = math.pow(10, 2)
	
end

function Update()
	local Config = " * "
	
	-- Rainmeter Data
	ColorMain = tostring(SKIN:GetVariable('ColorMain', '262524'))
	WinBG = SKIN:GetMeasure('MeasureSplitPaletteBG'):GetStringValue()
	WinAcc = SKIN:GetMeasure('MeasureSysColor'):GetStringValue()
	RandomHue = SKIN:GetMeasure('MeasureColorizerRandom'):GetValue()
	
	if WinBG == '' then return end
	
	-- Reticulating Splines
	
	ColorBG = string.sub(WinBG, 1,6)
	ColorMain = ContrastColor(ColorBG) .. ""
	ColorMainAcc = VaryColor(WinAcc)
	ColorMainAlt = ColorCpl(ColorMain)
	
	-- print("Before: " .. ColorBrightness(ColorBG) .. " " ..ColorBrightness(ColorMain) .. " " .. ColorBrightness(ColorMainAcc) .. " " .. ColorBrightness(ColorMainAlt))

	if ColorBrightness(ColorBG) < ColorBrightness(ColorMain   ) then
		ColorMain 	 = BrightColor(ColorMain, 	(0.375 - math.abs(ColorBrightness(ColorMain   ) - ColorBrightness(ColorBG))) / (1 - ColorBrightness(ColorMain   )))
		else                                        
		ColorMain 	 = DarkColor(ColorMain,     (0.375 - math.abs(ColorBrightness(ColorMain   ) - ColorBrightness(ColorBG))) / ColorBrightness(ColorMain   ))	
	end
	
	if ColorBrightness(ColorBG) < ColorBrightness(ColorMainAcc) then
		ColorMainAcc = BrightColor(ColorMainAcc,(0.375 - math.abs(ColorBrightness(ColorMainAcc) - ColorBrightness(ColorBG))) / (1 - ColorBrightness(ColorMainAcc)))
		else                                        
		ColorMainAcc = DarkColor(ColorMainAcc,  (0.375 - math.abs(ColorBrightness(ColorMainAcc) - ColorBrightness(ColorBG))) / ColorBrightness(ColorMainAcc))	
	end
	
	if ColorBrightness(ColorBG) < ColorBrightness(ColorMainAlt) then
		ColorMainAlt = BrightColor(ColorMainAlt,(0.375 - math.abs(ColorBrightness(ColorMainAlt) - ColorBrightness(ColorBG))) / (1 - ColorBrightness(ColorMainAlt)))
		else                                        
		ColorMainAlt = DarkColor(ColorMainAlt,  (0.375 - math.abs(ColorBrightness(ColorMainAlt) - ColorBrightness(ColorBG))) / ColorBrightness(ColorMainAlt))		
	end
	
	-- print("After: " .. ColorBrightness(ColorBG) .. " " ..ColorBrightness(ColorMain) .. " " .. ColorBrightness(ColorMainAcc) .. " " .. ColorBrightness(ColorMainAlt))
	
	ColorMainShd = ShadeColor(ColorMain, 0.5)
	ColorMainTnT = TintColor(ColorMain, 0.5)
	
	-- Save Data
	SKIN:Bang('!WriteKeyValue Variables ColorBG      "' .. string.upper(ColorBG)        .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorMain    "' .. string.upper(ColorMain)      .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorCplA    "' .. string.upper(ColorMainAcc)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorCplB    "' .. string.upper(ColorMainAlt)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorShade   "' .. string.upper(ColorMainShd)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	SKIN:Bang('!WriteKeyValue Variables ColorTint    "' .. string.upper(ColorMainTnT)   .. '" ' .. SKIN:ReplaceVariables(' #IncFile# '))
	
	SKIN:Bang('!SetVariable ColorBG      "' .. string.upper(ColorBG)       .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorMain    "' .. string.upper(ColorMain)     .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorCplA    "' .. string.upper(ColorMainAcc)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorCplB    "' .. string.upper(ColorMainAlt)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorShade   "' .. string.upper(ColorMainShd)  .. '" ' .. Config)
	SKIN:Bang('!SetVariable ColorTint    "' .. string.upper(ColorMainTnT)  .. '" ' .. Config)
	
	return
end

function ColorBrightness(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)

	local H, C, Y = RGBToHCY(R, G, B)
	
	-- print("RGB: " .. R .. " " .. G .. " " .. B .. " " .. Brightness)
	
	return Y
	
end

function ContrastColor(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	if H == 0 then H = RandomHue * 3.6
		else
		H = (360 + (H - 15 + (RandomHue * 3 / 10))) % 360
	end
	S = 1 - (S * 0.4)
	L = 0.75 - (L * 0.5)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function VaryColor(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	local AltHue = 50 - RandomHue
	local OffHue = math.max( AltHue / math.abs(AltHue), 0)
	
	AltHue = math.abs(AltHue)
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	if H == 0 then H = RandomHue * 3.6
		else
		H = ((H - 45 + (AltHue * 3 / 5)) + 60 * OffHue ) % 360
	end
	S = 1 - (S * 0.4)
	L = 0.75 - (L * 0.5)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function ColorCpl(ColorInputString)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	-- print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	local AltHue = 50 - RandomHue
	
	if AltHue > 0 then H = (360 + H + (135 + (AltHue * 30 / 50))) % 360
		elseif AltHue < 0 then H = (360 + H + (225 + (AltHue * 30 / 50))) % 360
		else H = (180 + (H - 15 + (RandomHue * 3 / 10))) % 360
	end
	S = S 
	L = L 
	
	-- print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function ShadeColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	H = H
	S = S 
	L = L - (L * Factor)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function TintColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, S, L = RGBToHSL(R, G, B)
	-- Contrast Calc
	
	--print("preHSL: " .. H .. " " .. S .. " " .. L)
	
	H = H
	S = S 
	L = L + ((1 - L) * Factor)
	
	--print("postHSL: " .. H .. " " .. S .. " " .. L)
	
	-- HSL to RGB
	R, G, B = HSLToRGB(H, S, L)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function BrightColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, C, Y = RGBToHCY(R, G, B)
	-- Contrast Calc
	
	-- print("BpreHCY: " .. H .. " " .. C .. " " .. Y)

	Y = Y + ((1 - Y) * math.min(math.max(Factor,0),1))
	
	-- print("BpostHCY: " .. H .. " " .. C .. " " .. Y .. " " .. math.min(math.max(Factor,0),1))
	
	-- HSL to RGB
	R, G, B = HCYToRGB(H, C, Y)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function DarkColor(ColorInputString, Factor)
	
	-- Hex to RGB
	local R, G, B = HexToRGB(ColorInputString)
	-- RGB to HSL
	local H, C, Y = RGBToHCY(R, G, B)
	-- Contrast Calc
	
	-- print("DpreHCY: " .. H .. " " .. C .. " " .. Y)

	Y = Y - (Y * math.min(math.max(Factor,0),1))
	
	-- print("DpostHCY: " .. H .. " " .. C .. " " .. Y .. " " .. math.min(math.max(Factor,0),1))
	
	-- HSL to RGB
	R, G, B = HCYToRGB(H, C, Y)
	-- And back
	local HexColor = RGBToHex(R, G, B)
	
	return HexColor
	
end

function HexToRGB(HexString)
	
	local R = tonumber( "0x" .. string.sub(HexString, 1,2) ) / 255
	local G = tonumber( "0x" .. string.sub(HexString, 3,4) ) / 255
	local B = tonumber( "0x" .. string.sub(HexString, 5,6) ) / 255
	
	return R, G, B
	
end

function RGBToHex(R, G, B)
	
	local R = math.max(math.min(math.floor(R * 255), 255), 0)
	local G = math.max(math.min(math.floor(G * 255), 255), 0)
	local B = math.max(math.min(math.floor(B * 255), 255), 0)
	
	local HexR = string.format("%02X", R) .. ""
	local HexG = string.format("%02X", G) .. ""
	local HexB = string.format("%02X", B) .. ""
	
	return HexR .. HexG .. HexB
	
end

function RGBToHSV(R, G, B)
	
	local H, S, V, Delta	
	local MAX = math.max(R, G, B)
	local MIN = math.min(R, G, B)
	
	V = MAX
	Delta = MAX - MIN
	
	if MAX ~= 0 then S = Delta / MAX
		else     S = 0
	end
	
	if Delta == 0 then
		H = 0
		else
		if     MAX == R then H = ((G - B) / Delta) % 6
			elseif MAX == G then H = 2 + (B - R) / Delta
			else 		     H = 4 + (R - G) / Delta
		end		
	end
	
	H = H * 60
	
	if H < 0 then H = H + 360 end
	
	-- Granularity
	
	H = math.floor( H * (ColorGranularity)       ) / (ColorGranularity)
	S = math.floor( S * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	V = math.floor( V * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return H, S, V
end

function HSVToRGB(H, S, V)
	
	local R, G, B
	
	local C = V * S
	local X = C * (1 - math.abs(((H / 60) % 2) - 1))
	local m = V - C
	
	local Hi = math.floor(H / 60)
	
	if Hi == 0 then     R, G, B = C, X, 0
		elseif Hi == 1 then R, G, B = X, C, 0
		elseif Hi == 2 then R, G, B = 0, C, X
		elseif Hi == 3 then R, G, B = 0, X, C
		elseif Hi == 4 then R, G, B = X, 0, C
		elseif Hi == 5 then R, G, B = C, 0, X
	end
	
	R, G, B = R + m, G + m, B + m
	
	-- Granularity
	
	R = math.floor( R * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	G = math.floor( G * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	B = math.floor( B * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return R, G, B
	
end

function RGBToHSL(R, G, B)
	
	local H, S, L, Delta	
	local MAX = math.max(R, G, B)
	local MIN = math.min(R, G, B)
	
	Delta = MAX - MIN
	
	L = (MAX + MIN) / 2
	
	if Delta == 0 then
		H, S = 0, 0
		else
		S = Delta / (1 - math.abs((L * 2) - 1))
		if     MAX == R then H = ((G - B) / Delta) % 6
			elseif MAX == G then H = 2 + (B - R) / Delta
			else 		     H = 4 + (R - G) / Delta
		end		
	end
	
	H = H * 60
	
	if H < 0 then H = H + 360 end
	
	-- Granularity
	
	H = math.floor( H * (ColorGranularity)       ) / (ColorGranularity)
	S = math.floor( S * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	L = math.floor( L * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	-- print("HSL: " .. H .. " " .. S .. " " .. L)
	
	return H, S, L
	
end

function HSLToRGB(H, S, L)
	
	local R, G, B
	
	local C = (1 - math.abs((L * 2) - 1)) * S
	local X = C * (1 - math.abs(((H / 60) % 2) - 1))
	local m = L - C / 2
	
	local Hi = math.floor(H / 60)
	
	if Hi == 0 then     R, G, B = C, X, 0
		elseif Hi == 1 then R, G, B = X, C, 0
		elseif Hi == 2 then R, G, B = 0, C, X
		elseif Hi == 3 then R, G, B = 0, X, C
		elseif Hi == 4 then R, G, B = X, 0, C
		elseif Hi == 5 then R, G, B = C, 0, X
	end
	
	R, G, B = R + m, G + m, B + m
	
	-- Granularity
	
	R = math.floor( R * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	G = math.floor( G * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	B = math.floor( B * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return R, G, B
	
end

function RGBToHCY(R, G, B)
	
	local H, C, Y, Delta	
	local MAX = math.max(R, G, B)
	local MIN = math.min(R, G, B)

	local Pr = 0.299
	local Pg = 0.587
	local Pb = 0.114
	
	Y = math.sqrt(R*R*Pr + G*G*Pg + B*B*Pb)
	
	Delta = MAX - MIN
	C = Delta
	
	if Delta == 0 then
		H, C = 0, 0
		else
		if     MAX == R then H = ((G - B) / Delta) % 6
			elseif MAX == G then H = 2 + (B - R) / Delta
			else 		     H = 4 + (R - G) / Delta
		end		
	end
	
	H = H * 60
	
	if H < 0 then H = H + 360 end
	
	-- Granularity
	
	H = math.floor( H * (ColorGranularity)       ) / (ColorGranularity)
	C = math.floor( C * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	Y = math.floor( Y * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return H, C, Y
	
end

function HCYToRGB(H, C, Y)
	
	local R, G, B
	
	local X = C * (1 - math.abs(((H / 60) % 2) - 1))
	
	local Pr = 0.299
	local Pg = 0.587
	local Pb = 0.114
	
	local Hi = math.floor(H / 60)
	
	if 		   Hi == 0 then R, G, B = C, X, 0
		elseif Hi == 1 then R, G, B = X, C, 0
		elseif Hi == 2 then R, G, B = 0, C, X
		elseif Hi == 3 then R, G, B = 0, X, C
		elseif Hi == 4 then R, G, B = X, 0, C
		elseif Hi == 5 then R, G, B = C, 0, X
	end
	
	local m = Y - math.sqrt(R*R*Pr + G*G*Pg + B*B*Pb)
	
	-- m = m - (m - (m * Y))
	
	-- print("PreRGB: " .. R .. " " .. G .. " " .. B .. " " .. Y .. " " .. m)
	
	R, G, B = R + m, G + m, B + m
	
	-- Granularity
	
	R = math.floor( R * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	G = math.floor( G * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	B = math.floor( B * (ColorGranularity) * 100 ) / (ColorGranularity * 100)
	
	return R, G, B
	
end
I also write back a color to the registry afterwards as the inactive window color.

UpdRegistry\UpdRegistry.ini :

Code: Select all

[Rainmeter]
Update=1000

....................................................................................................................................................

[Variables]
@Include="#CURRENTPATH#..\D10Variables.inc"

........................................................................................................................................................


[MeasureAccColor]
Measure=String
String=#ColorBG#
DynamicVariables=1
RegExpSubstitute=1
Substitute="(?siU)([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})":"C:\Windows\System32\reg.exe add HKCU\SOFTWARE\Microsoft\Windows\DWM /v AccentColorInactive /t REG_DWORD /d 0x00\3\2\1 /f"
OnUpdateAction=[!SetOption "MeasureAccColor" "UpdateDivider" "-1"][!CommandMeasure MeasureUpdateAccColor Run]
UpdateDivider=1

[MeasureUpdateAccColor]
Measure=Plugin
Plugin=Plugin\RunCommand.dll
Parameter=[MeasureAccColor]
OutputFile=c:\Root\RCDebug.txt
FinishAction=[!DeactivateConfig "DDWin10\UpdRegistry"]
;OutputType=ANSI
DynamicVariables=1
UpdateDivider=-1

[MeterDummy]
Meter=STRING
Text=""
Which allows me to inter alia place readable meters on that background such as this, using the calculated colors.

Time\Time.ini :

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
....................................................................................................................................................

[Variables]
@Include="#CURRENTPATH#..\D10Variables.inc"
XPos=0
YPos=0
WSize=300
HSize=200
.......................................................................................................................................................................

[MeasureDate]
Measure=Time
Format=%A, %#d %B, %Y
UpdateDivider=15

[Measure24HrTime]
Measure=Time
Format=%H:%M
UpdateDivider=15

[MeasureUptime]
Measure=Uptime
Format="%4!i! Days #CRLF# %3!i! Hours"
UpdateDivider=15

.......................................................................................................................................................................

[MeterTimeText]
Meter=STRING
MeasureName=Measure24HrTime
Text=%1
FontFace=#FontName#
FontColor=#ColorCplB#
FontSize=(#FontSize#+16)
;StringEffect=Shadow
;FontEffectColor=#ColorCplA#
StringStyle=Bold
AntiAlias=1
DynamicVariables=1
StringAlign=CenterBottom
X=(#XPos# + #WSize# / 2)
Y=(#YPos# + #HSize# / 1.25)


[MeterDateText]
Meter=STRING
MeasureName=MeasureDate
Text=%1
FontFace=#FontName#
FontColor=#ColorMain#
FontSize=(#FontSize#+2)
StringStyle=Bold
FontEffectColor=#ColorShade#
AntiAlias=1
DynamicVariables=1
StringAlign=CenterBottom
X=(#XPos# + #WSize# / 2)
Y=(#YPos# + #HSize# / 1.1)

[MeterUptimeText]
Meter=STRING
MeasureName=MeasureUptime
Text=%1
FontFace=#FontName#
FontColor=#ColorCplA#
FontSize=(#FontSize#+4)
AntiAlias=1
DynamicVariables=1
StringAlign=CenterCenter
X=(#XPos# + #WSize# / 2)
Y=(#YPos# + #HSize# / 3)
Post Reply