public void SaveScreenshot(string path) { var s = window.SurfaceSize; var raw = new byte[s.Width * s.Height * 4]; OpenGL.glPushClientAttrib(OpenGL.GL_CLIENT_PIXEL_STORE_BIT); OpenGL.glPixelStoref(OpenGL.GL_PACK_ROW_LENGTH, s.Width); OpenGL.glPixelStoref(OpenGL.GL_PACK_ALIGNMENT, 1); unsafe { fixed(byte *pRaw = raw) OpenGL.glReadPixels(0, 0, s.Width, s.Height, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE, (IntPtr)pRaw); } OpenGL.glFinish(); OpenGL.glPopClientAttrib(); ThreadPool.QueueUserWorkItem(_ => { // Convert GL pixel data into format expected by png // - Flip vertically // - BGRA to RGBA // - Force A to 255 (no transparent pixels!) var data = new byte[raw.Length]; for (var y = 0; y < s.Height; y++) { for (var x = 0; x < s.Width; x++) { var iData = 4 * (y * s.Width + x); var iRaw = 4 * ((s.Height - y - 1) * s.Width + x); data[iData] = raw[iRaw + 2]; data[iData + 1] = raw[iRaw + 1]; data[iData + 2] = raw[iRaw + 0]; data[iData + 3] = byte.MaxValue; } } var screenshot = new Png(data, window.SurfaceSize.Width, window.SurfaceSize.Height); screenshot.Save(path); }); }
public Bitmap TakeScreenshot() { var rect = new Rectangle(Point.Empty, WindowSize); var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); var data = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); OpenGL.glPushClientAttrib(OpenGL.GL_CLIENT_PIXEL_STORE_BIT); OpenGL.glPixelStoref(OpenGL.GL_PACK_ROW_LENGTH, data.Stride / 4f); OpenGL.glPixelStoref(OpenGL.GL_PACK_ALIGNMENT, 1); OpenGL.glReadPixels(rect.X, rect.Y, rect.Width, rect.Height, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE, data.Scan0); OpenGL.glFinish(); OpenGL.glPopClientAttrib(); bitmap.UnlockBits(data); // OpenGL standard defines the origin in the bottom left corner which is why this is upside-down by default. bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); return(bitmap); }