我想您在这里使用的是 Windows 窗体和 GDI+?我已经为此做了很多工作,并且可以非常自信地告诉您您想要使用 24 位或 32 位图像(我不记得哪个对不起)。性能大大提高了大约 10 到 100 倍。在我的应用程序中,用户在文本框中指定旋转与能够用鼠标抓取图像并动态平滑旋转、动态缩放等有所不同。
假设您遵循该建议,只留下能够访问每个像素的问题。为什么您认为无法获得 24 或 32 位图像的每个像素?
编辑:在我的应用程序中,我只对所有内容使用了 32 位位图。如果我得到另一种格式的位图(例如从文件打开),我会立即转换它。实际上,即使我得到 32 位格式,我也会立即克隆它,然后处理原始位图,因为我发现它在文件上保留了一些锁。内置克隆产生了奇怪的结果,所以我最终在下面编写了这段代码。请注意,这是我大概 8 年前写的东西,所以没有使用任何最新功能:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace ImageCloneTest
{
static class Program
{
[DllImport("kernel32", EntryPoint = "RtlMoveMemory")]
public unsafe static extern void CopyMemory(byte* Destination, byte* Source, int Length);
[DllImport("kernel32", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
public static Bitmap Clone(Bitmap SourceBitmap, PixelFormat Format)
{
// copy image if pixel format is the same
if (SourceBitmap.PixelFormat == Format) return Clone(SourceBitmap);
int width = SourceBitmap.Width;
int height = SourceBitmap.Height;
// create new image with desired pixel format
Bitmap bitmap = new Bitmap(width, height, Format);
// draw source image on the new one using Graphics
Graphics g = Graphics.FromImage(bitmap);
//fill background in case orig bitmap contains transparent regions.
g.FillRectangle(Brushes.White, 0, 0, bitmap.Width, bitmap.Height);
g.DrawImage(SourceBitmap, 0, 0, width, height);
g.Dispose();
return bitmap;
}
// and with unspecified PixelFormat it works strange too
public static Bitmap Clone(Bitmap SourceBitmap)
{
// get source image size
int width = SourceBitmap.Width;
int height = SourceBitmap.Height;
Rectangle rect = new Rectangle(0, 0, width, height);
// lock source bitmap data
BitmapData srcData = SourceBitmap.LockBits(rect, ImageLockMode.ReadOnly, SourceBitmap.PixelFormat);
// create new image
Bitmap dstBitmap = new Bitmap(width, height, SourceBitmap.PixelFormat);
// lock destination bitmap data
BitmapData dstData = dstBitmap.LockBits(rect, ImageLockMode.WriteOnly, dstBitmap.PixelFormat);
CopyMemory(dstData.Scan0, srcData.Scan0, height * srcData.Stride);
// unlock both images
dstBitmap.UnlockBits(dstData);
SourceBitmap.UnlockBits(srcData);
// copy pallete
if (BitmapHasPalette(SourceBitmap) && BitmapHasPalette(dstBitmap))
{
ColorPalette srcPalette = SourceBitmap.Palette;
ColorPalette dstPalette = dstBitmap.Palette;
int n = srcPalette.Entries.Length;
for (int i = 0; i < n; i++)
{
dstPalette.Entries[i] = srcPalette.Entries[i];
}
dstBitmap.Palette = dstPalette;
}
return dstBitmap;
}
public static bool BitmapHasPalette(Bitmap SourceBitmap)
{
if (SourceBitmap == null) return false;
switch (SourceBitmap.PixelFormat)
{
case PixelFormat.Format1bppIndexed:
case PixelFormat.Format4bppIndexed:
case PixelFormat.Format8bppIndexed:
case PixelFormat.Indexed:
return true;
}
return false;
}
}
}