影象演算法 -- 最全混合圖層演算法(附原始碼)

峻峰飛陽發表於2017-09-08

混合圖層演算法

本文中的混合圖層跟PhotoShop中完全一致。

 

1正常模式:混合色*不透明度+100%-混合色不透明度)

2溶解模式:溶解模式下混合色的不透明度及填充都是100%的話,我們就看不到基色圖層。降低混合色圖層的不透明度後,我們就會發現結果色中出現了很多細小的顆粒。這些顆粒會隨著混合色的不透明度變化。不透明度越低混合色圖層就被溶解的越多。剩下的部分就越少。不透明度越高混合色圖層被溶解的部分就越少,剩下的部分就越多,結果色就越接近混合色。

3變暗模式:變暗混合模式下,它會把混合色與基色進行對比,分別選擇RGB三組數值中最小的數值,也就是最暗的顏色作為結果色的數值。這樣整個畫面會變得更暗,如果是彩色影象,顏色也會發生很大的改變。(位置互換不發生變化)

4正片疊底:正片疊底混合原理:它是按照混合色與基色中的各RGB值計算,計算公式:結果色R=混合色R * 基色R / 255G值與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。數值大於255255

18點光:點光模式:它會根據混合色的顏色數值替換相應的顏色。如果混合色數值小於中性灰色,那麼就替換比混合色亮的畫素;相反混合色的數值大於中性灰色,則替換比混合色暗的畫素,因此混合出來的顏色對比較大。
計算公式:
基色 < 2 * 混合色 - 255:結果色 = 2 * 混合色 - 255
2 * 混合色 - 255 < 基色 < 2 * 混合色 :結果色 = 基色;
基色 > 2 * 混合色:結果色 = 2 * 混合色。

19實色混合 實色混合是把混合色顏色中的紅、綠、藍通道數值,新增到基色的RGB值中。結果色的RGB通道的數值只能是2550。因此結構色只有一下八種可能:紅、綠、藍、黃、青、洋紅、白、黑。由此看以看出結果色是非常純的顏色。

 

計算公式:

混合色 + 基色 < 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


(原文:http://blog.csdn.net/bravebean/article/details/51392440)

相關文章