C# Working With Device & Surface to screenshot games - c#

I recently found out about the surface & device class which may solve my problems with screenshoting a fullscreen direct3d game.
I've tried following this article : fastest method to capture game screen shots in c#?(more than20 images per second)
First method i've tried is :
Device device = new Device(0, DeviceType.Default, GetForegroundWindow(), CreateFlags.None, new PresentParameters());
Surface s2 = device.CreateImageSurface(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, Format.A8R8G8B8);
device.GetFrontBuffer(s2);
SurfaceLoader.Save("c:\\Screenshot.bmp", ImageFileFormat.Bmp, s2);
second method i've tried is :
Device device = new Device(0, DeviceType.Default, GetForegroundWindow(), CreateFlags.None, new PresentParameters());
Surface s1 = device.GetBackBuffer(0, BackBufferType.Mono);
device.GetFrontBuffer(s1);
On both methods the device would report a dll it can't find (Unable to load DLL 'netcfd3dm2_0.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E))
I got confused from that other article. Anyone with experience in this area can sort things out?

Seems you missing file that comes with Compact Framework. Try install/reinstall compact framework

Related

Capture still images with UWP MediaCapture (PIN_CATEGORY_STILL)

An alternative title could be: What happened to PIN_CATEGORY_STILL?
I am currently comparing images that were captured using DirectShow and PIN_CATEGORY_STILL with images that were captured using UWP MediaCapture.
On the device I am testing/playing around with DirectShow and MediaCapture, DirectShow detects a PIN_CATEGORY_STILL but I am not able to initialize an instance of MediaCapture with anything other than PhotoCaptureSource.VideoPreview.
MediaCaptureInitializationSettings settings = new()
{
VideoDeviceId = someDeviceId,
PhotoCaptureSource = PhotoCaptureSource.Photo
};
MediaCapture capture = new();
// this throws an exception
// "The capture source does not have an independent photo stream."
await capture.InitializeAsync(settings);
At this point I'm not even sure if PhotoCaptureSource.Photo is meant to be used as an equivalent to PIN_CATEGORY_STILL.
Images captured with PIN_CATEGORY_STILL are way brighter in a dark environment and have a much better quality (in file size and resolution) (which is clear to me, since I am using PhotoCaptureSource.VideoPreview for MediaCapture).
Considering this resource Win32 and COM for UWP apps, it seems like UWP MediaCapture does not use DirectShow underneath but MediaFoundation (which is meant to be a successor for DirectShow).
This article led me to this StackOverflow question Media Foundation is incorrectly marking still image capture stream descriptors as video capture, which basically states that MediaFoundation has no PIN_CATEGORY_STILL but returns 1 FPS as video capability for such devices (or profiles).
Since I am not directly using MediaFoundation nor C++, I tried testing this by querying GetAvailableMediaStreamProperties:
private void Foo()
{
var videoPreviewProperties = GetEncodingProperties(MediaStreamType.VideoRecord);
var photoProperties = GetEncodingProperties(MediaStreamType.Photo);
var videoRecordProperties = GetEncodingProperties(MediaStreamType.VideoPreview);
}
private List<VideoEncodingProperties> GetEncodingProperties(MediaStreamType streamType)
{
// MediaCapture was previously initialized with PhotoCaptureSource.VideoPreview
return MediaCapture.VideoDeviceController
.GetAvailableMediaStreamProperties(streamType)
.OfType<VideoEncodingProperties>()
.ToList();
}
None of these returns a VideoEncodingProperties with only 1 FPS.
To test MediaCapture any further I tried some of the sample applications from here UWP sample. I tried CameraAdvancedCapture, CameraOpenCV and CameraManualControls, but the results were not nearly as good as good old PIN_CATEGORY_STILL.
What happened to PIN_CATEGORY_STILL?
Is there any way to capture images without DirectShow/PIN_CATEGORY_STILL and still keeping this level of quality?
Any enlightenment is much appricated.

Playing an HDHomeRun stream on a Tizen.NET Xamarin App

I'm trying to play a HDHomeRun Connect Video source from a url in the following format: http://x.x.x.x:xxxx/auto/v4.1. This video source is an MPEG2 video encoding and AC3 audio encoding.
I've tried using the Samsung Tizen.TV .NET sample with the following source but the video never plays.
_player = new Tizen.Multimedia.Player();
var mediaSource = new Multimedia.MediaUriSource(uri);
_player.SetSource(mediaSource);
var display = new Multimedia.Display(Window.Instance);
_player.Display = display;
await _player.PrepareAsync();
The player state gets stuck in preparing, and the await _player.PrepareAsync() call never finishes. It is worth noting that I'm using the Tizen Samsung TV Emulator. Do I need to transcode the stream from the HDHomeRun to be playable? Are there any other measures I might be missing for the Video to play?
Ultimately, the Display property of the player wasn't being set correctly. The property that worked for me (found from investigating the JuvoPlayer code was this:
var display = new Multimedia.Display(((FormsApplication)Forms.Context).MainWindow);
_player.Display = display;
When you are to develop a Tizen .NET application, please be aware of which UI framework your project is targetted for among 3 different types: Xamarin.Forms, (pure) ElmSharp, and Tizen.NUI.
Unless your project is based on the Tizen.NUI framework, you shouldn't use Tizen.NUI.Window.Instance and types in Tizen.NUI namespace in any case. Instead, you will have to use types of ElmSharp or Xamarin.Forms.Platform.Tizen namespace for platform-specific code in your application.
Since the internal implementation of Xamarin.Forms for Tizen is based on ElmSharp, FormsApplication.MainWindow will return a ElmSharp.Window instance which can be used to instantiate a Tizen.Multimedia.Display object. That's why the code in your answer worked.

DirectX - Access denied when creating swap chain for CoreWindow

I'm currently trying to create a swapchain for a CoreWindow using the latest SharpDX as DirectX wrapper and UWP as project base framework.
The documentation on that is so sparse it's unbelievable. Nonetheless I could find a snippet which looked promising. Inititally I always got an E_INVALIDCALL error message. Now it's "only" E_ACCESSDENIED.
So far I've done this to set up the chain:
var description = new SwapChainDescription1
{
BufferCount = 2,
Flags = SwapChainFlags.None,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.FlipSequential,
Usage = Usage.RenderTargetOutput,
Width = 0,
Height = 0,
Scaling = Scaling.None,
Format = Format.B8G8R8A8_UNorm,
Stereo = false
};
CoreWindow window = CoreWindow.GetForCurrentThread();
if (window == null)
{
Logging.Error("Could not retrieve core window for swap chain.");
throw new Exception("Invalid core window.");
}
using (var device = _device.QueryInterface<SharpDX.DXGI.Device2>())
{
device.MaximumFrameLatency = 1;
using (Adapter adapter = device.Adapter)
{
using (ComObject coreWindow = new ComObject(window))
{
using (Factory2 factory = adapter.GetParent<Factory2>())
_swapChain = new SwapChain1(factory, _device, coreWindow, ref description);
}
}
}
The constructor of SwapChain1 throws the SharpDX exception:
SharpDX.Result.CheckError()
SharpDX.DXGI.Factory2.CreateSwapChainForCoreWindow(ComObject deviceRef, ComObject windowRef, SwapChainDescription1& descRef, Output restrictToOutputRef, SwapChain1 swapChainOut)
SharpDX.DXGI.SwapChain1..ctor(Factory2 factory, ComObject device, ComObject coreWindow, SwapChainDescription1& description, Output restrictToOutput)
RobInspect.Visualizer.Rendering.RenderingPanel.InitializeSizeDependentResources()
RobInspect.Visualizer.Rendering.RenderingPanel.InitializeDevice()
"HRESULT: [0x80070005], Module: [General], ApiCode: [E_ACCESSDENIED/General access denied error], Message: Access is denied.
"
Can anyone explain me why? "Access denied" is quite a broad statement and I'm not that experienced with DirectX's internals.
Further information: The code is executing on the main (UI) thread. So I guess I can exclude that the CoreWindow reference is inaccessible. Since this is first-time initialisation I also exclude the possibility of DirectX objects not being freed properly before creating the swap chain.
EDIT:
That's the code for creating the device. Whereas the flags are set to DeviceCreationFlags.BgraSuuport and DeviceCreationFlags.Debug. The levels are set to FeatureLevel.Level_11_1 down to FeatureLevel.Level_9_1.
using (var device = new Device(DriverType.Hardware, flags, levels))
{
_device = device.QueryInterface<Device1>();
_context = _device.ImmediateContext1;
}
The solution to this problem is that the terms WinRT Core and WinRT XAML are rather misleading. Since UWP is based on CoreWindow and both support and use them it's not clear where to use what.
DirectX exposes two methods for WinRT and one for Desktop. One being Factory2.CreateSwapChainForCoreWindow(...) and one Factory2.CreateSwapChainForComposition(...). The difference is that one takes the CoreWindow as parameter and one does not. And here's the trap I fell into.
Core stands for the design-scheme with which one only uses IFrameworkView and IFrameworkViewSource (see here for an example with SharpDX) whereas XAML stands for the traditional scheme where you have the Windows.UI.Xaml.Application class.
When using the Core-model you have to call the ...ForCoreWindow(...) method in order to create a swap chain. While using the XAML based approach you need a composition swap chain. I for myself already tried that, but failed because I forgot to enable (tip: do this if not already done) native debugging so the DirectX Debug Layer actually showed me essential information which could have saved me hours if not days of trial and error.
The issue here is that both composition and CoreWindow swap chains require special settings in the SwapChainDescription1. I'll leave you with the MSDN documentation. Moreover if native debugging and the debug layer is enabled, DirectX will tell you exactly what setting is invalid.

Screen capture program on Mac OS X Lion, preferable portable on other OS

I need to develop a screen capture program that runs on Mac OS X Lion. I tried to make a screenshot using mono and GTK#, but the screenshot is black
Gdk.Window window = Gdk.Global.DefaultRootWindow;
if (window!=null)
{
Gdk.Pixbuf pixBuf = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8,
window.Screen.Width, window.Screen.Height);
pixBuf.GetFromDrawable(window, Gdk.Colormap.System, 0, 0, 0, 0,
window.Screen.Width, window.Screen.Height);
pixBuf.ScaleSimple(400, 300, Gdk.InterpType.Bilinear);
pixBuf.Save("screenshot0.jpeg", "jpeg");
}
Can you point me in right direction. Preferably using mono, but if will be java, c++ or objective c is also good.
Thank in advance.
For Java, see Robot.createScreenCapture(Rectangle). Note though, that Robot commonly also produces a black screen image for apps. that take direct control of the screen area (e.g. many games).
Your best bet would probably be using a platform-specific API to do the actual image capture, while the rest of your app remains portable. For OS X, Apple actually provides sample code on how to do this, and your code will probably work under X11.

Is there a way to take a screenshot of the user's Windows desktop?

I want to provide the user with a scaled-down screenshot of their desktop in my application.
Is there a way to take a screenshot of the current user's Windows desktop?
I'm writing in C#, but if there's a better solution in another language, I'm open to it.
To clarify, I need a screenshot of the Windows Desktop - that's the wallpaper and icons only; no applications or anything that's got focus.
You're looking for Graphics.CopyFromScreen. Create a new Bitmap of the right size and pass the Bitmap's Graphics object screen coordinates of the region to copy.
There's also an article describing how to programmatically take snapshots.
Response to edit: I misunderstood what you meant by "desktop". If you want to take a picture of the desktop, you'll have to:
Minimize all windows using the Win32API (send a MIN_ALL message) first
Take the snapshot
Then undo the minimize all (send a MIN_ALL_UNDO message).
A better way to do this would be not to disturb the other windows, but to copy the image directly from the desktop window. GetDesktopWindow in User32 will return a handle to the desktop. Once you have the window handle, get it's device context and copy the image to a new Bitmap.
There's an excellent example on CodeProject of how to copy the image from it. Look for the sample code about getting and creating the device context in the "Capturing the window content" section.
I get the impression that you are shooting for taking a picture of the actual desktop (with wallpaper and icons), and nothing else.
1) Call ToggleDesktop() in Shell32 using COM
2) Use Graphics.CopyFromScreen to copy the current desktop area
3) Call ToggleDesktop() to restore previous desktop state
Edit: Yes, calling MinimizeAll() is belligerent.
Here's an updated version that I whipped together:
/// <summary>
/// Minimizes all running applications and captures desktop as image
/// Note: Requires reference to "Microsoft Shell Controls and Automation"
/// </summary>
/// <returns>Image of desktop</returns>
private Image CaptureDesktopImage() {
//May want to play around with the delay.
TimeSpan ToggleDesktopDelay = new TimeSpan(0, 0, 0, 0, 150);
Shell32.ShellClass ShellReference = null;
Bitmap WorkingImage = null;
Graphics WorkingGraphics = null;
Rectangle TargetArea = Screen.PrimaryScreen.WorkingArea;
Image ReturnImage = null;
try
{
ShellReference = new Shell32.ShellClass();
ShellReference.ToggleDesktop();
System.Threading.Thread.Sleep(ToggleDesktopDelay);
WorkingImage = new Bitmap(TargetArea.Width,
TargetArea.Height);
WorkingGraphics = Graphics.FromImage(WorkingImage);
WorkingGraphics.CopyFromScreen(TargetArea.X, TargetArea.X, 0, 0, TargetArea.Size);
System.Threading.Thread.Sleep(ToggleDesktopDelay);
ShellReference.ToggleDesktop();
ReturnImage = (Image)WorkingImage.Clone();
}
catch
{
System.Diagnostics.Debugger.Break();
//...
}
finally
{
WorkingGraphics.Dispose();
WorkingImage.Dispose();
}
return ReturnImage;
}
Adjust to taste for multiple monitor scenarios (although it sounds like this should work just fine for your application).
You might look at using GetDesktopWindow through p/invoke, then get the device context and take your snapshot. There is a very detailed tutorial here. It might be better than perturbing the existing windows.
You can always catch screenshot on windows startup before applications run
or use other desktop by using desktop switching. Take a look here:
http://www.codeproject.com/Articles/7666/Desktop-Switching
Switch to other desktop, take picture and remember you dont need to show it just create it "DESKTOP"
All former answers are completely wrong (minimizing apps is absurd)
Simply use SHW api : one line of code (the desktop bitmap being cached, the api simply blits it to your HDC...)

Categories