2

I'm currently having some problems in integrating a System.Drawing.Bitmap into a WPF WriteableBitmap.

I want to copy from the Bitmap to position (X,Y) of the WriteableBitmap.

The following code shows how I've tried to do this.

BitmapData Data = Bitmap.LockBits(new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
WriteableBitmap.Lock();

//CopyMemory(WriteableBitmap.BackBuffer, Data.Scan0,  ImageBufferSize);

Int32Rect Rect = new Int32Rect(X, Y, Bitmap.Width, Bitmap.Height);
WriteableBitmap.AddDirtyRect(Rect);
Bitmap.UnlockBits(Data);
Bitmap.Dispose();`

Thanks a lot,

Neokript

meklarian
  • 6,595
  • 1
  • 23
  • 49
Geotinc
  • 289
  • 1
  • 4
  • 21

2 Answers2

2

Use WritableBitmap.WritePixels. This will prevent using unmanaged code.

BitmapData Data = Bitmap.LockBits(new Rectangle(0, 0, Bitmap.Width, Bitmap.Height),
    ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

try
{    
    WritableBitmap.WritePixels(
        new Int32Rect(0,0,Bitmap.Width, Bitmap.Height),
        Data.Scan0,
        Data.Stride,
        X, Y);
}
finally
{
    Bitmap.UnlockBits(Data);
}

Bitmap.Dispose();
Dmitry Polomoshnov
  • 5,106
  • 2
  • 24
  • 25
  • that seems like it should work but I don't see a signature for WritePixels that takes (rect, ptr, int, int, int). Maybe something has changed since this was posted 10 years ago...https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.imaging.writeablebitmap.writepixels?view=windowsdesktop-7.0#system-windows-media-imaging-writeablebitmap-writepixels(system-windows-int32rect-system-intptr-system-int32-system-int32) – gghuffer Oct 14 '22 at 13:00
1

You should lock both BitmapData and WriteableBitmap. If you want to draw the image to a specific (x,y) location, then you should also manage the remaining width and height of image for drawing.

[DllImport("kernel32.dll",EntryPoint ="RtlMoveMemory")]
public static extern void CopyMemory(IntPtr dest, IntPtr source,int Length);

public void DrawImage(Bitmap bitmap)
{
    BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    try
    {
        writeableBitmap.Lock();
        CopyMemory(writeableBitmap.BackBuffer, data.Scan0,
            (writeableBitmap.BackBufferStride * bitmap.Height));
        writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.Width, bitmap.Height));
        writeableBitmap.Unlock();
    }
    finally
    {
        bitmap.UnlockBits(data);
        bitmap.Dispose();
    }
}

And in your code:

Bitmap bitmap = new Bitmap("pic.jpg"); // obtain it from anywhere, memory, file, stream ,...

writeableBitmap = new WriteableBitmap(
                        bitmap.Width,
                        bitmap.Height,
                        96,
                        96,
                        PixelFormats.Pbgra32,
                        null);

imageBox.Source = writeableBitmap;

DrawImage(bitmap);

I have managed to render a 1080P clip with 29 fps using this method.

Mohsen Afshin
  • 13,273
  • 10
  • 65
  • 90