Jump to content

Module:HexShade

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Plastikspork (talk | contribs) at 21:35, 12 December 2021 (Creating LUA version of Template:HexShade using code from Template:HexShade/1, Template:HSLtoRGB.R, Template:HSLtoRGB.G, Template:HSLtoRGB.B, Template:RGBtoHSL.H, Template:RGBtoHSL.S, Template:RGBtoHSL.L, Template:Hex2). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

-- This module implements {{HexShade}}
local p = {}

local function rgbdec2hex(r, g, b, d)
	if (r >= 0 and g >= 0 and b >= 0 ) then
		local baseconvert = require('Module:BaseConvert')
		local s1 = baseconvert.convert({n = math.floor(r+0.5), base = 16})
		local s2 = baseconvert.convert({n = math.floor(g+0.5), base = 16})
		local s3 = baseconvert.convert({n = math.floor(b+0.5), base = 16})
		s1 = mw.ustring.gsub(s1, '^([0-9A-Fa-f])$', '0%1')
		s2 = mw.ustring.gsub(s2, '^([0-9A-Fa-f])$', '0%1')
		s3 = mw.ustring.gsub(s3, '^([0-9A-Fa-f])$', '0%1')
		return s1 .. s2 .. s3
	end
	return d
end

local function rgbdec2hsl(r, g, b)
	local H, S, L
	-- hue
	if ((r == g) and (g == b)) then
		H = 0
	elseif ((g >= r) and (g >= b)) then
		if (r > b) then
			H = 120 - 60 * (r - b) / (g - b)
		else 
			H = 120 + 60 * (b - r) / (g - r)
		end
	elseif ((b >= r) and (b >= g)) then
		if (g > r) then
			H = 240 - 60 * (g - r) / (b - r)
		else 
			H = 240 + 60 * (r - g) / (b - g)
		end
	else
		if (b > g) then 
			H = 360 - 60 * (b - g) / (r - g)
		else 
			H = 60 * (g - b) / (r - b)
		end
	end
	-- saturation
	if ((r == g) and (g == b)) then
		S = 0
	elseif ((g >= r) and (g >= b)) then
		if (r > b) then
			if ((g + b) > 255) then
				S = (g - b) / (510 - g - b)
			else
				S = (g - b) / (g + b)
			end
		else 
			if ((g + r) > 255) then
				S = (g - r) / (510 - g - r)
			else
				S = (g - r) / (g + r)
			end
		end
	elseif ((r >= b) and (r >= g)) then
		if (r > g) then
			if ((r + g) > 255) then
				S = (r - g) / (510 - r - g)
			else
				S = (r - g) / (r + g)
			end
		else
			if ((r + b) > 255) then
				S = (r - b) / (510 - r - b)
			else 
				S = (r - b) / (r + b)
			end
		end
	else
		if (g > r) then
			if ((b + r) > 255) then
				S = (b - r) / (510 - b - r)
			else 
				S = (b - r) / (b + r)
			end
		else
			if ((b + g) > 255) then 
				S = (b - g) / (510 - b - g)
			else 
				S = (b - g) / (b + g)
			end
		end
	end
	
	-- luminosity
	L = (math.max(r, math.max(g, b)) + math.min(r, math.min(g, b))) / (255 * 2)
	
	return H, S, L
end

local function hsl2rgbdec(H, S, L)
	local R, G, B
	if ( 0 <= H and H < 360 and 0 <= S and S <= 1 and 0 <= L and L <= 1 ) then
		-- R
		if (math.fmod(H + 120, 360) > 180) then
			if (math.fmod(H + 120, 360) > 240) then
				if (L > 0.5) then
					R = L - S * (1 - L)
				else 
					R = (1 - S) * L
				end
			else
				if (L > 0.5) then 
					R = L - (1 - (240 - math.fmod(H + 120, 360) / 30) * S * (1 - L))
				else 
					R = (1 - (1 - (240 - math.fmod(H + 120, 360) / 30) * S) * L)
				end
			end
		else
			if (math.fmod(H + 120, 360) > 60) then
				if (L > 0.5) then 
					R = L + S * (1 - L)
				else 
					R = (1 + S) * L
				end
			else
				if (L > 0.5) then
					R = L - ((1 - math.fmod(H + 120, 360) / 30) * S * (1 - L))
				else 
					R = (1 - ((1 - math.fmod(H + 120, 360) / 30) * S) * L)
				end
			end
		end
		-- G
		if (math.fmod(H,360) > 180) then
			if (math.fmod(H,360) > 240) then
				if (L > 0.5) then 
					G = L - S * (1 - L)
				else 
					G = (1 - S) * L
				end
			else
				if (L > 0.5) then 
					G = L - (1 - (240 - math.fmod(H,360)) / 30) * S * (1 - L)
				else 
					G = (1 - (1 - (240 - math.fmod(H,360)) / 30) * S) * L
				end
			end
		else
			if (math.fmod(H,360) > 60) then
				if (L > 0.5) then 
					G = L + S * (1 - L)
				else 
					G = (1 + S) * L
				end
			else
				if (L > 0.5) then 
					G = L - ((1 - math.fmod(H,360)) / 30) * S * (1 - L)
				else 
					G = (1 - ((1 - math.fmod(H,360)) / 30) * S) * L
				end
			end
		end
		-- B
		if (math.fmod(H - 120,360) > 180) then
			if (math.fmod(H - 120,360) > 240) then
				if (L > 0.5) then
					B = L - S * (1 - L)
				else 
					B = (1 - S) * L
				end
			else
				if (L > 0.5) then 
					B = L - (1 - (240 - math.fmod(H - 120,360)) / 30) * S * (1 - L)
				else 
					B = (1 - (1 - (240 - math.fmod(H - 120,360)) / 30) * S) * L
				end
			end
		else
			if (math.fmod(H - 120,360) > 60) then
				if (L > 0.5) then
					B = L + S * (1 - L)
				else 
					B = (1 + S) * L
				end
			else
				if (L > 0.5) then
					B = L - (1 - math.fmod(H - 120,360) / 30) * S * (1 - L)
				else 
					B = (1 - (1 - math.fmod(H - 120,360) / 30) * S) * L
				end
			end
		end
	
		return 255*R, 255*G, 255*B
	end
	return -1, -1, -1
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame)
	
	-- Remove nowiki and leading hash signs
	local c = mw.text.unstrip(args[1] or '')
	c = mw.ustring.match(c, '^[%s]*(.-)[%s]*$')
	c = mw.ustring.gsub(c, '^[%s#]*', '')
	c = mw.ustring.gsub(c, '^&#32;[%s]*', '')
	-- Lowercase	
	c = c:lower()
	-- Expand short 3 hex for to 6 hex form
	c = mw.ustring.gsub(c, '^([0-9a-f])([0-9a-f])([0-9a-f])$', '%1%1%2%2%3%3')
	
	-- Get new value for luminosity
	local Lnew = tonumber(args[2] or '-1') or -1
	
	-- Default return
	local res = c
	
	-- Adjust shading
	local cs = mw.text.split(c or '', '')
	if( #cs == 6 ) then
		-- Convert to RGBdec
		local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
		local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
		local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])

		-- Convert RGBdec to HSL
		local H, S, L = rgbdec2hsl(R, G, B)
		
		-- Convert back to RGBdec
		local R, G, B = hsl2rgbdec(H, S, Lnew)
		
		-- Convert back to RGBhex
		res = rgbdec2hex(R, G, B, c)
	end
	
	if args[3] == '#' and mw.ustring.match('^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]') then
		return '#' .. res
	end
	
	return res
end

return p