【发布时间】:2021-02-08 15:31:11
【问题描述】:
这是对另一个问题的简短测试,我尝试使用ImageAttributes.SetRemapTable() 替换图像中的颜色。我发现Graphics.DrawImage() 也改变了其他颜色,这不是颜色映射的一部分。
因此,我在 Graphics.DrawImage() 上创建了一个小测试。
我希望两个保存的图像是相同的:
var bitmap = new Bitmap (1, 1, PixelFormat.Format32bppArgb);
bitmap.SetPixel(0,0,Color.FromArgb(10,10,10,10));
bitmap.Save (@"bitmap1.png", ImageFormat.Png);
var bitmap2 = new Bitmap (1, 1, PixelFormat.Format32bppArgb);
var graphics = Graphics.FromImage(bitmap2);
graphics.DrawImage(bitmap, Point.Empty);
bitmap2.Save (@"bitmap2.png", ImageFormat.Png);
bitmap1 中像素的 ARGB 为 10,10,10,10。bitmap2中像素的ARGB为10,0,0,0。
为什么DrawImage() 没有像我预期的那样绘制?
我怎样才能得到预期的结果?
我不想创建自己的颜色替换方法;我希望 .net 的颜色映射能够正常工作。
编辑
我做了另一个测试,同样的 1 像素图像,但不是 ARGB 10,10,10,10,而是 ARGB 100,100,100,100。输出像素现在具有 ARGB 100,99,99,99。
在我看来,这就像 GDI+ 或 .Net 中的错误,但绝对不是预期的计算输出。
而且,为了确保它不是由 1 个像素的宽度和高度引起的,我更改为
var bitmap = new Bitmap (5, 5, PixelFormat.Format32bppArgb);
bitmap.SetPixel(2,2,Color.FromArgb(100,100,100,100));
再一次,输出像素是 ARGB 100,99,99,99。
现在看起来像是舍入错误,但上面的 10,0,0,0 绝对不是舍入错误。
编辑 2
现在看起来都像舍入错误:像素颜色的计算似乎是舍入的,例如在一个除法之后(可能是一个整数),所以舍入误差在另一个乘法中相乘。
此测试使用 16x16,RGB 为 20,100,255,Alpha 0(左上角)到 255(右下角)。
Beyond Compare中bitmap1(左)和bitmap2(右)的比较,结果在底部(结果图像的对比度增加),表明差异在低alpha时很高,在RGB中的差异在高alpha时向1或0减小:
示例值:
Pixel 0|0: Left = ARGB 0,20,100,255; Right = ARGB 0,0,0,0.
Pixel 1|0: Left = ARGB 1,20,100,255; Right = ARGB 1,0,0,255.
Pixel 2|0: Left = ARGB 2,20,100,255; Right = ARGB 2,0,127,255.
Pixel 3|0: Left = ARGB 3,20,100,255; Right = ARGB 3,0,85,255. (85 = 1/3*255 => obviously division by alpha 3)
Pixel 3|0: Left = ARGB 4,20,100,255; Right = ARGB 4,0,127,255. (127 = 2/4*255 => obviously division by alpha 4)
Pixel 5|0: Left = ARGB 5,20,100,255; Right = ARGB 5,0,102,255. (102 = 2/5*255 => obviously division by alpha 5)
Pixel 15|0: Left = ARGB 15,20,100,255; Right = ARGB 15,17,102,255. (17 = 1/15*255 => obviously division by alpha 15)
Pixel 14|15: Left = ARGB 254,20,100,255; Right = ARGB 254,20,100,254.
Pixel 15|15: Left = ARGB 255,20,100,255; Right = ARGB 255,20,100,255.
是否有其他方法可以绘制部分透明的图像?
【问题讨论】:
-
根据this post 的说法,使用 1x1 位图会将整个图像缩小到其边界,因此会弄乱所有 1 个像素。解决方案(使用带有半像素的 RectangleF)是否有助于实现您的目标将取决于细节..
-
@TaW:查看我的编辑
-
并不是说它在这里改变了问题,你从来没有像人们需要的那样设置
CompositingMode.SourceCopy.. -
@TaW:谢谢,这可能会解决另一个问题。但正如您已经指出的那样,它并不能解决这个问题。
-
“是否有其他方法可以绘制部分透明的图像?” -- 当然可以。您还尝试过哪些其他替代方案?到目前为止,您找到了哪些但还没有尝试过?您具体需要哪些帮助?显然,对于像素到像素的精确保真度,您可以
LockBits()并自己执行复制。或者:stackoverflow.com/a/4597984。我会指出,我已经尝试过您的场景,并且我发现当两个位图(原始和副本)被绘制到屏幕上时,屏幕上的实际像素值是相同的,尽管.. .
标签: c# colors graphics drawimage