Означает ли это, что 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);
Я создаю альтернативный код, он использует unsafe
и работает с использованием PixelFormat.Format32bppArgb
или PixelFormat.Format24bppRgb
", вы можете расширить его функциональностьесли вам нужно ":
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;
}