【发布时间】:2014-02-14 16:56:19
【问题描述】:
我正在尝试使用 memcpy 裁剪 24bpp 图像,就像我在这里读到的那样:cropping an area from BitmapData with C#。我遇到的问题是它仅在我的 sourceImage 为 32bpp 时才有效。当我的 sourceImage 为 24bpp 时,它给了我一个损坏的图像。
class Program
{
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static unsafe extern int memcpy(byte* dest, byte* src, long count);
static void Main(string[] args)
{
var image = new Bitmap(@"C:\Users\Vincent\Desktop\CroppedScaledBitmaps\adsadas.png");
//Creates a 32bpp image - Will work eventhough I treat it as a 24bpp image in the CropBitmap method...
//Bitmap newBitmap = new Bitmap(image);
//Creates a 24bpp image - Will produce a corrupt cropped bitmap
Bitmap newBitmap = (Bitmap)image.Clone();
var croppedBitmap = CropBitmap(newBitmap, new Rectangle(0, 0, 150, 150));
croppedBitmap.Save(@"C:\Users\Vincent\Desktop\CroppedScaledBitmaps\PieceOfShit.png", ImageFormat.Png);
Console.ReadLine();
}
static public Bitmap CropBitmap(Bitmap sourceImage, Rectangle rectangle)
{
Console.WriteLine("Bits per pixel of sourceImage: {0}", Image.GetPixelFormatSize(sourceImage.PixelFormat));
var sourceBitmapdata = sourceImage.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
var croppedImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format24bppRgb);
var croppedBitmapData = croppedImage.LockBits(new Rectangle(0, 0, rectangle.Width, rectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* sourceImagePointer = (byte*)sourceBitmapdata.Scan0.ToPointer();
byte* croppedImagePointer = (byte*)croppedBitmapData.Scan0.ToPointer();
memcpy(croppedImagePointer, sourceImagePointer, croppedBitmapData.Stride * rectangle.Height);
}
sourceImage.UnlockBits(sourceBitmapdata);
croppedImage.UnlockBits(croppedBitmapData);
return croppedImage;
}
}
我很困惑,因为我唯一要更改的是 sourceImage PixelFormat,而不是 CropBitmap 方法中的任何代码。所以我总是使用 24bpp Pixelformat 调用 LockBits,即使 sourceImage 是 32bpp。
我尝试了不同的方法来计算我正在复制的字节数,但一切都或多或少地导致了相同的损坏图像。
感谢任何帮助!
【问题讨论】:
-
你调试过代码并检查过值吗?注意
Stride的值可以是负数,它的位图倒置存储在内存中。 -
如果我使用 32bpp sourceImage 或 24bpp sourceImage,步幅是相同的。 (这可能是因为我在锁定位时将 32bpp sourceImage 视为 24bpp 图像?)
-
您不需要使用
memcpy,而是使用Marshal类。更安全。
标签: c# .net image-processing memcpy