QQ群聊的背景色為白色,而打開圖片后的背景色為黑色,如果能巧妙修改圖片各個像素的透明度,就可以達到在不同背景下顯示出不同圖片的功能,
目錄
效果
原理分析
透明度疊加演算法
灰度圖演算法
黑白圖演算法
彩色圖演算法
影像放縮
界面設計
源檔案
???????
效果
點開前:

點開后:

原理分析
我們已經知道是通過修改透明度來實作這個效果,現在只需要計算出透明度就行了,
假設有兩張圖片,一張是在白色背景下可以看到的,我們稱之為“白圖”,另一種是在黑色背景下才能看到的,我們稱之為“黑圖”,為了把兩張圖混合在一起,對任意像素點G(i,j),計算(i+j),根據即奇偶性來選擇顯示白圖還是黑圖,相當于把兩張圖片穿插在一起,整體上看起來不會有任何例外,
對于透明度具體怎么計算,下面提供了三種思路,
透明度疊加演算法
設有兩張圖A,B,A在B的上面,B的不透明度為255(0表示全透明,255表示不透明),A的不透明度為alpha,則實際看到的像素值為
![]()
灰度圖演算法
設白圖在點(i,j)處像素值為G',求出灰度值G,通常采用的灰度值演算法為
![]()
現在已經知道了灰度值G,我們希望它能在白色背景下顯示出原圖的灰度圖,此時前景色為黑色,背景色為白色,列出運算式:
![]()
得到alpha = 255-G,即G的反色,
設黑圖在(i,j)處的灰度值為G,此時前景色為白色,背景色為黑色,列出運算式:
![]()
得到alpha = G,
所以對于白圖,把它的不透明度設定為255 - G,對于黑圖,把它的不透明度設定為G,就能做到在白色背景下能看到白圖,在黑色背景下能看到黑圖的效果,
演算法代碼:
private static Bitmap Merge_GRAY(Bitmap p1, Bitmap p2)
{
bool flag;//判斷顯示白圖還是黑圖
Color color;
int transparency;//不透明度
Bitmap bitmap = new Bitmap(p1.Width, p1.Height);
for (int i = 0; i < p1.Width; i++)
{
for (int j = 0; j < p1.Height; j++)
{
flag = (i + j) % 2 == 0;
if (flag)
{
color = p1.GetPixel(i, j);
//R,G,B為靜態變數,分別是299,587,114
transparency = (color.R * R + color.G * G + color.B * B) / 1000;
bitmap.SetPixel(i, j, Color.FromArgb(255 - transparency, Color.Black));
}
else
{
color = p2.GetPixel(i, j);
transparency = (color.R * R + color.G * G + color.B * B) / 1000;
bitmap.SetPixel(i, j, Color.FromArgb(transparency, Color.White));
}
}
}
return bitmap;
}
黑白圖演算法
與灰度圖類似,但是要將灰度值用黑白兩種顏色來代替,所以需要先遍歷整張圖,計算平均灰度值,把高于平均值的一律替換成白色,即255,把低于平均值的一律替換成黑色,即0
private static Bitmap Merge_BLACK_AND_WHITE(Bitmap p1, Bitmap p2)
{
bool flag;
Color color;
int RGB;
Bitmap bitmap = new Bitmap(p1.Width, p1.Height);
int[,] gray1 = new int[p1.Width,p1.Height];
int[,] gray2 = new int[p1.Width, p1.Height];
int sum1 = 0, sum2 = 0;
for (int i = 0; i < p1.Width; i++)
{
for (int j = 0; j < p1.Height; j++)
{
color = p1.GetPixel(i,j);
gray1[i, j] = (color.R * R + color.G * G + color.B * B) / 1000;
sum1 += gray1[i, j];
color = p2.GetPixel(i, j);
gray2[i, j] = (color.R * R + color.G * G + color.B * B) / 1000;
sum2 += gray2[i, j];
}
}
sum1 /= p1.Width * p1.Height;
sum2 /= p1.Width * p1.Height;
for(int i = 0; i < p1.Width; i++)
{
for(int j = 0; j < p1.Height; j++)
{
flag = (i + j) % 2 == 0;
if (flag)
{
RGB = gray1[i, j] > sum1 ? 0 : 255;
bitmap.SetPixel(i, j, Color.FromArgb(RGB, Color.Black));
}
else
{
RGB = gray2[i, j] > sum2 ? 0 : 255;
bitmap.SetPixel(i, j, Color.FromArgb(255 - RGB, Color.White));
}
}
}
return bitmap;
}
彩色圖演算法
若一張白圖想要在白色背景下顯示,設不透明度為alpha,列出運算式
![]()
顯然alpha為255
當這張圖在黑色背景下時,需要它完全隱藏,
![]()
顯然alpha=0
為什么會出現兩個完全相反的答案,而之前不會?原來之前的灰度圖中,使用灰色像素來顯示白圖,在白色背景下通過不透明度讓灰色像素顯示,而在黑色背景下,灰色像素有顏色優勢,無論不透明度是多少都不影響它在黑色背景下隱藏,但是彩色像素就不一樣了,如果不透明度太大,會導致它在黑色背景下無法隱藏,最終出現兩個圖顯示在一起的效果,
現在的問題在于:如果要圖片更清晰,則需要增大不透明度,如果要白圖黑圖互不干擾,則需要減少不透明度,顯然減少黑白圖的相互干擾比清晰顯示更重要,白圖在黑色背景下,灰度值越高(顏色越白),則不透明度應該越低,
所以我們得出結論,不透明度應隨著灰度值的增大而減小,且具有相同區間[0,255],顯然正比例函式就具有上述特性
設不透明度alpha,灰度值G = (0.299R+0.587G+0.114B) / 3;
![]()
代入(0,255),(255,0),得到 k = -1, m = 255,
當然不一定是一次函式,也可以是二次函式,但是實作起來較為復雜,所以不考慮,
現在我們得到alpha = 255 - G,這是白圖的計算方法,
對于黑圖,它想要在黑色背景下顯示,因此灰度值越大(顏色越白),不透明度越高,即不透明度與灰度值也成正比,我們也用上面那式子來代入計算,
得到 alpha = G,這是黑圖的計算方法,
代碼:
private static Bitmap Merge_COLORFUL(Bitmap p1,Bitmap p2)
{
bool flag;
Color color;
int transparency;
Bitmap bitmap = new Bitmap(p1.Width, p1.Height);
for (int i = 0; i < p1.Width; i++)
{
for (int j = 0; j < p1.Height; j++)
{
flag = (i + j) % 2 == 0;
if (flag)
{
color = p1.GetPixel(i, j);
transparency = (color.R * R + color.G * G + color.B * B) / 1000;
bitmap.SetPixel(i, j, Color.FromArgb(255 - transparency, p1.GetPixel(i, j)));
}
else
{
color = p2.GetPixel(i, j);
transparency = (color.R * R + color.G * G + color.B * B) / 1000;
bitmap.SetPixel(i, j, Color.FromArgb(transparency, p2.GetPixel(i,j)));
}
}
}
return bitmap;
}
影像放縮
想要讓兩種圖片混合,顯然它們必須具有相同的寬度和高度,使用C#自帶的放縮方法即可完成
private static Bitmap Scale(Bitmap b,int width,int height)
{
Bitmap bitmap = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bitmap);
g.InterpolationMode = interpolationMode;
g.DrawImage(b, new Rectangle(0, 0, width, height), new Rectangle(0, 0, b.Width, b.Height), GraphicsUnit.Pixel);
g.Dispose();
return bitmap;
}
界面設計
主界面顯示黑白兩種顏色,分別用來模擬白色和黑色背景,

下圖左右兩邊顯示出不同的圖片,實際上是同一張,由于背景色的緣故看起來不同,這就是QQ上的最終效果,

點擊“原圖”后顯示原來的圖片,點擊“匯出”后把生成的圖片保存到本地,
設定里提供了高度自定義功能,可以修改灰度演算法的引數,圖片比例,放縮演算法和圖片型別,

源檔案
源檔案:https://dearx.lanzoui.com/iYPmas7wofg
EXE檔案:https://dearx.lanzoui.com/iPar7s7wpre
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292141.html
標籤:其他
上一篇:什么是人工智能?
