2013-04-11 6 views
1

다음 코드는 투명 비트 맵을 만든 다음 앤티 앨리어싱을 사용하여 흰색 타원을 그립니다.GDI + 버그 : 앤티 앨리어싱 흰색 투명도

using(var background = new Bitmap(500, 500)) 
using (var graphics = Graphics.FromImage(background)) 
{ 
    graphics.SmoothingMode = SmoothingMode.AntiAlias; 

    graphics.Clear(Color.Transparent); 

    graphics.DrawEllipse(new Pen(Color.White, 50), 250, 250, 150, 150); 

    background.Save("test.png", ImageFormat.Png); 
} 

내가 찾은 버그는 타원의 가장자리 주변의 앤티 앨리어싱 픽셀이 예상치 못한 색상을 가지고있다. RGB 값은 (255,255,255) 대신 (254,254,254)입니다. GDI +는 ARGB (0,255,255,255)와 흰색을 (255,255,255,255)로 정의했기 때문에 혼합 후 254가 왜 표시됩니까?

+0

을 ... 무슨

코드는의 예를 기반으로 배경 색상? – Sayse

+0

배경색은 Color.Transparent ARGB (0,255,255,255)입니다. 따라서 정밀도가 어느 정도 떨어져 있는지 확실하지 않습니다. – Zach

+0

특정 픽셀에 영향을 미치는 전경색은 하위 픽셀의 전경색 범위에 따라 혼합되어 배경에서의 영향을 무시합니다. http://www.w3.org/Conferences/WWW4/Papers/53/gq-trans.html – Sayse

답변

0

Mono (Mac OS X)의 SVG에서 PNG를 생성했을 때와 동일한 문제가 발생했지만 Windows가 아닌 이유가 있습니다.

이 문제를 해결하려면 그림에서 가장 가까운 rgb 값을 앤티 앨리어스 픽셀로 복사했지만 안티 알리아스 알파 값을 사용했습니다. 방법 저장하기 전에 같은 마지막 단계를 실행하는 https://msdn.microsoft.com/en-us/library/ms229672(v=vs.90).aspx

코드 : 나는 그것에게 정밀 문제를 상상

var pxf = PixelFormat.Format32bppArgb; 
var rect = new Rectangle(0, 0, image.Width, image.Height); 
BitmapData bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, pxf); 

IntPtr ptr = bmpData.Scan0; 

int numBytes = image.Width * image.Height * 4; 
byte[] rgbValues = new byte[numBytes]; 
Marshal.Copy(ptr, rgbValues, 0, numBytes); 

for (int argb = 0; argb < rgbValues.Length; argb += 4) { 
    var a = rgbValues [argb + 3]; //A 
    if(a > 0x00 && a < 0xFF) { //Antialiasing: 
     //Scan for neares solid with 0 transparency: 
     for (int i = 0; i < 3; i++) { //3 pixels scan seems to be enough 

      var right = argb + i * 4; 
      var left = argb - i * 4; 
      var up = argb - i * image.Width * 4; 
      var down = argb + i * image.Width * 4; 

      if (right < rgbValues.Length && rgbValues [right + 3] == 0xFF) { 
       rgbValues [argb+2] = rgbValues [right + 2]; //R 
       rgbValues [argb+1] = rgbValues [right + 1]; //G 
       rgbValues [argb] = rgbValues [right];  //B 
       break; 
      } else if (left > 0 && rgbValues [left + 3] == 0xFF) { 
       rgbValues [argb+2] = rgbValues [left + 2]; 
       rgbValues [argb+1] = rgbValues [left + 1]; 
       rgbValues [argb] = rgbValues [left]; 
       break; 
      } else if (up > 0 && rgbValues [up + 3] == 0xFF) { 
       rgbValues [argb+2] = rgbValues [up + 2]; 
       rgbValues [argb+1] = rgbValues [up + 1]; 
       rgbValues [argb] = rgbValues [up]; 
       break; 
      } else if (down < rgbValues.Length && rgbValues [down + 3] == 0xFF) { 
       rgbValues [argb+2] = rgbValues [down + 2]; 
       rgbValues [argb+1] = rgbValues [down + 1]; 
       rgbValues [argb] = rgbValues [down]; 
       break; 
      } 
     } 
     //rgbValues [argb+3] = a; //Keep old alpha. 
    } 
} 

Marshal.Copy(rgbValues, 0, ptr, numBytes); 

image.UnlockBits(bmpData); 

`

+0

코드에는 4 가지 방향, 위 방향, 수직 방향, 아래쪽 방향 및 완전히 수직 방향이 필요합니다. 이것은 쉽게 구현할 수 있습니다. – oddbear