这是在没有任何 dll 的情况下以有效、快速的方式从 C# Windows 窗体中的图像制作底片的解决方案吗?
tomaszs
问问题
6298 次
2 回答
14
最好的方法是使用位图数据直接访问像素。
只是添加一些时间细节:
对 8 兆像素图像执行取反(在 2.4 Ghz Core 2 Duo 上):
- SetPixel (~22 秒) - 慢 220 倍
- 颜色矩阵,下面的 Matajon 方法(~750 毫秒) - 慢 7 倍
- 直接访问位图数据(~100 毫秒) - 最快
所以,如果你不能有不安全的代码,那么 Color Matrix 比 SetPixel 要好得多。
public static void Negate(Bitmap image)
{
const int RED_PIXEL = 2;
const int GREEN_PIXEL = 1;
const int BLUE_PIXEL = 0;
BitmapData bmData = currentImage.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
try
{
int stride = bmData.Stride;
int bytesPerPixel = (currentImage.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4);
unsafe
{
byte* pixel = (byte*)(void*)bmData.Scan0;
int yMax = image.Height;
int xMax = image.Width;
for (int y = 0; y < yMax; y++)
{
int yPos = y * stride;
for (int x = areaSize.X; x < xMax; x++)
{
int pos = yPos + (x * bytesPerPixel);
pixel[pos + RED_PIXEL] = (byte)(255 - pixel[pos + RED_PIXEL]);
pixel[pos + GREEN_PIXEL] = (byte)(255 - pixel[pos + GREEN_PIXEL]);
pixel[pos + BLUE_PIXEL] = (byte)(255 - pixel[pos + BLUE_PIXEL]);
}
}
}
}
finally
{
image.UnlockBits(bmData);
}
}
如果您有兴趣,这里是颜色矩阵的代码:
public static void Negate(Bitmap image)
{
Bitmap clone = (Bitmap) image.Clone();
using (Graphics g = Graphics.FromImage(image))
{
// negation ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {-1, 0, 0, 0, 0},
new float[] {0, -1, 0, 0, 0},
new float[] {0, 0, -1, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(colorMatrix);
g.DrawImage(clone, new Rectangle(0, 0, clone.Width, clone.Height),
0, 0, clone.Width, clone.Height, GraphicsUnit.Pixel, attributes);
}
}
于 2009-02-16T01:38:31.117 回答
0
逐个遍历所有像素(Bitmap.GetPixel() 或其他内容)并从 0xff 中减去 RGB 值以创建负色像素。将此像素保存到新图像或使用 (Bitmap.SetPixel()) 在同一位置的同一图像上。
// Retrieve the image.
var image1 = new Bitmap(@"C:\Documents and Settings\All Users\"
+ @"Documents\My Music\music.bmp", true);
int x, y;
// Loop through the images pixels to reset color.
for(x=0; x<image1.Width; x++)
{
for(y=0; y<image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
Color newColor = Color.FromArgb(0xff - pixelColor.R
, 0xff - pixelColor.G, 0xff - pixelColor.B);
image1.SetPixel(x, y, newColor);
}
}
于 2009-02-12T13:57:56.017 回答