PDF版 ePub版

# 映射 (Map)

1>#{ "key"=>42}.
#{"key" => 42}

-module(color).

-export([new/4, blend/2]).

-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).

new(R,G,B,A) when ?is_channel(R), ?is_channel(G),
?is_channel(B), ?is_channel(A) ->
#{red => R, green => G, blue => B, alpha => A}.

blend(Src,Dst) ->
blend(Src,Dst,alpha(Src,Dst)).

blend(Src,Dst,Alpha) when Alpha > 0.0 ->
Dst#{
red   := red(Src,Dst) / Alpha,
green := green(Src,Dst) / Alpha,
blue  := blue(Src,Dst) / Alpha,
alpha := Alpha
};
blend(_,Dst,_) ->
Dst#{
red   := 0.0,
green := 0.0,
blue  := 0.0,
alpha := 0.0
}.

alpha(#{alpha := SA}, #{alpha := DA}) ->
SA + DA*(1.0 - SA).

red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
green(#{green := SV, alpha := SA}, #{green := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
blue(#{blue := SV, alpha := SA}, #{blue := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).

1> c(color).
{ok,color}
2> C1 = color:new(0.3,0.4,0.5,1.0).
#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}
3> C2 = color:new(1.0,0.8,0.1,0.3).
#{alpha => 0.3,blue => 0.1,green => 0.8,red => 1.0}
4> color:blend(C1,C2).
#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}
5> color:blend(C2,C1).
#{alpha => 1.0,blue => 0.38,green => 0.52,red => 0.51}

-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).

new(R,G,B,A) when ?is_channel(R), ?is_channel(G),
?is_channel(B), ?is_channel(A) ->
#{red => R, green => G, blue => B, alpha => A}.

blend/2 函数所做的第一件事就是计算 alpha 通道：

alpha(#{alpha := SA}, #{alpha := DA}) ->
SA + DA*(1.0 - SA).

red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).

blend(Src,Dst,Alpha) when Alpha > 0.0 ->
Dst#{
red   := red(Src,Dst) / Alpha,
green := green(Src,Dst) / Alpha,
blue  := blue(Src,Dst) / Alpha,
alpha := Alpha
};

Dst 映射会被更新为一个新的通道值。更新已存在的映射键值对可以用 := 操作符。