我是这样解决这个问题的(background.png和colorWithAlpha.png具有相同的尺寸):
Bitmap bg = new Bitmap("background.png");
Bitmap overlay = new Bitmap("colorWithAlpha.png");
float m = 0;
Color c;
for (int i = 0; i < bg.Width; i++)
{
for (int j = 0; j < bg.Height; j++)
{
m = overlay.GetPixel(i, j).A / 255f;
c = HSVtoRGB(overlay.GetPixel(i,j).GetHue(), overlay.GetPixel(i,j).GetSaturation(), bg.GetPixel(i, j).GetBrightness());
c = Color.FromArgb((int)(m * c.R + (1 - m) * bg.GetPixel(i, j).R), (int)(m * c.G + (1 - m) * bg.GetPixel(i, j).G), (int)(m * c.B + (1 - m) * bg.GetPixel(i, j).B));
bg.SetPixel(i, j, c);
}
}
public static Color HSVtoRGB(float hue, float saturation, float value)
{
double h;
double s;
double v;
double r = 0;
double g = 0;
double b = 0;
h = ((double)hue / 255 * 360) % 360;
s = (double)saturation / 255;
v = (double)value / 255;
if (s == 0)
{
r = v;
g = v;
b = v;
}
else
{
double p;
double q;
double t;
double fractionalSector;
int sectorNumber;
double sectorPos;
sectorPos = h / 60;
sectorNumber = (int)(Math.Floor(sectorPos));
fractionalSector = sectorPos - sectorNumber;
p = v * (1 - s);
q = v * (1 - (s * fractionalSector));
t = v * (1 - (s * (1 - fractionalSector)));
switch (sectorNumber)
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
}
return Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255));
}
函数HSVtoRGB取自
https://bytes.com/topic/c-sharp/answers/236124-how-would-i-change-hue-bitmap,稍作调整,因为原始函数期望所有输入值都在0-255之间,所以必须去除缩放。