So I have some code that takes a photo in a UWP app (running on windows desktops and phones) using this code.
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
And it works great but it always takes the image at the full resolution of the device... (so 44 megapixels on a Lumia 1020) which is too big for me. I want to limit the resolution to a fixed size (say around 16 megapixel).
So is there a way of setting the camera capture resolution or will I have to capture it at full resolution and downscale it myself?
You should be able to change resolution of MediaCapture element by setting MediaStreamProperties just after initialization:
// initialization here
// get available resolutions
var resolutions = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).ToList();
// set used resolution
await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, resolutions[1]);
Related
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.
I'm using Media Foundation in my WPF application to implement functionality that is similar to the Windows Camera App: show a live webcam feed and take a high resolution image when pressing a button. While the Windows Camera App always takes a correctly exposed snapshot, the snapshot taken by Media Foundation is often overexposed.
The application is only used by devices that have built-in high resolutions for Photos (eg Surface Go 2, Surface 7 Pro, ...). A specific image stream is used to take the snapshot instead of reading one frame of the video stream.
I have already tried changing the IAMCameraControl and IAMVideoProcAmp properties like Exposure or Brightness before taking a snapshot but the photo was always overexposed.
Are there any additional settings or approaches for fixing overexposure when taking a high resolution snapshot (eg. the same way the Windows Camera App works)?
Overexposed snapshot
High resolutions for photos
Code to take the snapshot
IMFCaptureEngineClassFactory captureEngineClassFactory = null;
IMFCaptureEngine captureEngine = null;
IMFCapturePhotoSink capturePhotoSink = null;
IMFMediaType photoMediaType = null;
try
{
// Create a CaptureEngineClassFactory
captureEngineClassFactory = mff.GetCaptureEngineClassFactory();
// Create a CaptureEngine
captureEngine = mff.GetCaptureEngine(captureEngineClassFactory);
// Initialize the CaptureEngine
MFCaptureEngineOnEventCallback captureEngineOnEventCallback = MFCaptureEngineOnEventCallback.GetInstance();
mff.Initialize(captureEngine, captureEngineOnEventCallback, mediaSource);
captureEngineOnEventCallback.WaitUntilInitialized();
// Create a Photo Sink
capturePhotoSink = mff.CreateCapturePhotoSink(captureEngine);
// Create a Photo Media Type
photoMediaType = CreatePhotoMediaType(mediaType);
// Remove all streams
mff.RemoveAllStreams(capturePhotoSink);
// Add Stream
int sinkStreamIndex = mff.AddStream(capturePhotoSink, streamIndex, photoMediaType);
// Set output filename
mff.SetSampleCallback(capturePhotoSink, this);
// Take photo
mff.TakePhoto(captureEngine);
captureEngineOnEventCallback.WaitUntilDone();
// imageSource should be filled in after executing TakePhoto
return image;
}
finally
{
TryRelease(captureEngineClassFactory);
TryRelease(captureEngine);
TryRelease(capturePhotoSink);
TryRelease(photoMediaType);
}
The following code works well
AudioManager am = (AudioManager)this.GetSystemService(Context.AudioService);
am.RingerMode = RingerMode.Vibrate;
So after running it the ring volume gets to 0, but I would want to set it to a custom value like for instance "57".
To do this I used the following code:
AudioManager am = (AudioManager)this.GetSystemService(Context.AudioService);
am.SetStreamVolume(Stream.Ring, 57, 0);
After this code runs nothing changed to my ring volume, I expected that it will change to a "57" value.
I am using latest Xamarin libraries on a Android 7.0 version. I need to implement this only for Android.
Is this custom ring volume set a limitation ?
What should this am.SetStreamVolume(Stream.Ring, 57, 0); actually do (if it is not changing the ring volume of the phone).
You could use GetStreamMaxVolume firstly to get the maximum value for a particular stream, then set a proper number smaller than the maximum value.
Hello I displayed 1 webcam preview in UWP and that was a success.
But now I want to use 2 camera's preview on my program or be able to choose between the two cameras while connected 2 cameras on computer.
When I run 1 webcam preview, I referred to documentation on using MediaCapture and it was good.
But now I don't know how to display 2 camera previews or select a one between cameras.
Is it impossible?
Yes, it is possible :-) . The MediaCapture class takes the default camera when you call the InitializeAsync method without parameters, but there is another overload that allows you to specify the device ID.
The documentation shows how to discover video capture devices:
DeviceInformationCollection devices =
await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
Now you can initialize multiple MediaCapture instances like this:
foreach ( var device in devices )
{
var mediaInitSettings =
new MediaCaptureInitializationSettings { VideoDeviceId = device.Id };
MediaCapture mediaCapture = new MediaCapture();
mediaCapture.InitializeAsync(mediaInitSettings);
//do something with the media capture
}
Naturally, when you want to display multiple previews, you will need to have multiple CaptureElements, each set to the specific MediaCapture instance you want.
However this approach is quite simplified. To make sure the concurrent capture and preview is supported, you must first ensure to query only cameras that support device profile using MediaCapture.IsVideoProfileSupported method as shown in the documentation and then also check find a concurrency-enabled profile common for both cameras - MediaCapture.FindConcurrentProfiles, see docs. Only then you can safely create the two previews and know the app will not crash.
I'm trying to create a secondary tile for a windows 8.1 application, i need this tile to contain images for all sizes and all of them come from internet. this is my code :
string dynamicTileId = selectedItem.UniqueId;
string sLogo = selectedItem.logo;
string wLogo = selectedItem.widelogo;
string lLogo = selectedItem.imagen3;
Uri logo = new Uri(sLogo);//150x10 image
Uri wideLogo = new Uri(wLogo);//310x150 image
Uri largeLogo = new Uri(lLogo);//310x310 image
string tileActivationArguments = dynamicTileId;
var secondaryTile = new SecondaryTile(dynamicTileId, selectedItem.Title, tileActivationArguments, largeLogo, TileSize.Square310x310);
secondaryTile.VisualElements.ForegroundText = ForegroundText.Light;
secondaryTile.VisualElements.BackgroundColor = Colors.CadetBlue;
secondaryTile.VisualElements.Square310x310Logo = largeLogo;
secondaryTile.VisualElements.Square150x150Logo = logo;
secondaryTile.VisualElements.Wide310x150Logo = wideLogo;
await secondaryTile.RequestCreateAsync();
I'm having this error while the app tries to use the 310x310 logo:
WinRT information: Could not initialize secondary tile with provided arguments.
All the other images work fine. I'm using this picture for testing : http://www.usatodayeducate.com/staging/wp-content/uploads/2013/03/310x310-0313-gapyear.jpg
if i comment the line that includes the 310x310 logo everything works fine.
Any idea why this is happening?
As per the SecondaryTile class
public SecondaryTile(string tileId, string displayName, string arguments, Uri square150x150Logo, TileSize desiredSize);
where
desiredSize:The size of tile to pin. This value must be Default
(which provides Windows 8 behavior), Square150x150, or Wide310x150.
Any other TileSize value causes an exception to be thrown during
runtime.
Here you used 310x310 size for desiredSize which is not acceptable by the Secondary tile.
Please check your code.
looks that you're using a high dpi image, 300 dpi.
I was reviewing the image and the unique attribute looking unusual is image dpi (high).
Try using same image in traditional screen 96 dpi, you could try with this one I have conveted to 96 dpi:
You cannot link to web resources.
They must be either local in the app (A path within the deployed app package. This path is resolved for languages and DPI plateau supported by the app.) or on the user device (A file found in the per-user app storage.).
Documentation of this:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.startscreen.secondarytilevisualelements.square310x310logo.aspx