cropping an area from BitmapData with C#

后端 未结 5 1378
囚心锁ツ
囚心锁ツ 2020-12-17 23:28

I have a bitmap sourceImage.bmp

locking it\'s bits:

BitmapData dataOriginal = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.W         


        
5条回答
  •  情书的邮戳
    2020-12-18 00:09

    Fopedush's answer benefits greatly when we subsitute Marshal.copy with memcpy, because that way we don't have to copy it through a byte[] array. That way the memory gets copied only once, instead of three times!

    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static unsafe extern int memcpy(byte* dest, byte* src, long count);
    
    static public Bitmap cropBitmap(Bitmap sourceImage, Rectangle rectangle)
    {
        const int BPP = 4; //4 Bpp = 32 bits; argb
        var sourceBitmapdata = sourceImage.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        var croppedImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
        var croppedBitmapData = croppedImage.LockBits(new Rectangle(0, 0, rectangle.Width, rectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
        unsafe
        {
            croppedBitmapData.Stride = sourceBitmapdata.Stride;
            byte* sourceImagePointer = (byte*)sourceBitmapdata.Scan0.ToPointer();
            byte* croppedImagePointer = (byte*)croppedBitmapData.Scan0.ToPointer();
            memcpy(croppedImagePointer, sourceImagePointer,
                   Math.Abs(croppedBitmapData.Stride) * rectangle.Height);
        }
        sourceImage.UnlockBits(sourceBitmapdata);
        croppedImage.UnlockBits(croppedBitmapData);
        return croppedImage;
    }
    

    My results are:

    BitmapClone: 1823 ms
    LockBits: 4857 ms
    Rectangle: 1479 ms
    My method: 559 ms
    My method with LockBits on source image done only once (before loop): 160 ms
    

    I don't have AForge so I haven't included that, but by looking on op's results it would be slower than this. I was testing cropping the image in half.

    Please note, that if we would exchange memcpy with:

    for (int k = 0; k < Math.Abs(croppedBitmapData.Stride) * rectangle.Height; k++)
         *(croppedImagePointer++) = *(sourceImagePointer++);
    

    it gets 10x slower!

提交回复
热议问题