为什么 Graphics.DrawImage() 会改变颜色不使用调整大小?

问题描述

这是另一个问题的简短测试,我尝试使用 ImageAttributes.SetRemapTable() 替换图像中的颜色。我发现 Graphics.DrawImage() 也会改变其他颜色,这些颜色不属于颜色映射。

因此我在 Graphics.DrawImage() 上创建了一个小测试。
我希望两个保存的图像是相同的:

  var bitmap = new Bitmap (1,1,PixelFormat.Format32bppArgb);
  bitmap.SetPixel(0,Color.FromArgb(10,10,10));
  bitmap.Save (@"bitmap1.png",ImageFormat.Png);

  var bitmap2 = new Bitmap (1,PixelFormat.Format32bppArgb);
  var graphics = Graphics.FromImage(bitmap2);
  graphics.DrawImage(bitmap,Point.Empty);
  bitmap2.Save (@"bitmap2.png",ImageFormat.Png);

bitmap1 中像素的 ARGB 为 10,10
bitmap2 中像素的 ARGB 为 10,0

为什么 DrawImage() 没有像我预期的那样绘制?
我怎样才能得到预期的结果?

我不想创建自己的颜色替换方法;我希望 .net 的颜色映射正常工作。

编辑
我做了另一个测试,同样的 1 像素图像,但我使用了 ARGB 10,10,而不是 ARGB 100,100,100输出像素现在具有 ARGB 100,99,99
在我看来,这像是 GDI+ 或 .Net 中的错误,但绝对不是预期的计算输出

而且,为了确保它不是由 1 个像素的宽度和高度引起的另一项改进,我改为

  var bitmap = new Bitmap (5,5,PixelFormat.Format32bppArgb);
  bitmap.SetPixel(2,2,Color.FromArgb(100,100));

再一次,输出像素是 ARGB 100,99
这现在看起来像是舍入错误,但上面的 10,0 绝对不是舍入错误

编辑 2
现在看起来都像是舍入错误:像素颜色的计算似乎舍入了例如在除法之后(可能除以整数),所以舍入误差乘以另一个乘法。
此测试使用 16x16 和 RGB 20,255 和 Alpha 0(左上角)到 255(右下角)。
Beyond Compare中bitmap1(左)和bitmap2(右)的比较,底部的结果(结果图像的对比度增加),表明在低alpha时差异很大,在高alpha时在RGB中向1或0减小:

enter image description here


示例值:

Pixel 0|0: Left = ARGB 0,20,255; Right = ARGB 0,0.  
Pixel 1|0: Left = ARGB 1,255; Right = ARGB 1,255.  
Pixel 2|0: Left = ARGB 2,255; Right = ARGB 2,127,255.  
Pixel 3|0: Left = ARGB 3,255; Right = ARGB 3,85,255. (85 = 1/3*255 => obvIoUsly division by alpha 3)
Pixel 3|0: Left = ARGB 4,255; Right = ARGB 4,255. (127 = 2/4*255 => obvIoUsly division by alpha 4)
Pixel 5|0: Left = ARGB 5,255; Right = ARGB 5,102,255. (102 = 2/5*255 => obvIoUsly division by alpha 5)
Pixel 15|0: Left = ARGB 15,255; Right = ARGB 15,17,255. (17 = 1/15*255 => obvIoUsly division by alpha 15)
Pixel 14|15: Left = ARGB 254,255; Right = ARGB 254,254.
Pixel 15|15: Left = ARGB 255,255; Right = ARGB 255,255.

是否有其他方法可以绘制部分透明的图像?

解决方法

问题背后的目的是交换图像中的颜色。交换的颜色包括透明度(alpha 因此,最后,我创建了自己的方法:

const connection = await db.connection();
    try {
        await connection.query("START TRANSACTION");
        await connection.query('delete from X where id=?',[bar.id]);
        await connection.query('INSERT INTO X (...) values (...)
        await connection.query("COMMIT");