Пример #1
0
        /// <summary>
        ///     Saves the window contents to a stream.
        /// </summary>
        /// <param name="stream">Stream to write the window contents to.</param>
        public override void Save(Stream stream, PixelFormat requestedFormat)
        {
            D3D.Device  device = driver.Device;
            DisplayMode mode   = device.DisplayMode;

            SurfaceDescription desc = new SurfaceDescription();

            desc.Width  = mode.Width;
            desc.Height = mode.Height;
            desc.Format = Format.A8R8G8B8;

            // create a temp surface which will hold the screen image
            Surface surface = device.CreateOffscreenPlainSurface(
                mode.Width, mode.Height, Format.A8R8G8B8, Pool.SystemMemory);

            // get the entire front buffer.  This is SLOW!!
            device.GetFrontBufferData(0, surface);

            // if not fullscreen, the front buffer contains the entire desktop image.  we need to grab only the portion
            // that contains our render window
            if (!IsFullScreen)
            {
                // whatever our target control is, we need to walk up the chain and find the parent form
                Form form = windowHandle.FindForm();

                // get the actual screen location of the form
                System.Drawing.Rectangle rect = form.RectangleToScreen(form.ClientRectangle);

                desc.Width  = width;
                desc.Height = height;
                desc.Format = Format.A8R8G8B8;

                // create a temp surface that is sized the same as our target control
                Surface tmpSurface = device.CreateOffscreenPlainSurface(rect.Width, rect.Height, Format.A8R8G8B8, Pool.Default);

                // copy the data from the front buffer to the window sized surface
                device.UpdateSurface(surface, rect, tmpSurface);

                // dispose of the prior surface
                surface.Dispose();

                surface = tmpSurface;
            }

            int pitch;

            // lock the surface to grab the data
            GraphicsStream graphStream = surface.LockRectangle(LockFlags.ReadOnly | LockFlags.NoSystemLock, out pitch);

            // create an RGB buffer
            byte[] buffer = new byte[width * height * 3];

            int offset = 0, line = 0, count = 0;

            // gotta copy that data manually since it is in another format (sheesh!)
            unsafe {
                byte *data = (byte *)graphStream.InternalData;

                for (int y = 0; y < desc.Height; y++)
                {
                    line = y * pitch;

                    for (int x = 0; x < desc.Width; x++)
                    {
                        offset = x * 4;

                        int pixel = line + offset;

                        // Actual format is BRGA for some reason
                        buffer[count++] = data[pixel + 2];
                        buffer[count++] = data[pixel + 1];
                        buffer[count++] = data[pixel + 0];
                    }
                }
            }

            surface.UnlockRectangle();

            // dispose of the surface
            surface.Dispose();

            // gotta flip the image real fast
            Image image = Image.FromDynamicImage(buffer, width, height, PixelFormat.R8G8B8);

            image.FlipAroundX();

            // write the data to the stream provided
            stream.Write(image.Data, 0, image.Data.Length);
        }