0

In the program, I need to quickly draw on the image. To do this, I chose WriteableBitmap, and I perform the necessary manipulations with BackBuffer. And everything is drawn safely, as long as the image size does not exceed a certain limit in the region of 1500 pixels. Above this size, instead of the desired shape, something else appears.

writeable.Lock();
IntPtr buff = writeable.BackBuffer;
unsafe
{
    byte* pbuff = (byte*)buff.ToPointer();
    ...
}
writeable.AddDirtyRect(new Int32Rect(0, 0, (int)writeable.Width, (int)writeable.Height));
writeable.Unlock();

At the top of an incorrect result of drawing down approximately as it should look (round brush).

If we do not update the entire image, but only the area you are changing, the result is identical to updating the entire image. What is the problem? Is this a feature of BackBuffer or some other restrictions on the size of WriteableBitmap? And what to do with it if we need very fast rendering on images of 15-30 megapixels? Please do not consider options with Direct2D.

Developer
  • 1
  • 3
  • I used WriteableBitmap for very large images 20 MP and bigger and had no problems. But maybe do not use (int)Width and (int)Height. WriteableBitmap has extra PixelWidth and PixelHeight Properties. – Quergo May 04 '20 at 18:39
  • Could you please provide a code snippet of how you actually write to the buffer? – Igor May 04 '20 at 18:50
  • This can be seen in my answer below. – Developer May 04 '20 at 19:37
  • @Quergo By the way, do you have any feedback here? https://stackoverflow.com/q/61416524/1136211 – Clemens May 04 '20 at 19:51

1 Answers1

0

Based on the post, I solved this problem by changing the way BackBuffer is accessed.

Code that doesn't work with big images:

writeable.Lock();
IntPtr buff = writeable.BackBuffer;
unsafe
{
    byte* pbuff = (byte*)buff.ToPointer();

    pbuff[Index * 3 + 0] = (byte)(B);
    pbuff[Index * 3 + 1] = (byte)(G);
    pbuff[Index * 3 + 2] = (byte)(R);
}
writeable.AddDirtyRect(new Int32Rect(0, 0, writeable.PixelWidth, writeable.PixelHeight));
writeable.Unlock();

Working code:

writeable.Lock();
unsafe
{
    long pBackBuffer = (long)writeable.BackBuffer;
    int stride = writeable.BackBufferStride;

    int offset = (int)(RelativeY * stride + RelativeX * 3);
    long pBackBufferWithOffset = pBackBuffer + offset;
    *((byte*)pBackBufferWithOffset + 0) = (byte)(B);
    *((byte*)pBackBufferWithOffset + 1) = (byte)(G);
    *((byte*)pBackBufferWithOffset + 2) = (byte)(R);
}
writeable.AddDirtyRect(new Int32Rect(0, 0, writeable.PixelWidth, writeable.PixelHeight));
writeable.Unlock();

writeable.PixelWidth OR (int)writeable.Width - doesn't matter.

It is important to use this - long, not this - int.

Developer
  • 1
  • 3
  • "*writeable.PixelWidth OR (int)writeable.Width - doesn't matter*" - only as long as it has exactly 96 DPI. If you deal with pixels, *always* use PixelWidth/-Height. – Clemens May 04 '20 at 20:25