Quantcast
Viewing all articles
Browse latest Browse all 2341

Commented Unassigned: Begin/AfterDrawing and OnDrawBackBuffer provide write only context [25998]

First, thank you to all developers who have produced this package, it is very useful. My issue is the way the AfterDrawing and OnDrawBackBuffer are implemented. I was attempting to draw anti-aliased and per-pixel alpha images over the map, but could not get the transparency to work. Inspecting the source, I found that the back buffer is implemented with a gdi+ bitmap, and the hdc from the gdi+ graphics object is what gets passed to the Fire*() callbacks. This is fine for drawing any purely source pixel objects, but makes any raster operation which needs to combine the source with the destination pixels impossible because gdi+ only tracks changes to the bitmap, and then copies the net results to the actual bitmap only after ReleaseDC is called. See: [this article](https://support.microsoft.com/en-us/kb/311221) for a better explanation.
Perhaps there might be a way to expose the buffer bitmap itself?
Comments: Hey Sergei, I did a quick test to find a feasible work around for this. I just pass a pointer to the back buffer bits instead of the HDC. See the comments in the following code. In CMapView::HandleNewDrawing: Original code ``` // Passes a DC obtained from a Gdiplus Graphics object, // which while being efficient, will be write-only, meaning no alpha-blending // in the OnDrawBackBuffer callback. //HDC hdc = gBuffer->GetHDC(); //this->FireOnDrawBackBuffer((long)hdc); //gBuffer->ReleaseHDC(hdc); ``` New code ``` // Here we pass the backbuffer's memory pointer. // Of course, the OnDrawBackBuffer callback won't know everything // it needs to (format, width, height, stride), but I tried this as // a quick sanity check. I am able to draw in my OnDrawBackBuffer managed callback // with proper alpha-blending, and there should be no performance // impact (no extra image copies). // To make this correct, we will really need to pass the BitmapData structure, but Gdiplus::Rect r (0, 0, _bufferBitmap->GetWidth(), _bufferBitmap->GetHeight()); Gdiplus::BitmapData bmd; _bufferBitmap->LockBits(&r, Gdiplus::ImageLockModeRead|Gdiplus::ImageLockModeWrite, _bufferBitmap->GetPixelFormat(), &bmd); this->FireOnDrawBackBuffer((long)bmd.Scan0); _bufferBitmap->UnlockBits(&bmd); ``` In the managed code OnDrawBackBuffer: ``` using (Bitmap mapBackBuffer = new Bitmap(axMap1.Width, axMap1.Height, 4 * axMap1.Width, System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(e.backBuffer))) // <- references the image memory; does not copy :) { using (Graphics g = Graphics.FromImage(mapBackBuffer)) { using (SolidBrush br = new SolidBrush(Color.FromArgb(128, 255, 0, 0))) { g.FillEllipse(br, 100, 100, 100, 100); // This will correctly render with alpha blending } } } ```

Viewing all articles
Browse latest Browse all 2341

Trending Articles