Permanently protected module
From Wikipedia, the free encyclopedia


--

-- This module implements

--  {{Color contrast ratio}}

--  {{Greater color contrast ratio}}

--  {{ColorToLum}}

--  {{RGBColorToLum}}

--

local p = {}

local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )



local function sRGB (v)

	if (v <= 0.03928) then

		v = v / 12.92

	else

		v = math.pow((v+0.055)/1.055, 2.4)

	end

	return v

end



local function rgbdec2lum(R, G, B)

	if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then

		return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)

	else

		return ''

	end

end



local function hsl2lum(h, s, l)

	if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then

		local c = (1 - math.abs(2*l - 1))*s

		local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )

		local m = l - c/2



		local r, g, b = m, m, m

		if( 0 <= h and h < 60 ) then

			r = r + c

			g = g + x

		elseif( 60 <= h and h < 120 ) then

			r = r + x

			g = g + c

		elseif( 120 <= h and h < 180 ) then

			g = g + c

			b = b + x

		elseif( 180 <= h and h < 240 ) then

			g = g + x

			b = b + c

		elseif( 240 <= h and h < 300 ) then

			r = r + x

			b = b + c

		elseif( 300 <= h and h < 360 ) then

			r = r + c

			b = b + x

		end

		return rgbdec2lum(255*r, 255*g, 255*b)

	else

		return ''

	end

end



local function color2lum(c)



	if (c == nil) then

		return ''

	end



	-- html '#' entity

	c = c:gsub("&#35;", "#")



	-- whitespace

	c = c:match( '^%s*(.-)[%s;]*$' )



	-- unstrip nowiki strip markers

	c = mw.text.unstripNoWiki(c)



	-- lowercase

	c = c:lower()



	-- first try to look it up

	local L = HTMLcolorc

	if (L ~= nil) then

		return L

	end



	-- convert from hsl

	if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then

		local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')

		return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)

	end



	-- convert from rgb

	if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then

		local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')

		return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))

	end



	-- convert from rgb percent

	if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then

		local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')

		return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)

	end



	-- remove leading # (if there is one) and whitespace

	c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')



	-- split into rgb

	local cs = mw.text.split(c or '', '')

	if( #cs == 6 ) then

		local R = 16*tonumber('0x' .. cs1]) + tonumber('0x' .. cs2])

		local G = 16*tonumber('0x' .. cs3]) + tonumber('0x' .. cs4])

		local B = 16*tonumber('0x' .. cs5]) + tonumber('0x' .. cs6])



		return rgbdec2lum(R, G, B)

	elseif ( #cs == 3 ) then

		local R = 16*tonumber('0x' .. cs1]) + tonumber('0x' .. cs1])

		local G = 16*tonumber('0x' .. cs2]) + tonumber('0x' .. cs2])

		local B = 16*tonumber('0x' .. cs3]) + tonumber('0x' .. cs3])



		return rgbdec2lum(R, G, B)

	end



	-- failure, return blank

	return ''

end



-- This exports the function for use in other modules.

-- The colour is passed as a string.

function p._lum(color)

	return color2lum(color)

end



function p._greatercontrast(args)

	local bias = tonumber(args'bias' or '0') or 0

	local css = (args'css' and args'css' ~= '') and true or false

	local v1 = color2lum(args1 or '')

	local c2 = args2 or '#FFFFFF'

	local v2 = color2lum(c2)

	local c3 = args3 or '#000000'

	local v3 = color2lum(c3)

	local ratio1 = -1;

	local ratio2 = -1;

	if (type(v1) == 'number' and type(v2) == 'number') then

		ratio1 = (v2 + 0.05)/(v1 + 0.05)

		ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1

	end

	if (type(v1) == 'number' and type(v3) == 'number') then

		ratio2 = (v3 + 0.05)/(v1 + 0.05)

		ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2

	end



	if css then

		local c1 = args1 or ''

		if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c1 = '#' .. c1

		end

		if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c2 = '#' .. c2

		end

		if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c3 = '#' .. c3

		end

		return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'

	end



	return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''

end



function p._ratio(args)

	local v1 = color2lum(args1])

	local v2 = color2lum(args2])

	if (type(v1) == 'number' and type(v2) == 'number') then

		-- v1 should be the brighter of the two.

		if v2 > v1 then

			v1, v2 = v2, v1

		end

		return (v1 + 0.05)/(v2 + 0.05)

	else

		return args'error' or '?'

	end

end



function p._styleratio(args)

	local style = (args1 or ''):lower()

	local bg, fg = 'white', 'black'

	local lum_bg, lum_fg = 1, 0



	if args2 then

		local lum = color2lum(args2])

		if lum ~= '' then bg, lum_bg = args2], lum end

	end

	if args3 then

		local lum = color2lum(args3])

		if lum ~= '' then fg, lum_fg = args3], lum end

	end



	local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '&#35;', '#'), ';')

	for k = 1,#slist do

		local s = slistk

		local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )

		k = k or ''

		v = v or ''

		if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then

			local lum = color2lum(v)

			if( lum ~= '' ) then bg, lum_bg = v, lum end

		elseif (k:match('^[%s]*(color)[%s]*$')) then

			local lum = color2lum(v)

			if( lum ~= '' ) then bg, lum_fg = v, lum end

		end

	end

	if lum_bg > lum_fg then

		return (lum_bg + 0.05)/(lum_fg + 0.05)

	else

		return (lum_fg + 0.05)/(lum_bg + 0.05)

	end

end



--[[

Use {{#invoke:Color contrast|somecolor}} directly or

{{#invoke:Color contrast}} from a wrapper template.



Parameters:

	-- |1=	— required; A color to check.

--]]

function p.lum(frame)

	local color = frame.args1 or frame:getParent().args1

	return p._lum(color)

end



function p.ratio(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._ratio(args)

end



function p.styleratio(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._styleratio(args)

end



function p.greatercontrast(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._greatercontrast(args)

end



return p
Permanently protected module
From Wikipedia, the free encyclopedia


--

-- This module implements

--  {{Color contrast ratio}}

--  {{Greater color contrast ratio}}

--  {{ColorToLum}}

--  {{RGBColorToLum}}

--

local p = {}

local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )



local function sRGB (v)

	if (v <= 0.03928) then

		v = v / 12.92

	else

		v = math.pow((v+0.055)/1.055, 2.4)

	end

	return v

end



local function rgbdec2lum(R, G, B)

	if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then

		return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)

	else

		return ''

	end

end



local function hsl2lum(h, s, l)

	if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then

		local c = (1 - math.abs(2*l - 1))*s

		local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )

		local m = l - c/2



		local r, g, b = m, m, m

		if( 0 <= h and h < 60 ) then

			r = r + c

			g = g + x

		elseif( 60 <= h and h < 120 ) then

			r = r + x

			g = g + c

		elseif( 120 <= h and h < 180 ) then

			g = g + c

			b = b + x

		elseif( 180 <= h and h < 240 ) then

			g = g + x

			b = b + c

		elseif( 240 <= h and h < 300 ) then

			r = r + x

			b = b + c

		elseif( 300 <= h and h < 360 ) then

			r = r + c

			b = b + x

		end

		return rgbdec2lum(255*r, 255*g, 255*b)

	else

		return ''

	end

end



local function color2lum(c)



	if (c == nil) then

		return ''

	end



	-- html '#' entity

	c = c:gsub("&#35;", "#")



	-- whitespace

	c = c:match( '^%s*(.-)[%s;]*$' )



	-- unstrip nowiki strip markers

	c = mw.text.unstripNoWiki(c)



	-- lowercase

	c = c:lower()



	-- first try to look it up

	local L = HTMLcolorc

	if (L ~= nil) then

		return L

	end



	-- convert from hsl

	if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then

		local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')

		return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)

	end



	-- convert from rgb

	if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then

		local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')

		return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))

	end



	-- convert from rgb percent

	if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then

		local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')

		return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)

	end



	-- remove leading # (if there is one) and whitespace

	c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')



	-- split into rgb

	local cs = mw.text.split(c or '', '')

	if( #cs == 6 ) then

		local R = 16*tonumber('0x' .. cs1]) + tonumber('0x' .. cs2])

		local G = 16*tonumber('0x' .. cs3]) + tonumber('0x' .. cs4])

		local B = 16*tonumber('0x' .. cs5]) + tonumber('0x' .. cs6])



		return rgbdec2lum(R, G, B)

	elseif ( #cs == 3 ) then

		local R = 16*tonumber('0x' .. cs1]) + tonumber('0x' .. cs1])

		local G = 16*tonumber('0x' .. cs2]) + tonumber('0x' .. cs2])

		local B = 16*tonumber('0x' .. cs3]) + tonumber('0x' .. cs3])



		return rgbdec2lum(R, G, B)

	end



	-- failure, return blank

	return ''

end



-- This exports the function for use in other modules.

-- The colour is passed as a string.

function p._lum(color)

	return color2lum(color)

end



function p._greatercontrast(args)

	local bias = tonumber(args'bias' or '0') or 0

	local css = (args'css' and args'css' ~= '') and true or false

	local v1 = color2lum(args1 or '')

	local c2 = args2 or '#FFFFFF'

	local v2 = color2lum(c2)

	local c3 = args3 or '#000000'

	local v3 = color2lum(c3)

	local ratio1 = -1;

	local ratio2 = -1;

	if (type(v1) == 'number' and type(v2) == 'number') then

		ratio1 = (v2 + 0.05)/(v1 + 0.05)

		ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1

	end

	if (type(v1) == 'number' and type(v3) == 'number') then

		ratio2 = (v3 + 0.05)/(v1 + 0.05)

		ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2

	end



	if css then

		local c1 = args1 or ''

		if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c1 = '#' .. c1

		end

		if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c2 = '#' .. c2

		end

		if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or

			mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

				c3 = '#' .. c3

		end

		return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'

	end



	return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''

end



function p._ratio(args)

	local v1 = color2lum(args1])

	local v2 = color2lum(args2])

	if (type(v1) == 'number' and type(v2) == 'number') then

		-- v1 should be the brighter of the two.

		if v2 > v1 then

			v1, v2 = v2, v1

		end

		return (v1 + 0.05)/(v2 + 0.05)

	else

		return args'error' or '?'

	end

end



function p._styleratio(args)

	local style = (args1 or ''):lower()

	local bg, fg = 'white', 'black'

	local lum_bg, lum_fg = 1, 0



	if args2 then

		local lum = color2lum(args2])

		if lum ~= '' then bg, lum_bg = args2], lum end

	end

	if args3 then

		local lum = color2lum(args3])

		if lum ~= '' then fg, lum_fg = args3], lum end

	end



	local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '&#35;', '#'), ';')

	for k = 1,#slist do

		local s = slistk

		local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )

		k = k or ''

		v = v or ''

		if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then

			local lum = color2lum(v)

			if( lum ~= '' ) then bg, lum_bg = v, lum end

		elseif (k:match('^[%s]*(color)[%s]*$')) then

			local lum = color2lum(v)

			if( lum ~= '' ) then bg, lum_fg = v, lum end

		end

	end

	if lum_bg > lum_fg then

		return (lum_bg + 0.05)/(lum_fg + 0.05)

	else

		return (lum_fg + 0.05)/(lum_bg + 0.05)

	end

end



--[[

Use {{#invoke:Color contrast|somecolor}} directly or

{{#invoke:Color contrast}} from a wrapper template.



Parameters:

	-- |1=	— required; A color to check.

--]]

function p.lum(frame)

	local color = frame.args1 or frame:getParent().args1

	return p._lum(color)

end



function p.ratio(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._ratio(args)

end



function p.styleratio(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._styleratio(args)

end



function p.greatercontrast(frame)

	local args = frame.args1 and frame.args or frame:getParent().args

	return p._greatercontrast(args)

end



return p

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook