问题
The sample code for this issue is largely self-explanatory, so:
[Fact]
private void Color_in_should_equal_color_out()
{
var bitmap = new Bitmap(128,128,PixelFormat.Format32bppArgb);
var color = Color.FromArgb(30,60,90,120);
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(color);
}
var result = bitmap.GetPixel(0,0);
Assert.Equal(color, result);
}
In this instance I would expect the color of the background to be identical to the color I cleared it to. Instead I get this:
Assert.Equal() Failure
Expected: Color [A=30, R=60, G=90, B=120]
Actual: Color [A=30, R=59, G=93, B=119]
How is this even possible?
Some pass:
Color.FromArgb(0, 0, 0, 0);
Color.FromArgb(255, 255, 255, 255);
Some more examples that fail:
Expected: Color [A=32, R=64, G=96, B=128]
Actual: Color [A=32, R=63, G=95, B=127]
Expected: Color [A=128, R=192, G=32, B=16]
Actual: Color [A=128, R=191, G=31, B=15]
Expected: Color [A=32, R=192, G=127, B=90]
Actual: Color [A=32, R=191, G=127, B=87]
回答1:
@redwyre's comment is correct (but I don't have sufficient reputation myself to comment). So I'll refer you to Vincent Povirk's comment at Drawing PixelFormat32bppPARGB images with GDI+ uses conventional formula instead of premultiplied one:
The format of your foreground image doesn't matter (given that it has alpha) because you're setting it to a Gdiplus::Color. Color values are defined as non-premultiplied, so gdiplus multiplies the components by the alpha value when it clears the foreground image. The alternative would be for Color values to have different meaning depending on the format of the render target, and that way lies madness.
The example in that post uses Gdiplus directly, but then, so does System.Drawing.Graphics, as you can see here in the .NET sources.
The different values you see are directly related to round-tripping from color channel value to premultiplied value and back using 8-bit arithmetic. (E.g., from your last example, alpha=32 and B=90: 90*32/255 = 11.2+ truncates to 11 then back 11*255/32 = 87.6+ truncates to 87.)
来源:https://stackoverflow.com/questions/22086404/why-does-the-color-after-image-clearx-not-exactly-equal-the-color-x