2012-06-02 2 views
2

C#의 드로잉 프로그램 프로토 타입을 작성하고 있습니다.투명 이미지를 GDI +와 혼합 할 때의 결과

마우스 위치에 따라 대상 이미지 위에 혼합되는 "브러시"이미지를 생성합니다. 작동하지만 같은 장소에서 계속해서 혼합하면 유물이 생성됩니다. 특히 브러시의 투명한 픽셀은 대상 이미지를 어둡게하는 경향이 있습니다.

아티팩트가있는 브러시와 대상 이미지가 있습니다. 오른쪽에는 해당 알파 채널이 있습니다. 마지막 행은 플랫 브러시 (반투명 디스크)를 사용할 때 올바른 결과를 보여줍니다.

Bug illustrated

I는이 문제를 나타낸 샘플 프로그램을 만들었다.

public static Bitmap GenerateBrush(double radius, Func<double, double, double> curve) 
{ 
    int npx = (int)Math.Ceiling(radius) * 2 + 1; 
    Bitmap bmp = new Bitmap(npx, npx, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
    for (int ix = 0; ix < npx; ix++) { 
     for (int iy = 0; iy < npx; iy++) { 
      double fx = 2.0 * ix/(double)(npx - 1) - 1.0; 
      double fy = 2.0 * iy/(double)(npx - 1) - 1.0; 
      double res = curve(fx, fy); 
      bmp.SetPixel(ix, iy, Color.FromArgb((int)(res * 255), 255, 255, 255)); 
     } 
    } 
    return bmp; 
} 

static void Main(string[] args) 
{ 
    var bmpDest = new Bitmap(200, 200, PixelFormat.Format32bppArgb); 
    var graphDest = Graphics.FromImage(bmpDest); 
    graphDest.Clear(Color.FromArgb(0, 255, 255, 255)); 

    var bmpSrc = GenerateBrush(40, delegate(double x, double y) { 
     double d = Math.Max(1.0 - Math.Sqrt(x * x + y * y), 0.0); 
     return 0.5 + Math.Sin((d - 0.5) * Math.PI)/2; 
    }); 

    var im = new ImageAttributes(); 
    im.SetColorMatrix(new ColorMatrix(
     new float[][] { 
     new float[] { 1, 0, 0, 0, 0 }, 
     new float[] { 0, 1, 0, 0, 0 }, 
     new float[] { 0, 0, 0, 0, 0 }, 
     new float[] { 0, 0, 0, 0.3f, 0 }, 
     new float[] { .0f, .0f, .0f, .0f, 1 } 
     } 
    )); 

    int nsteps = 2000; 
    for (int i = 0; i < nsteps; i++) { 
     var t = i/(float)nsteps; 
     var xpos = 60 + (int)(Math.Sin(t*Math.PI*40) * 50); 
     var ypos = 60 + (t>0.5 ? 20: -20); 
     graphDest.DrawImage(bmpSrc, new Rectangle(xpos, ypos, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel, im); 
    } 

    bmpDest.Save(@"test.png"); 
} 

GDI + 투명 이미지를 혼합하는 방식의 정밀도 문제로 인한 것 같습니다. 이견있는 사람?

- 편집

컬러 매트릭스없이

같은 문제를() (의 drawImage에서 마지막 인자를 제거) :

enter image description here

- 편집이

그것은 아무도처럼 보인다 이것에 대한 답이 있습니다 - 그 질문은 충분히 명확하지 않습니까?

+0

질문을 이해할 수 없다. 그러나 컬러 매트릭스가 문제의 일부가되어야합니다. 0.3 * 0.3 * 0.3 * ... = 0 –

+1

귀하의 의견을 이해한다고 말할 수는 없지만 ImageAttributes없이 DrawImage()를 호출하면 문제가 남아 있습니다. – trethaller

답변

1

예, 잘림 오류가 누적됩니다. 이미지에 대해 PixelFormat.Format32bppPArgb 모드를 사용해 볼 수도 있지만 도움이 될지 잘 모르겠습니다.

확실한 해결책은 브러시 스트로크를 단일 채널 이미지에 축적 한 다음 그 결과를 마스크로 사용하여 캔버스에 페인트하는 것입니다.

+0

PixelFormat.Format32bppPArgb를 사용하면 문제가 해결됩니다. "에어 브러시"기능을 계속해서 혼합해야하지만 단일 블렌드 스트로크를 구현하는 것도 좋은 방법입니다. 이제 부동 소수점 정밀도로 전환 할 수 있는지 여부를 결정할 것입니다. 감사 ! – trethaller

0

그래픽 객체의 SmoothingMode 조정을 시도해 보셨습니까? 브러쉬를 왼쪽에서 오른쪽으로 움직일 때 추가 보간이 발생하는 것처럼 보입니다.

+0

예, System.Drawing.Drawing2D.SmoothingMode의 가능한 모든 값을 시도했지만 문제가 해결되지 않습니다. – trethaller

관련 문제