混合图层算法
本文中的混合图层跟PhotoShop中完全一致。
1正常模式:混合色*不透明度+(100%-混合色不透明度)
2溶解模式:溶解模式下混合色的不透明度及填充都是100%的话,我们就看不到基色图层。降低混合色图层的不透明度后,我们就会发现结果色中出现了很多细小的颗粒。这些颗粒会随着混合色的不透明度变化。不透明度越低混合色图层就被溶解的越多。剩下的部分就越少。不透明度越高混合色图层被溶解的部分就越少,剩下的部分就越多,结果色就越接近混合色。
3变暗模式:变暗混合模式下,它会把混合色与基色进行对比,分别选择R,G,B三组数值中最小的数值,也就是最暗的颜色作为结果色的数值。这样整个画面会变得更暗,如果是彩色图像,颜色也会发生很大的改变。(位置互换不发生变化)
4正片叠底:正片叠底混合原理:它是按照混合色与基色中的各R,G,B值计算,计算公式:结果色R=混合色R
* 基色R / 255,G值与B值同样的方法计算。最后得到的R,G,B值就是结果色的颜色。由于各通道的最大值是255,因此结果色的数值比混合色及基色的数值都要小,也就是结果色要暗。(位置互换不发生变化)
5颜色加深:颜色加深可以快速增加图片的暗部。它的计算公式:结果色 = (基色 + 混合色 -
255)* 255 / 混合色。其中(基色 + 混合色 -
255)如果出现负数就直接归0。因此在基色与混合色都较暗的时候都是直接变成黑色的。这样结果色的暗部就会增加。整体效果看上去对比较为强烈。
6线性加深:线性加深的计算公式是:结果色 = 基色 + 混合色 -
255,如果基色 + 混合色的数值小于255,结果色就为0。由这个公式可以看出,画面暗部会直接变成黑色。因此画面整体会更暗。白色与基色混合得到基色,黑色与基色混合得到黑色。(位置互换不发生变化)
7深色模式:深色混合模式比较好理解。它是通过计算混合色与基色的所有通道的数值,然后选择数值较小的作为结果色。因此结果色只跟混合色或基色相同,不会产生出另外的颜色。白色与基色混合色得到基色,黑色与基色混合得到黑色。深色模式中,混合色与基色的数值是固定的,我们颠倒位置后,混合色出来的结果色是没有变化的。
8变亮模式:变亮模式跟变暗模式是相对的,它是通过混合色与基色的相关数值进行比较,选择较大的数值作为结果色。因此结果色会更亮,同时颜色也会变化。(位置互换不发生变化)
9滤色模式:滤色模式与正片叠底模式相对。它的计算公式是:
255 - 混合色的补色 * 基色补色 /
255。得到的数据会比混合及基色更大,因此结果色会更亮。从计算公式也可以看出基色或混合色任何一项为255也就是白色,结果色数值就是255为白色。任何一项数值为0,也就是为黑色的话,结果色就跟数值不为0的一致。
10颜色减淡:颜色减淡是通过混合色及基色的各通道颜色值进行对比,减少二者的对比度使基色的变亮来反映混合色。
它的计算公式:结果色 = 基色 + (混合色 * 基色)
/ (255 - 混合色)。混合色为黑色,结果色就等于基色,混合色为白色结果色就为白色。基色为黑色结果色就为黑色。
11线性减淡:线性减淡是通过查看每个通道的颜色信息,并通过增加亮度使基色变亮以反映混合色。它的计算公式:结果色 = 基色 + 混合色,其中基色与混合色的数值大于255,系统就默认为最大值也就是255。
由公式可以分析出混合色为黑色结果色就等于基色,混合色为白色结果色就为白色。基色也一样。我们颠倒混合色及基色的位置,结果色也不会变化。(位置互换不发生变化)
12浅色模式:浅色模式比较好理解:它是通过计算混合色与基色所有通道的数值总和,哪个数值大就选为结果色。因此结果色只能在混合色与基色中选择,不会产生第三种颜色。与深色模式刚好相反。
13叠加:叠加模式比较特别,它是通过分析基色个通道的数值,对颜色进行正片叠加或滤色混合,结果色保留基色的明暗对比,因此结果色以基色为主导。
计算公式:
基色 < = 128:结果色 = 混合色 * 基色 /
128;基色 > 128:结果色 = 255 - (255
- 混合色)* (255 - 基色) / 128。
从公式可以看出,结果色会根据基色的颜色数值选择不同的计算公式。
14柔光模式:柔光模式是较为常用的模式,它是根据混合色的通道数值选择不同的公式计算混合色。数值大于128的时候,结果色就比基色稍亮;数值小于或等于128,结果色就比基色稍暗。柔光模式是以基色为主导,混合色只相应改变局部明暗。其中混合色为黑色,结果色不会为黑色,只比结果色稍暗,混合色为中性色,结果色跟基色一样。
计算公式:
混合色 <=128:结果色 = 基色 +
(2 * 混合色 - 255) * (基色 - 基色 * 基色 /
255) / 255;
混合色 >128: 结果色 = 基色 +
(2 * 混合色 - 255) * (Sqrt(基色/255)*255 - 基色)/255。
如果基色=混合色,则可优化为256的表smoothlight,公式变形如下:
res = x + (2x-255)*(x-x*x/255)/255;
res = x+(2x-255)*(255*sqrt(x/255)-x)/255;
unsigned char smoothlight[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20,
21, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98,
99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 133, 135, 136, 137, 139, 140, 142, 143, 144, 146, 147, 148, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 163, 164, 165, 166, 168, 169, 170,
171, 173, 174, 175, 176, 178, 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224, 225,
226, 227, 228, 228, 229, 230, 231, 232, 233, 233, 234, 235, 236, 236, 237, 238, 239, 239, 240, 241, 241, 242, 243, 243, 244, 245, 245, 246, 247, 247, 248, 248, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 255};
15强光模式:强光模式跟叠加模式十分类似,只是在计算的时候需要通过混合色来控制,混合色的数值小于或等于128的时候,颜色会变暗;混合色的数值大于128的时候,颜色会变亮。混合色为白色,结果色就为白色;混合色为黑色,结果为黑色。混合色起到主导作用。
计算公式:
混合色 <= 128:结果色 = 混合色 * 基色 /
128;
混合色 > 128 :结果色 = 255 - (255
- 混合色) * (255 - 基色) / 128.
16亮光模式:亮光模式是通过增加或减少对比度是颜色变暗或变亮,具体取决于混合色的数值。混合色比中性灰色暗,结果色就相应的变暗,混合色比中性灰色亮,结果色就相应的变亮。有点类似颜色加深或颜色减淡。
计算公式:
A---基色;B—混合色
C=A-(255-A)*(255-2B)/2B 当混合色>128时
C=A+[A*(2B-255)]/[255-(2B-255)
17线性光:线性光:通过减少或增加亮度,来使颜色加深或减淡。具体取决于混合色的数值。混合色数值比中性灰色暗的时候进行相应的加深混合;混合色的数值比中性灰色亮的时候进行减淡混合。这里的加深及减淡时线性加深或线性减淡。
计算公式:结果色 = 2 * 混合色 + 基色 -255。数值大于255取255。
18点光:点光模式:它会根据混合色的颜色数值替换相应的颜色。如果混合色数值小于中性灰色,那么就替换比混合色亮的像素;相反混合色的数值大于中性灰色,则替换比混合色暗的像素,因此混合出来的颜色对比较大。
计算公式:
基色 < 2 * 混合色 - 255:结果色 =
2 * 混合色 - 255;
2 * 混合色 - 255 < 基色 <
2 * 混合色 :结果色 = 基色;
基色 > 2 * 混合色:结果色 = 2 * 混合色。
19实色混合: 实色混合是把混合色颜色中的红、绿、蓝通道数值,添加到基色的RGB值中。结果色的R、G、B通道的数值只能是255或0。因此结构色只有一下八种可能:红、绿、蓝、黄、青、洋红、白、黑。由此看以看出结果色是非常纯的颜色。
计算公式:
混合色 + 基色 < 255:结果色 =
0 ;混合色 + 基色 >= 255:结果色 =
255。
20差值模式:差值模式:查看每个通道的数值,用基色减去混合色或用混合色减去基色。具体取决于混合色与基色那个通道的数值更大。白色与任何颜色混合得到反相色,黑色与任何颜色混合颜色不变。
计算公式:
结果色 = 绝对值(混合色 - 基色)
21排除模式:排除模式是跟差值模式非常类似的混合模式,只是排除模式的结果色对比度没有差值模式强。白色与基色混合得到基色补色,黑色与基色混合得到基色。
计算公式:
结果色 = (混合色 + 基色)
- 混合色 * 基色 / 128。
22减去模式:减去模式:查看各通道的颜色信息,并从基色中减去混合色。如果出现负数就剪切为零;与基色相同的颜色混合得到黑色;白色与基色混合得到黑色;黑色与基色混合得到基色。
计算公式:
结果色 = 基色 - 混合色。
23划分模式:查看每个通道的颜色信息,并用基色分割混合色。基色数值大于或等于混合色数值,混合出的颜色为白色。基色数值小于混合色,结果色比基色更暗。因此结果色对比非常强。白色与基色混合得到基色,黑色与基色混合得到白色。
计算公式:
结果色 = (基色 / 混合色)
* 255。
24色相:色相混合模式:结果色保留混合色的色相,饱和度及明度数值保留明度数值。这里用到的色相、饱和度、明度也是一种颜色模式,也称作:HSB模式。色相代表颜色的颜色相貌,也就是我们看到的红、绿、蓝等;饱和度是颜色的饱和程度,也就是鲜艳度;明度是颜色的明暗程度。其中黑色、灰色、白色是没有颜色和饱和度的,也就是相关数值为0。
25饱和度模式:饱和度模式是用混合色的饱和度以及基色的色相和明度创建结果色。我们都知道饱和度只控制颜色的鲜艳程度,因此混合色只改变图片的鲜艳度,不能影响颜色。黑、白、灰除外,因为这些颜色的饱和度为0,混合后只能产生一种灰色效果。
26颜色模式:颜色模式是用混合色的色相,饱和度以及基色的明度创建结果色。这种模式下混合色控制真个画面的颜色,是黑白图片上色的绝佳模式,因为这种模式下会保留基色图片也就是黑白图片的明度度。黑、白、会与基色混合会产生相同的灰色效果,因为这三种颜色的色相,饱和度都是0。
27明度模式:明度混合模式是利用混合色的明度以及基色的色相与饱和度创建结果色。她跟颜色模式刚好相反,因此混合色图片只能影响图片的明暗度,不能对基色的颜色产生影响,黑、白、灰除外。黑色与基色混合得到黑色;白色与基色混合得到白色;灰色与基色混合得到明暗不同的基色。
28去色公式:每个像素RGB的最大值和最小值和的一半,作为最后值输出。
附录 Android C Code with RGB565
附录 Android C Code with RGB565
specialeffect.h
#ifndef SPECIALEFFECT
#define SPECIALEFFECT
#include
#include
#include
#include
#include
int ModeDarkness(int basePixel,int mixPixel);//变暗模式
int ModeMultiply(int basePixel,int mixPixel);//正片叠底模式
int ModeColorDark(int basePixel,int mixPixel);//颜色加深模式
int ModeLinearDark(int basePixel,int mixPixel);//线性渐变模式
int* ModeDark(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue);//深色模式
int ModeLighten(int basePixel,int mixPixel);//变亮模式
int ModeFilterColor(int basePixel,int mixPixel);//滤色模式
int ModeColorLighten(int basePixel,int mixPixel);//颜色减淡模式
int ModeColorLinearLighten(int basePixel,int mixPixel);//颜色线性减淡模式
int* ModeLightColor(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue);//浅色模式
int ModeSuperposition(int basePixel,int mixPixel);//叠加模式
int ModeSmoothLight(int basePixel,int mixPixel);//柔光模式
int ModeStrongLight(int basePixel,int mixPixel);//强光模式
int ModeHightLight(int basePixel,int mixPixel);//亮光模式
int ModeLinearLight(int basePixel,int mixPixel);//线性光模式
int ModePointLight(int basePixel,int mixPixel);//点光模式
int* ModeSolidColorMixing(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue);
int ModeDifference(int basePixel,int mixPixel);//差值模式
int ModeExclude(int basePixel,int mixPixel);//排除模式
int ModeSubtract(int basePixel,int mixPixel);//减去模式
int ModeDivide(int basePixel,int mixPixel);//划分模式
int ModeGray(int red,int green,int blue);//去色
int* ModeColorInverse(int red,int green,int blue);//反相
int CheckRange(int value);
int CheckValue(int value);
int getPSGray(int pixel);
#endif
Specialeffect.c
#include
#include
#include
#include
#include
/*int CheckValue(int value)
{
return (value & ~0xff)==0?value:value>255?255:0;
};*/
int CheckRange(int value)
{
return (value & ~0xff)==0?value:value>255?255:0;
/*int res = 0;
res = value > 255 ? 255 : (value < 0 ? 0 : value);
return res*/;
};
int ModeGray(int red,int green,int blue)
{
int min = 0,max = 0;
min = red < green ? (red < blue ? red : blue) : (green
max = red > green ? (red > blue ? red : blue) : (green>blue?green:blue);
return (min + max)/2;
};
int getPSGray(int pixel)
{
int red = 0,green = 0,blue = 0,min = 0,max = 0;
red = ((pixel >> 16) & 0xFF);
green = ((pixel >> 8) & 0xFF);
blue = (pixel & 0xFF);
min = red < green ? (red < blue ? red : blue) : (green
max = red > green ? (red > blue ? red : blue) : (green>blue?green:blue);
return (min + max)/2;
};
int ModeDarkness(int basePixel,int mixPixel)
{
int res = 0;
res = (basePixel>mixPixel?mixPixel:basePixel);
return res;
};
int ModeMultiply(int basePixel,int mixPixel)
{
int res = 0;
res = mixPixel * basePixel / 255;
return CheckRange(res);
};
int ModeColorDark(int basePixel,int mixPixel)
{
int res = 0;
int temp = basePixel + mixPixel - 255;
temp = temp<0?0:temp;
if(mixPixel==0)
return basePixel;
res = temp * 255 / mixPixel;
return CheckRange(res);
};
int ModeLinearDark(int basePixel,int mixPixel)//结果色 = 基色 + 混合色 - 255
{
int res = 0;
res = basePixel + mixPixel - 255;
return CheckRange(res);
};
int* ModeDark(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue)//??
{
int baseSum = 0, mixSum = 0;
int* res = (int*)malloc(sizeof(int)*3);
baseSum = baseRed + baseGreen + baseBlue;
mixSum = mixRed + mixGreen + mixBlue;
if(baseSum
{
res[0] = baseRed;
res[1] = baseGreen;
res[2] = baseBlue;
}
else
{
res[0] = mixRed;
res[1] = mixGreen;
res[2] = mixBlue;
}
return res;
};
int ModeLighten(int basePixel,int mixPixel)
{
int res = 0;
res = (basePixel>mixPixel?basePixel:mixPixel);
return res;
};
int ModeFilterColor(int basePixel,int mixPixel)//255 - 混合色的补色 * 基色补色 / 255
{
int res = 0;
res = 255 - (255 - mixPixel) * (255 - basePixel) / 255;
return CheckRange(res);
};
int ModeColorLighten(int basePixel,int mixPixel)//结果色 = 基色 + (混合色 * 基色) / (255 - 混合色)
{
int res = 0;
res = basePixel + (basePixel * mixPixel) / (256 - mixPixel);
return CheckRange(res);
};
int ModeColorLinearLighten(int basePixel,int mixPixel)
{
int res = 0;
res = basePixel + mixPixel;
return CheckRange(res);
};
int* ModeLightColor(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue)//??
{
int baseSum = 0, mixSum = 0;
int* res = (int*)malloc(sizeof(int)*3);
baseSum = baseRed + baseGreen + baseBlue;
mixSum = mixRed + mixGreen + mixBlue;
if(baseSum>mixSum)
{
res[0] = baseRed;
res[1] = baseGreen;
res[2] = baseBlue;
}
else
{
res[0] = mixRed;
res[1] = mixGreen;
res[2] = mixBlue;
}
return res;
};
int ModeSuperposition(int basePixel,int mixPixel)//基色 < = 128:结果色 = 混合色 * 基色 / 128;基色 > 128:结果色 = 255 - (255 - 混合色)* (255 - 基色) / 128
{
int res = 0;
res = ((basePixel <= 128) ? (mixPixel * basePixel / 128):(255 - (255 - mixPixel) * (255 - basePixel) / 128));
return CheckRange(res);
};
int ModeSmoothLight(int basePixel,int mixPixel)
{
int res = 0;
res = mixPixel > 128 ? ((int)((float)basePixel+((float)mixPixel+(float)mixPixel-255.0f)*((sqrt((float)basePixel/255.0f))*255.0f-(float)basePixel)/255.0f)):
((int)((float)basePixel+((float)mixPixel+(float)mixPixel-255.0f)*((float)basePixel-(float)basePixel*(float)basePixel/255.0f)/255.0f));
return CheckRange(res);
};
int ModeStrongLight(int basePixel,int mixPixel)
{
int res = 0;
res = mixPixel <= 128 ? (mixPixel * basePixel / 128):(255 - (255 - mixPixel) * (255 - basePixel) / 128);
return CheckRange(res);
};
int ModeHightLight(int basePixel,int mixPixel)
{
int res = 0;
if (mixPixel <= 128)
res = mixPixel == 0 ? basePixel : (basePixel - (255 - basePixel)*(255-2*mixPixel) / (2 * mixPixel));
else
res = mixPixel == 255 ? basePixel : basePixel+ (basePixel*(2*mixPixel-255))/(255-(2*mixPixel-255));
return CheckRange(res);
};
int ModeLinearLight(int basePixel,int mixPixel)
{
int res = 0;
res = 2 * mixPixel + basePixel - 255;
return CheckRange(res);
};
int ModePointLight(int basePixel,int mixPixel)
{
int res = 0;
int a = mixPixel + mixPixel - 255;
int b = mixPixel + mixPixel;
if(basePixel < a)
res = b - 255;
if(basePixel >= a && basePixel < b)
res = basePixel;
if(basePixel > b)
res = b;
return CheckRange(res);
};
int* ModeSolidColorMixing(int baseRed,int baseGreen,int baseBlue,int mixRed,int mixGreen,int mixBlue)
{
int* res = (int*)malloc(sizeof(int)*3);
res[0] = baseRed + mixRed;
res[1] = baseGreen + mixGreen;
res[2] = baseBlue + mixBlue;
res[0] = res[0]>255?255:0;
res[1] = res[1]>255?255:0;
res[2] = res[2]>255?255:0;
return res;
};
int ModeDifference(int basePixel,int mixPixel)
{
int res = 0;
res = abs(mixPixel - basePixel);
return res;
};
int ModeExclude(int basePixel,int mixPixel)
{
int res = 0;
res = (mixPixel + basePixel) - mixPixel * basePixel / 128;
return CheckRange(res);
};
int ModeSubtract(int basePixel,int mixPixel)
{
int res = 0;
res = basePixel - mixPixel;
return CheckRange(res);
};
int ModeDivide(int basePixel,int mixPixel)
{
int res = 0;
if(mixPixel == 0)
return basePixel;
res = 255 * basePixel / mixPixel;
return CheckRange(res);
};
int* ModeColorInverse(int red,int green,int blue)
{
int* res = (int*)malloc(sizeof(int)*3);
res[0] = 255 - red;
res[1] = 255 - green;
res[2] = 255 - blue;
return res;
};
demo: http://www.zealfilter.com/forum.php?mod=viewthread&tid=70&extra=page%3D1