置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Colorhime

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [查看] [编辑] [历史] [刷新]
local Colorhime = {}

local getArgs = require('Module:Arguments').getArgs
local Color = require('Module:color')

function Colorhime.main(frame)
	local args = getArgs(frame)
	local colors = {}
	local a = { args['LtMAG'] or 1 , args['ChrMAG'] or 3 , args['LtMAX'] or 225 , args['LtMIN'] or 0 , args['ChrMAX'] or 200 }
	
	local col_o = Color.create(args[1]):rgb().value
	local l2 = math.min( math.max( a[1]*(0.2126*col_o[1]^2+0.7152*col_o[2]^2+0.0722*col_o[3]^2) , a[4]^2 ) , a[3]^2 , 65025 )
	local col_t = Colorhime.convert(l2, col_o, a[2], a[5])
	colors['o'] = toString(col_o, args['alpha-o'] or 1)
	colors['t'] = toString(col_t, args['alpha-t'] or 1)
	frame:callParserFunction( '#vardefine' , 'color-t' , colors['t'] )
	
	for k, v in pairs(args) do
		if mw.ustring.sub(k, 1, 6) == 'color-' then
			local col_k = {}
			k = mw.ustring.sub(k, 7)
			if v:find('^%+') then
				v = l2 + (65025 - l2) * v / 100
			elseif v:find('^%-') then
				v = l2 * (1 + v / 100)
			else
				v = v ^ 2
			end
			v = math.min( math.max( v , 0 ) , 65025 )
			
			if v == 65025 then
				col_k = {255, 255, 255}
			elseif v >= l2 then
				col_k = Colorhime.kCalc(col_t, v)
			else
				col_k = Colorhime.convert(v, col_t, 1, 500)
			end
			colors[k] = toString(col_k, args['alpha-'..k] or 1)
			frame:callParserFunction( '#vardefine' , 'color-'..k , colors[k] )
		end
	end
	
	return colors[args['output'] or 't']
end

function Colorhime.convert(l2, rgb, m, c)
	local h
	local r, g, b = rgb[1], rgb[2], rgb[3] 
	if r > g then
		if g > b then      --rgb 0~60
			h = (g - b)/(r - b)
			return Colorhime.tCalc( h , 0.2126 , 0.7152 , 0.0722 , l2 , math.min(m*(r-b), c*(-1286.9*h^4+1328.7*h^3-142.29*h^2+134.23*h+165.74)/200, 255) )
		elseif b > r then  --brg 240~300
			h = (r - g)/(b - g)
			rgb = Colorhime.tCalc( h , 0.0722 , 0.2126 , 0.7152 , l2 , math.min(m*(b-g), c*(-53.74*h^2+37.053*h+129.88)/200, 255) )
			return {rgb[2], rgb[3], rgb[1]}
		else             --rbg 300~360
			h = (r - b)/(r - g)
			rgb = Colorhime.tCalc( 1-h , 0.2126 , 0.0722 , 0.7152 , l2 , math.min(m*(r-g), c*(-49.395*h^2+101.94*h+113.19)/200, 255) )
			return {rgb[1], rgb[3], rgb[2]}
		end
	else
		if r > b then      --grb 60~120
			h = (g - r)/(g - b)
			rgb = Colorhime.tCalc( 1-h , 0.7152 , 0.2126 , 0.0722 , l2 , math.min(m*(g-b), c*(29.76*h^2-104.35*h+199.48)/200, 255) )
			return {rgb[2], rgb[1], rgb[3]}
		elseif b > g then  --bgr 180~240
			h = (b - g)/(b - r)
			rgb = Colorhime.tCalc( 1-h , 0.0722 , 0.7152 , 0.2126 , l2 , math.min(m*(b-r), c*(-1436.6*h^4+3559.6*h^3-2760.2*h^2+379.84*h+387.24)/200, 255) )
			return {rgb[3], rgb[2], rgb[1]}
		elseif g > r then  --gbr 120~180
			h = (b - r)/(g - r)
			rgb = Colorhime.tCalc( h , 0.7152 , 0.0722 , 0.2126 , l2 , math.min(m*(g-r), c*(-1404.8*h^4+2509.9*h^3-1063.4*h^2+220.65*h+124.89)/200, 255) )
			return {rgb[3], rgb[1], rgb[2]}
		else             --r=g=b c=0
			return Colorhime.tCalc( 0 , 1 , 0 , 0 , l2 , 0 )
		end
	end
end

function Colorhime.tCalc(h, k1, k2, k3, l2, c)
	local c1, c2, c3
	if l2 < (k1 + k2 * h ^ 2) * c ^ 2 then
		c1 = (l2 / (k1 + k2 * h ^ 2)) ^ (1/2)
		c2 = c1 * h
		c3 = 0
	elseif l2 > k1 * 65025 + k2 * (255 - c + h * c) ^ 2 + k3 * (255 - c) ^ 2 then
		local A = k2 * (1 - h) ^ 2+ k3
		c3 = ((A * l2 / 65025 - k1 * A - k2 * k3 * h ^ 2) ^ (1/2) - k2 * h * (1 - h)) * 255 / A
		c2 = (255 - c3) * h + c3
		c1 = 255
	else
		local B = k1 + k2 * h 
		c3 = ((B ^ 2 - k1 - k2 * h ^ 2) * c ^ 2 + l2) ^ (1/2) - B * c
		c2 = c * h + c3
		c1 = c + c3
	end
	return {c1, c2, c3}
end

function Colorhime.kCalc(rgb, l2)
	local h1 = (255 - rgb[1]) / (765 - rgb[1] - rgb[2] - rgb[3])
	local h2 = (255 - rgb[2]) / (765 - rgb[1] - rgb[2] - rgb[3])
	local h3 = (255 - rgb[3]) / (765 - rgb[1] - rgb[2] - rgb[3])
	local A = 0.2126 * h1 ^ 2 + 0.7152 * h2 ^ 2 + 0.0722 * h3 ^ 2
	local B = 0.2126 * h1 + 0.7152 * h2 + 0.0722 * h3
	local X = (B - (B ^ 2 - A * (1 - l2 / 65025)) ^ (1/2)) * 255 / A
	
	return { 255-h1*X , 255-h2*X , 255-h3*X }
end

function toString(rgb, alpha)
	function toHex(int)
		local zero = ''
		if int < 16 then zero = '0' end
		return zero..string.format('%X', int)
	end
	
	local r, g, b = math.floor(rgb[1] + 0.5), math.floor(rgb[2] + 0.5), math.floor(rgb[3] + 0.5)
	
	if alpha == 1 then
		return toHex(r)..toHex(g)..toHex(b)
	else
		return 'rgba('..r..','..g..','..b..','..alpha..')'
	end
end

return Colorhime