我正在使用C#编写绘图程序原型。
我生成一个“画笔”图像,我按照鼠标位置混合到目标图像上。它有效,但在同一个地方反复混合会产生伪影。特别是,画笔上的透明像素会使目标图像变暗。
这是带有工件的画笔和目标图像。右边是相应的alpha通道。当我使用平刷(半透明光盘)时,最后一行显示正确的结果。
我制作了一个说明问题的示例程序。
public static Bitmap GenerateBrush(double radius, Func<double, double, double> curve)
{
int npx = (int)Math.Ceiling(radius) * 2 + 1;
Bitmap bmp = new Bitmap(npx, npx, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
for (int ix = 0; ix < npx; ix++) {
for (int iy = 0; iy < npx; iy++) {
double fx = 2.0 * ix / (double)(npx - 1) - 1.0;
double fy = 2.0 * iy / (double)(npx - 1) - 1.0;
double res = curve(fx, fy);
bmp.SetPixel(ix, iy, Color.FromArgb((int)(res * 255), 255, 255, 255));
}
}
return bmp;
}
static void Main(string[] args)
{
var bmpDest = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
var graphDest = Graphics.FromImage(bmpDest);
graphDest.Clear(Color.FromArgb(0, 255, 255, 255));
var bmpSrc = GenerateBrush(40, delegate(double x, double y) {
double d = Math.Max(1.0 - Math.Sqrt(x * x + y * y), 0.0);
return 0.5 + Math.Sin((d - 0.5) * Math.PI) / 2;
});
var im = new ImageAttributes();
im.SetColorMatrix(new ColorMatrix(
new float[][] {
new float[] { 1, 0, 0, 0, 0 },
new float[] { 0, 1, 0, 0, 0 },
new float[] { 0, 0, 0, 0, 0 },
new float[] { 0, 0, 0, 0.3f, 0 },
new float[] { .0f, .0f, .0f, .0f, 1 }
}
));
int nsteps = 2000;
for (int i = 0; i < nsteps; i++) {
var t = i / (float)nsteps;
var xpos = 60 + (int)(Math.Sin(t*Math.PI*40) * 50);
var ypos = 60 + (t>0.5 ? 20: -20);
graphDest.DrawImage(bmpSrc, new Rectangle(xpos, ypos, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel, im);
}
bmpDest.Save(@"test.png");
}
在我看来,这可能是由于GDI +混合透明图像的方式存在精确问题。有什么想法吗?
- 编辑
没有颜色矩阵的同样问题(删除DrawImage()中的最后一个参数):
- 编辑2
似乎没有人对此有答案 - 这个问题不够明确吗?
答案 0 :(得分:1)
是的,截断错误正在累积。您可以尝试使用PixelFormat.Format32bppPArgb
模式拍摄图像,但我不确定它会有所帮助。
确保解决方法是将画笔笔划累积到单通道图像中,然后将该结果用作画布在画布上绘画。
答案 1 :(得分:0)
您是否尝试过调整图形对象的SmoothingMode?当你从左到右移动画笔时,看起来可能会发生额外的插值。