2011-07-17 1 views
3
 Bitmap x = new Bitmap(s.Width, s.Height); 
     Graphics g = Graphics.FromImage(x); 
     g.CopyFromScreen(0, 0, 0, 0, new Size(s.Width, s.Height), CopyPixelOperation.SourceCopy); 
     g.Dispose(); 
     x.Save("x_before.png", ImageFormat.Png); 

     Graphics g1 = Graphics.FromImage(x); 
     g1.DrawImage(x); // to make sure the image is in g1 context 
     g1.CopyFromScreen(0, 0, 0, 0, new Size(s.Width, s.Height), CopyPixelOperation.SourceInvert); 
     g1.Dispose(); 
     x.Save("x_after.png", ImageFormat.Png); 

화면을 비트 맵으로 복사합니다. 그런 다음 동일한 비트 맵에 XOR 매개 변수 반전과 동일한 화면이 표시됩니다.CopyPixelOperation.SourceInvert가 작동하지 않습니다.

1 XOR 1 = 0

0 XOR 0 = 0

0 XOR 1 = 1

1 XOR 0 = 1

그 결과 검은 이미지이어야한다. 그러나 그렇지 않습니다.

CopyPixelOperation.SourceInvert가 작동하지 않는다는 의미입니까?

답변

2

CopyPixelOperation.SourceInvert가 작동하지 않는다는 의미입니까?

예; 내가 제공 한 코드를 실행하면 CopyPixelOperation.SourceInvert이 실제로 그렇게 작동하지 않는다는 것을 알았습니다. Reflector를 사용한 추가 조사에서 CopyFromScreen 메서드가 gdi32.dll 메서드 BitBlt을 내부적으로 호출하는 것으로 나타났습니다.이 메서드는 버그 일 수 있습니다.

업데이트 : 코드 결과가 검은 이미지가 아닌 알파 이미지 여야합니다. new Bitmap(s.Width, s.Height);new Bitmap(s.Width, s.Height, PixelFormat.Format32bppArgb);과 같으므로 결과는 알파가 0으로 설정된 검은 이미지이므로 투명 이미지입니다. 같이 사용하는 24 비트하지만 만약이 검은 색 이미지되어야한다 : 나는 대체 코드를 만들 new Bitmap(s.Width, s.Height, PixelFormat.Format24bppRgb);

, 그것은 PixelFormat.Format32bppArgb 또는 PixelFormat.Format24bppRgb를 사용 unsafe 작업을 사용하고 "당신은 당신이있는 경우에이 기능의 확장 할 수있다"

public unsafe static Bitmap ImageXOR(this Bitmap source, Bitmap destination) 
{ 


    #region Verification 

    if (destination == null) 
    { 
     throw new ArgumentNullException("newBitmap"); 
    } 
    if (source.PixelFormat != destination.PixelFormat) 
    { 
     throw new ArgumentException("PixelFormat does not match"); 
    } 
    if (source.Size != destination.Size) 
    { 
     throw new ArgumentException("Size does not match"); 
    } 
    if (source.PixelFormat != PixelFormat.Format24bppRgb && source.PixelFormat != PixelFormat.Format32bppArgb) 
    { 
     throw new NotSupportedException(string.Format("Pixel format \"{0}\" not supported", source.PixelFormat)); 
    } 

    #endregion//Verification 


    BitmapData sourceBitmapData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), 
     ImageLockMode.ReadOnly, source.PixelFormat); 

    try 
    { 
     BitmapData destinationBitmapData = destination.LockBits(
      new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.ReadWrite, destination.PixelFormat); 

     try 
     { 
      int colorDepth = source.PixelFormat == PixelFormat.Format32bppArgb ? 4 : 3; 

      byte* sourceFirstPixelPhysicalAddress = (byte*)sourceBitmapData.Scan0.ToPointer(); 
      byte* destinationFirstPixelPhysicalAddres = (byte*)destinationBitmapData.Scan0.ToPointer(); 
      for (int heightIndex = 0; heightIndex < source.Height; heightIndex++) 
      { 
       for (int widthIndex = 0; widthIndex < sourceBitmapData.Width; widthIndex++) 
       { 
        byte* sourceRowPhysicalAddress = (byte*)sourceFirstPixelPhysicalAddress + 
         (heightIndex * sourceBitmapData.Stride); 
        byte* destinationRowPhysicalAddress = (byte*)destinationFirstPixelPhysicalAddres + 
         (heightIndex * destinationBitmapData.Stride); 

        int pixelPosition = widthIndex * colorDepth; 

        int indexOfBlue = 0 + pixelPosition; 
        int indexOfGreen = 1 + pixelPosition; 
        int indexOfRed = 2 + pixelPosition; 
        int indexOfAlpha = 3 + pixelPosition; 

        //get color values 
        //get blue 
        byte blue = (byte)((byte)sourceRowPhysicalAddress[indexOfBlue]^(byte)destinationRowPhysicalAddress[indexOfBlue]); 
        //get green 
        byte green = (byte)((byte)sourceRowPhysicalAddress[indexOfGreen]^(byte)destinationRowPhysicalAddress[indexOfGreen]); 
        //get red 
        byte red = (byte)((byte)sourceRowPhysicalAddress[indexOfRed]^(byte)destinationRowPhysicalAddress[indexOfRed]); 
        byte alpha = 0; 
        if (colorDepth > 3) 
        { 
         //get alpha 
         alpha = (byte)((byte)sourceRowPhysicalAddress[indexOfAlpha]^(byte)destinationRowPhysicalAddress[indexOfAlpha]); 
        } 
        //set blue 
        destinationRowPhysicalAddress[indexOfBlue] = blue; 
        //set green 
        destinationRowPhysicalAddress[indexOfGreen] = green; 
        //set red 
        destinationRowPhysicalAddress[indexOfRed] = red; 
        if (colorDepth > 3) 
        { 
         //set alpha 
         destinationRowPhysicalAddress[indexOfAlpha] = alpha; 
        } 
       } 
      } 
     } 
     finally 
     { 
      destination.UnlockBits(destinationBitmapData); 
     } 
    } 
    finally 
    { 
     source.UnlockBits(sourceBitmapData); 
    } 

    return destination; 
} 
+0

@Kirk : 대체 코드를 추가했습니다. 확인해 봐. –

+0

@Kirk Robb : 이것을 시험해 보셨습니까? 이 대답이 질문에 대한 대답입니까? –

+1

방금이 도구를 사용했는데 멋졌습니다. (위로 표시된 답변) 여전히 XOR 이미지에 대한 최상의 솔루션입니까? 또한 원본 이미지와이 XOR 이미지를 저장하면 XOR을 사용하여 새 이미지를 다시 얻을 수 있습니까? 감사! – Don

관련 문제