C# GDI+;错误:透明度上的抗锯齿白色
下面的代码将创建一个透明位图,然后在其上绘制一个带抗锯齿的白色椭圆C# GDI+;错误:透明度上的抗锯齿白色,c#,gdi+,transparent,antialiasing,C#,Gdi+,Transparent,Antialiasing,下面的代码将创建一个透明位图,然后在其上绘制一个带抗锯齿的白色椭圆 using(var background = new Bitmap(500, 500)) using (var graphics = Graphics.FromImage(background)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.Clear(Color.Transparent); graphics.DrawEll
using(var background = new Bitmap(500, 500))
using (var graphics = Graphics.FromImage(background))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.Clear(Color.Transparent);
graphics.DrawEllipse(new Pen(Color.White, 50), 250, 250, 150, 150);
background.Save("test.png", ImageFormat.Png);
}
我发现的错误是椭圆边缘周围的抗锯齿像素具有意外的颜色。它们的RGB值为(25425)而不是(255255)。既然GDI+将透明定义为ARGB(0255255),白色定义为(255255),为什么混合后我会看到254?在Mono(Mac OS X)中从SVG生成PNG时,我遇到了相同的问题,但由于某些原因,在Windows上没有 为了解决这个问题,我将最接近的rgb值从图形复制到了抗锯齿像素,但保留了抗锯齿alpha值 代码基于以下示例: 要作为保存方法之前的最后一步运行的代码:
var pxf = PixelFormat.Format32bppArgb;
var rect = new Rectangle(0, 0, image.Width, image.Height);
BitmapData bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, pxf);
IntPtr ptr = bmpData.Scan0;
int numBytes = image.Width * image.Height * 4;
byte[] rgbValues = new byte[numBytes];
Marshal.Copy(ptr, rgbValues, 0, numBytes);
for (int argb = 0; argb < rgbValues.Length; argb += 4) {
var a = rgbValues [argb + 3]; //A
if(a > 0x00 && a < 0xFF) { //Antialiasing:
//Scan for neares solid with 0 transparency:
for (int i = 0; i < 3; i++) { //3 pixels scan seems to be enough
var right = argb + i * 4;
var left = argb - i * 4;
var up = argb - i * image.Width * 4;
var down = argb + i * image.Width * 4;
if (right < rgbValues.Length && rgbValues [right + 3] == 0xFF) {
rgbValues [argb+2] = rgbValues [right + 2]; //R
rgbValues [argb+1] = rgbValues [right + 1]; //G
rgbValues [argb] = rgbValues [right]; //B
break;
} else if (left > 0 && rgbValues [left + 3] == 0xFF) {
rgbValues [argb+2] = rgbValues [left + 2];
rgbValues [argb+1] = rgbValues [left + 1];
rgbValues [argb] = rgbValues [left];
break;
} else if (up > 0 && rgbValues [up + 3] == 0xFF) {
rgbValues [argb+2] = rgbValues [up + 2];
rgbValues [argb+1] = rgbValues [up + 1];
rgbValues [argb] = rgbValues [up];
break;
} else if (down < rgbValues.Length && rgbValues [down + 3] == 0xFF) {
rgbValues [argb+2] = rgbValues [down + 2];
rgbValues [argb+1] = rgbValues [down + 1];
rgbValues [argb] = rgbValues [down];
break;
}
}
//rgbValues [argb+3] = a; //Keep old alpha.
}
}
Marshal.Copy(rgbValues, 0, ptr, numBytes);
image.UnlockBits(bmpData);
var pxf=PixelFormat.Format32bppArgb;
var rect=新矩形(0,0,image.Width,image.Height);
BitmapData bmpData=image.LockBits(rect、ImageLockMode.ReadWrite、pxf);
IntPtr ptr=bmpData.Scan0;
int numBytes=image.Width*image.Height*4;
字节[]rgbValues=新字节[numBytes];
封送处理副本(ptr,rgb值,0,numBytes);
for(int argb=0;argb0x00&&a<0xFF){//抗锯齿:
//扫描透明度为0的近实体:
对于(inti=0;i<3;i++){//3像素的扫描似乎就足够了
var right=argb+i*4;
var left=argb-i*4;
var up=argb-i*image.Width*4;
var down=argb+i*image.Width*4;
if(right0&&RGB值[left+3]==0xFF){
RGB值[argb+2]=RGB值[left+2];
RGB值[argb+1]=RGB值[left+1];
RGB值[argb]=RGB值[左];
打破
}否则如果(向上>0&&RGB值[向上+3]==0xFF){
RGB值[argb+2]=RGB值[up+2];
RGB值[argb+1]=RGB值[up+1];
RGB值[argb]=RGB值[up];
打破
}else if(向下
`我想这是一个精度问题……背景颜色是什么?背景颜色是彩色的。透明ARGB(0255255)。因此,我不确定精度在哪里丢失。构成特定像素的前景颜色根据其亚像素前景覆盖率混合在一起,忽略背景的影响。您要求GDI+做一些不可能的事情:渲染将在任何背景下混合的抗锯齿像素。这在设计上不起作用,只有当背景颜色与混合颜色匹配时,图像边缘才会看起来很好。最好不要尝试,使用SmoothingMode。没有,你会得到一个纯白色的边缘。代码还需要4个方向,垂直、垂直、左下和右下。这很容易实现。