2014-02-28 15 views
1

이 문제에 대한 샘플 코드는, 그래서 대부분 설명이 필요하다 :이 경우Image.Clear (x) 이후의 색상이 x 색상과 정확히 일치하지 않는 이유는 무엇입니까?

[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); 
} 

나는 배경의 색이 나는 그것이 클리어 컬러와 동일 할 것으로 예상한다. 대신 나는 이것을 얻는다 :

Assert.Equal() Failure 

Expected: Color [A=30, R=60, G=90, B=120] 
Actual: Color [A=30, R=59, G=93, B=119] 

이것은 어떻게 가능한가?

일부 통과 : 실패

Color.FromArgb(0, 0, 0, 0); 
Color.FromArgb(255, 255, 255, 255); 

좀 더 예 :

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] 
+0

PS : 검색했습니다. 이게 중복 된 것 같지 않아, 내가 찾을 수있는 가장 가까운 성냥은 http://stackoverflow.com/questions/721324/using-toargb-followed-by-fromargb-does-not-result-in-the-original- color 및 http://stackoverflow.com/questions/2032398/why-does-color-isnamedcolor-not-work-when-i-create-a-color-using-color-fromargb – nathanchere

답변

1

redwyre의 코멘트 @는 (그러나 나는 나 자신이 언급하기에 충분한 명성을하지 않는) 올바른 것입니다. 그래서 Drawing PixelFormat32bppPARGB images with GDI+ uses conventional formula instead of premultiplied one에서 빈센트 Povirk의 코멘트에 당신을 참조 할 수 있습니다 :

문제가되지 않는 전경 이미지의 형식을 당신이에는 GDIPlus :: 컬러로 설정하고 있기 때문에 (이 알파를 가지고 주어진). 색상 값은 미리 곱하지 않은 것으로 정의되므로 gdiplus는 전경 이미지를 지울 때 알파 값으로 구성 요소를 곱합니다. 대안은 렌더링 대상의 형식에 따라 색상 값이 다른 의미를 가지므로 그 방법은 광기입니다.

해당 게시물의 예

직접에는 GDIPlus을 사용하지만 당신은 .NET 소스에 here를 볼 수있는 다음, 그래서 System.Drawing.Graphics 않습니다.

다른 값은 색상 채널 값에서 미리 곱한 값으로, 그리고 8 비트 산술을 사용하여 다시 올림하는 것과 직접 관련이 있습니다. (예 : 마지막 예에서 알파 = 32 및 B = 90 : 90 * 32/255 = 11.2+는 11로 자르고 11은 255 * 328 = 87.6+는 87로 자릅니다.)

+0

PixelFormat32bppPArgb와 PixelFormat32bppArgb를 모두 시도해 보았습니다. 그 결과에 대해 (64 비트 PArgb 등) 동일한 결과가 나왔습니다. 사후 계산 된 알파가 정확히 동일한 반올림 오류를 생성하기를 기대하지 않습니다. 그렇지 않으면 알파 채널을 미리 곱하기가 무엇입니까? – nathanchere

+0

또한 위의 주 예제 ('[A = 30, R = 60, G = 90, B = 120]')를 사용하면 어떻게 G가 93으로 끝날 수 있습니까? 작동하도록 강조 표시된 90 -> 87 예제의 경우 11.2를 0으로 반올림해야합니다. 90-> 93 예제의 경우 0에서 10.5를 반올림하고 (심지어 94에서 93이 아닐 때까지만) 작동합니다. 결과의 불일치는 '버그'를 가능성으로 생각합니다. – nathanchere

+0

@nathanchere - 결과가 반올림되기 때문에 90-> 93 예제도 작동합니다. 나는 위의 예에서 그랬기 때문에 위의 내용을 잘라 냈지만 산술은 실제로 반올림했다. 94 대 93 문제는 컴퓨터 산술을위한 표준으로, 우리가 학교에서 배운 방식을 항상 반올림하지는 않습니다 (예 : 0.5 라운드 업). 실제로, 컴퓨터 산술은 빈번하게 0을 향해 라운딩한다. 실제로, 동일한 아키텍처에 대한 상이한 명령어는, 예를 들면 일반 레지스터에서의 통상 명령어와 SIMD 레지스터 (SSE와 같은)에서의 SIMD 명령어와 같이 다르게 라운드 될 수있다. – davidbak