Answered by:
[WP8.1][C#]Take photo the same as the camera app

Question
-
I'm writing a WinRT Universal application which has a section that allows the user to take a photo. In the Windows Store version I have use the CameraCaptureUI class to display a camera page but this class is not available for Windows Phone (as yet!)
I created something similar for the Phone app using a CaptureElement and a MediaCapture class but I cannot get it to take photos exactly the same way as the phone's camera app does. My app requires photos to be taken quite close to the subject but I cannot get it to focus on the subject very well whereas the phone's camera app is very good at doing this.
I'm setting the focus settings with this code:
var focusSettings = new FocusSettings(); focusSettings.AutoFocusRange = AutoFocusRange.FullRange; focusSettings.Mode = FocusMode.Auto; focusSettings.WaitForFocus = true; focusSettings.DisableDriverFallback = false; MediaCapture.VideoDeviceController.FocusControl.Configure(focusSettings);
... and capturing the photo with:
await MediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream1);
Does anyone know if it is possible to mimic what the Camera App does? Is there a better way of doing this?
I don't think my app will be viable unless I can solve this problem but I don't know what to try next.
- Edited by Jamles Hez Thursday, April 30, 2015 9:27 AM modify tag
Wednesday, April 29, 2015 5:13 PM
Answers
-
After quite a bit of experimentation, I found out that the part I had missing was when you actually take the photo. I thought that setting the focus mode to Mode = FocusMode.Auto would mean that the camera automatically focused when you tried to capture the photo stream. Now I know that this is not the case. You have to tell the device to focus each time a photo is taken.
This is my final code for anyone else trying to achieve the same thing:
protected async override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); this.navigationHelper.OnNavigatedTo(e); MediaCapture = new MediaCapture(); DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); DeviceInformation frontCamera = devices.Where(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front).FirstOrDefault(); DeviceInformation backCamera = devices.Where(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back).FirstOrDefault(); DeviceInformation useCamera = (backCamera != null) ? backCamera : frontCamera; if (useCamera != null) { await MediaCapture.InitializeAsync(new MediaCaptureInitializationSettings() { AudioDeviceId = "", VideoDeviceId = useCamera.Id } ); } else await MediaCapture.InitializeAsync(); MediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees); await MediaCapture.VideoDeviceController.SceneModeControl.SetValueAsync(CaptureSceneMode.Auto); if (MediaCapture.VideoDeviceController.WhiteBalanceControl.Supported) await MediaCapture.VideoDeviceController.WhiteBalanceControl.SetPresetAsync(ColorTemperaturePreset.Auto); if (MediaCapture.VideoDeviceController.IsoSpeedControl.Supported) await MediaCapture.VideoDeviceController.IsoSpeedControl.SetAutoAsync(); if (MediaCapture.VideoDeviceController.ExposureControl.Supported) await MediaCapture.VideoDeviceController.ExposureControl.SetAutoAsync(true); if (MediaCapture.VideoDeviceController.ExposureCompensationControl.Supported) await MediaCapture.VideoDeviceController.ExposureCompensationControl.SetValueAsync(0); if (MediaCapture.VideoDeviceController.FlashControl.Supported) { MediaCapture.VideoDeviceController.FlashControl.Auto = true; MediaCapture.VideoDeviceController.FlashControl.Enabled = true; } if (MediaCapture.VideoDeviceController.FocusControl.Supported) MediaCapture.VideoDeviceController.FocusControl.Configure(new FocusSettings { AutoFocusRange = AutoFocusRange.Macro, Mode = FocusMode.Auto, DisableDriverFallback = true, WaitForFocus = true, Distance = ManualFocusDistance.Nearest }); previewElement.Source = MediaCapture; await MediaCapture.StartPreviewAsync(); } public async void TakePhoto() { using (IRandomAccessStream stream1 = new InMemoryRandomAccessStream()) using (IRandomAccessStream stream2 = new InMemoryRandomAccessStream()) { if (MediaCapture.VideoDeviceController.FocusControl.Supported) await MediaCapture.VideoDeviceController.FocusControl.FocusAsync(); await MediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream1); //create decoder and encoder BitmapDecoder dec = await BitmapDecoder.CreateAsync(stream1); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(stream2, dec); //roate the image enc.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees; //write changes to the image stream await enc.FlushAsync(); WriteableBitmap image = new WriteableBitmap(8, 8); stream2.Seek(0); await image.SetSourceAsync(stream2); ((ViewModelCamera)DataContext).Photo = image; photoElement.Source = image; stream2.Seek(0); using (var reader = new DataReader(stream2)) { await reader.LoadAsync((uint)stream2.Size); byte[] buffer = new byte[(int)stream2.Size]; reader.ReadBytes(buffer); ((ViewModelCamera)DataContext).PhotoTaken(buffer); } } }
- Marked as answer by Silverdex Saturday, May 2, 2015 1:48 PM
Saturday, May 2, 2015 1:48 PM
All replies
-
Hi Silverdex,
Before trying to use the Focus Control, I would suggest you to check FocusChangedSupported | focusChangedSupported property if it is supported with Windows Phone.
Besides here is a discussion that can help you: http://stackoverflow.com/questions/25825398/windows-phone-8-1-camera-initialisation take a look to see if it helps.
To help clarify your post and let people easily tell what it is about, please use a clear and concise subject and include applicable tags. We will help to modify the title tag base on this sticky post or you can modify it by yourself(recommended), and thanks for your cooperation.
--James
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.Thursday, April 30, 2015 9:27 AM -
Hi Jamles,
Thanks for the response.
The FocusChangeSupported property will be useful and I've added a check to my app but I have experimented using the code in the link and I still cannot mimic the exact behaviour of the camera app.
I'm really not sure what I'm missing. I've also played around with the flash settings (as the camera app tends to flash at close range) but with no success.
Thursday, April 30, 2015 9:07 PM -
After quite a bit of experimentation, I found out that the part I had missing was when you actually take the photo. I thought that setting the focus mode to Mode = FocusMode.Auto would mean that the camera automatically focused when you tried to capture the photo stream. Now I know that this is not the case. You have to tell the device to focus each time a photo is taken.
This is my final code for anyone else trying to achieve the same thing:
protected async override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); this.navigationHelper.OnNavigatedTo(e); MediaCapture = new MediaCapture(); DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); DeviceInformation frontCamera = devices.Where(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front).FirstOrDefault(); DeviceInformation backCamera = devices.Where(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back).FirstOrDefault(); DeviceInformation useCamera = (backCamera != null) ? backCamera : frontCamera; if (useCamera != null) { await MediaCapture.InitializeAsync(new MediaCaptureInitializationSettings() { AudioDeviceId = "", VideoDeviceId = useCamera.Id } ); } else await MediaCapture.InitializeAsync(); MediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees); await MediaCapture.VideoDeviceController.SceneModeControl.SetValueAsync(CaptureSceneMode.Auto); if (MediaCapture.VideoDeviceController.WhiteBalanceControl.Supported) await MediaCapture.VideoDeviceController.WhiteBalanceControl.SetPresetAsync(ColorTemperaturePreset.Auto); if (MediaCapture.VideoDeviceController.IsoSpeedControl.Supported) await MediaCapture.VideoDeviceController.IsoSpeedControl.SetAutoAsync(); if (MediaCapture.VideoDeviceController.ExposureControl.Supported) await MediaCapture.VideoDeviceController.ExposureControl.SetAutoAsync(true); if (MediaCapture.VideoDeviceController.ExposureCompensationControl.Supported) await MediaCapture.VideoDeviceController.ExposureCompensationControl.SetValueAsync(0); if (MediaCapture.VideoDeviceController.FlashControl.Supported) { MediaCapture.VideoDeviceController.FlashControl.Auto = true; MediaCapture.VideoDeviceController.FlashControl.Enabled = true; } if (MediaCapture.VideoDeviceController.FocusControl.Supported) MediaCapture.VideoDeviceController.FocusControl.Configure(new FocusSettings { AutoFocusRange = AutoFocusRange.Macro, Mode = FocusMode.Auto, DisableDriverFallback = true, WaitForFocus = true, Distance = ManualFocusDistance.Nearest }); previewElement.Source = MediaCapture; await MediaCapture.StartPreviewAsync(); } public async void TakePhoto() { using (IRandomAccessStream stream1 = new InMemoryRandomAccessStream()) using (IRandomAccessStream stream2 = new InMemoryRandomAccessStream()) { if (MediaCapture.VideoDeviceController.FocusControl.Supported) await MediaCapture.VideoDeviceController.FocusControl.FocusAsync(); await MediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream1); //create decoder and encoder BitmapDecoder dec = await BitmapDecoder.CreateAsync(stream1); BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(stream2, dec); //roate the image enc.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees; //write changes to the image stream await enc.FlushAsync(); WriteableBitmap image = new WriteableBitmap(8, 8); stream2.Seek(0); await image.SetSourceAsync(stream2); ((ViewModelCamera)DataContext).Photo = image; photoElement.Source = image; stream2.Seek(0); using (var reader = new DataReader(stream2)) { await reader.LoadAsync((uint)stream2.Size); byte[] buffer = new byte[(int)stream2.Size]; reader.ReadBytes(buffer); ((ViewModelCamera)DataContext).PhotoTaken(buffer); } } }
- Marked as answer by Silverdex Saturday, May 2, 2015 1:48 PM
Saturday, May 2, 2015 1:48 PM