windows 10 mobile camera - c#

I'm trying to use the camera in a Windows 10 Mobile App but an error is occurring when I take the picture and try to show it on the screen.
Here's the code:
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo == null)
{
// User cancelled photo capture
return;
}
StorageFolder destinationFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await photo.CopyAsync(destinationFolder, "ProfilePhoto.jpg", NameCollisionOption.ReplaceExisting);
await photo.DeleteAsync();
IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap,
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied);
SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);
imageControl.Source = bitmapSource;
The exception message:
An exception of type 'System.IO.FileNotFoundException' occurred in
System.Private.CoreLib.dll but was not handled in user code
Additional information: The system cannot find the file specified.
(Exception from HRESULT: 0x80070002)
If there is a handler for this exception, the program may be safely continued."
Someone can help me with this?

This is because you deleted the photo but then trying to read the photo which has just deleted, so the exception "FileNotFound" will throw. Please remove the following code line it will work.
await photo.DeleteAsync();
But I think what you really want to do is to delete the photo which is got from the CameraCaptureUI, and then read the photo from the local folder which has already copied. In that case, code should be as followings:
await photo.CopyAsync(destinationFolder, "ProfilePhoto.jpg", NameCollisionOption.ReplaceExisting);
await photo.DeleteAsync();
StorageFile newphoto = await destinationFolder.GetFileAsync("ProfilePhoto.jpg");
IRandomAccessStream stream = await newphoto.OpenAsync(FileAccessMode.Read);

Related

how to get Bytes of a file for sending in UWP?

I'm a newbie in UWP and i want to open a file of any type and transmit the bytes of it to the reciever. forexample for a jpg file i wrote this code:
// Create FileOpenPicker instance
FileOpenPicker fileOpenPicker = new FileOpenPicker();
// Set SuggestedStartLocation
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
// Set ViewMode
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
fileOpenPicker.FileTypeFilter.Clear();
fileOpenPicker.FileTypeFilter.Add(".jpg");
// Open FileOpenPicker
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
byte[] bytesRead = File.ReadAllBytes(file.Path);
string Paths =
#"C:\\Users\zahraesm\Pictures\sample_reconstructed.jpg";
File.WriteAllBytes(Paths, bytesRead);
the two last lines are for writing the bytes into a file supposing in the receiver. However i keep getting the following exception:
System.InvalidOperationException: 'Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run.'
Try this Code.
try {
FileOpenPicker openPicker = new FileOpenPicker {
ViewMode = PickerViewMode.Thumbnail,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
FileTypeFilter = { ".jpg", ".jpeg", ".png" }
};
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null) {
using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read)) {
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
var LoadReader = await reader.LoadAsync((uint)fileStream.Size);
byte[] pixels = new byte[fileStream.Size];
reader.ReadBytes(pixels);
}
}
} catch (Exception ex) {
}
consider wrapping last operation in Task.Run()
await Task.Run(()=>{
byte[] bytesRead = File.ReadAllBytes(file.Path);
string Paths =
#"C:\\Users\zahraesm\Pictures\sample_reconstructed.jpg";
File.WriteAllBytes(Paths, bytesRead);
});
You should directly read the bytes from the StorageFile returned from your FilePicker, lest you end up with File permission errors in the future.
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
var buffer = await FileIO.ReadBufferAsync(file);
byte[] bytes = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.ToArray(buffer);
You should also use await FileIO.WriteBytesAsync(targetFile, myBytes) to write.
Unless you have broadFileSystemAccess in your package Manifest, you should generally avoid using the System.IO API unless you know your application explicitly has permission to access files in that area (i.e., your application's local storage), and instead use Windows.Storage API's
Check MSDN for File Access Permissions for UWP apps for more information on file permissions.
And if you do use System.IO, always perform the work on the background thread via await Task.Run(() => { ... }

How to downscale the pixel values in UWP App (C#)?

I built a UWP App based on the Squeeze Net example provided in the repository (C#) that uses a Deep Learning model (ONNX) for image classification. I have built the deep learning model in PyTorch where the pixel values of the image have been scaled down from the range [0, 255] to [0, 1] and then normalized with channel wise (RGB) standard deviation and mean. So, this model expects the pixel values other than [0, 255] range.
But in the UWP App, I'm unable to perform this downscaling of the pixel values before binding the inputs to the model. I have searched the SoftwareBitmap class but couldn't find a way to perform this downscaling operation. Any help would be very very appreciated.
I need this operation somewhere in between these lines of code.
await LoadModel();
// Trigger file picker to select an image file
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
StorageFile file = await picker.PickSingleFileAsync();
outputTextBlock.Text = $"The selected Image: {file.Name}";
SoftwareBitmap softwareBitmap;
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
{
// Create the decoder from the stream
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
PixelDataProvider random = await decoder.GetPixelDataAsync();
// byte[] pD = random.DetachPixelData();
//await FileIO.WriteBytesAsync("path/file.ext", pD);
// System.IO.File.WriteAllBytes("path/file.ext", pD);
// byteData.Text = $"{pD}";
// Get the SoftwareBitmap representation of the file in BGRA8 format
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore);
}
var streamD = await file.OpenReadAsync();
var imageSource = new BitmapImage();
await imageSource.SetSourceAsync(streamD);
selectedImage.Source = imageSource;
// Display the image
//SoftwareBitmapSource imageSource = new SoftwareBitmapSource();
//await imageSource.SetBitmapAsync(softwareBitmap);
//selectedImage.Source = imageSource;
// Encapsulate the image within a VideoFrame to be bound and evaluated
VideoFrame inputWoodImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
await EvaluateVideoFrameAsync(inputWoodImage);
this is a repost of this thread here that contains some answers and is more actual:
https://github.com/Microsoft/Windows-Machine-Learning/issues/22

DataPackage.SetBitmap is not working in Windows phone 8.1 WinRT App

I am using following code to share image in my windows phone 8.1 App.
private async void MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(this);
// 1. Get the pixels
IBuffer pixelBuffer = await bitmap.GetPixelsAsync();
byte[] pixels = pixelBuffer.ToArray();
// 2. Write the pixels to a InMemoryRandomAccessStream
var stream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96, 96,
pixels);
await encoder.FlushAsync();
stream.Seek(0);
// 3. Share it
args.Request.Data.Properties.Description = "test";
args.Request.Data.Properties.Title = "test";
args.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));
deferral.Complete();
}
Above code shows 'Preparing content to share' view but it doesn't show the list of apps to share the image.
However, everything works fine if I use DataPackage.SetText.
Couldn't figure out the problem.Please help me!
Below two links helped me in capturing screenshot.
Taking Screenshot
Saving and Sharing Screenshot
Save image to file, then attach file do DataPackage like this:
args.Request.Data.SetStorageItems(new List<IStorageFile> { yourPngFile });

Windows UWP C# delete folder

When I try to delete a folder I get the following error:
Exception thrown: 'System.UnauthorizedAccessException' in mscorlib.ni.dll
Additional information: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
The whole block of code is here:
StorageFolder folder;
try
{
folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("images");
await folder.DeleteAsync();
StorageFolder new_images = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.ReplaceExisting);
}
catch (FileNotFoundException ex)
{
StorageFolder new_images = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.ReplaceExisting);
}
The error occurs on this line:
await folder.DeleteAsync();
I'm guessing the issue comes when I add a bunch of images from the images folder like so:
tmp.Source = new BitmapImage(new Uri("ms-appdata:///local/images/image_" + ring.Name + ".jpg", UriKind.Absolute));
It could also be when I save the image:
try {
StorageFile file = await image_folder.CreateFileAsync("image_" + id + ".jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, responseBytes);
} catch (System.Exception)
{
}
If the issue comes because it is reading it and I try to delete the folder, how can I make it work, I honestly don't know what to do here.
Exception thrown: 'System.UnauthorizedAccessException' in mscorlib.ni.dll
I noticed that you were trying to save the image using FileIO.WriteBytesAsync() method, I couldn't see how you load the image file to Byte array. The most possible reason is "forgot to dispose of the stream after opening it to load image data"
This is the way I load an image and save to LocalFolder:
private async Task<byte[]> ConvertImagetoByte(StorageFile image)
{
IRandomAccessStream fileStream = await image.OpenAsync(FileAccessMode.Read);
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
byte[] pixels = new byte[fileStream.Size];
reader.ReadBytes(pixels);
return pixels;
}
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
var uri = new Uri("ms-appx:///images/image.jpg");
var img = await StorageFile.GetFileFromApplicationUriAsync(uri);
byte[] responseBytes = await ConvertImagetoByte(img);
var image_folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.OpenIfExists);
StorageFile file = await image_folder.CreateFileAsync("image_test.jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, responseBytes);
tmp.Source = new BitmapImage(new Uri("ms-appdata:///local/images/image_test.jpg", UriKind.Absolute));
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
It may sound strange but at times authorization type of issues occur when we don't start our IDE as an administrator. Which is done by right clicking on the IDE (Visual Studio) icon and then select 'Run as Administrator'
Try this if it resolves your issue.
You need to use lock to be sure that file or folder will not be modified while it using in another thread. Since you are using await I would suggest to take a look at this - https://github.com/bmbsqd/AsyncLock/
You can get more info about thread sync here - https://msdn.microsoft.com/ru-ru/library/ms173179(v=vs.80).aspx

MediaCapture SetEncodingPropertiesAsync returns exception The stream number provided was invalid. PreviewState

I'm working on a Universal Windows App for my Windows Phone (Lumia 950 with Windows 10). It's a very simple app which takes a photo using the front camera of the phone.
The problem is that the photo being taken is in landscape mode by default, which isn't great when it's a selfie. I'd like to rotate it 90 degrees so that it becomes a portrait. I use the MediaCapture object to initialize the camera. I've tried the following to rotate the image:
await _mediaCapture.InitializeAsync(settings);
var videoEncodingProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
videoEncodingProperties.Properties.Add(new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1"), 90);
await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, videoEncodingProperties, null);
But the last line throws an exception "The stream number provided was invalid. PreviewState". I'm guessing this has to do with the GUID provided, but after countless hours googling I keep finding this value that developers use for this.
I tried another solution to rotate the image:
_mediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
But that doesn't do anything.
Any ideas how I can rotate the image? Thanks a lot!
To rotate the preview, you need an active preview. This means you need to attach the mediaCapture to your capture element, then start the preview, and finally set the rotation with SetPreviewRotation.
If you do that, it should work perfectly.
Since pretty much nothing worked for me, I ended up re-writing most of the application in order to rotate the image. Here are the essential parts of my code that worked in the end:
private async void TakePicture()
{
var stream = new InMemoryRandomAccessStream();
try
{
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
var photoOrientation = _foundFrontCam ? PhotoOrientation.Rotate90 : PhotoOrientation.Normal;
var photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync("Photo.jpeg", CreationCollisionOption.GenerateUniqueName);
await ReencodeAndSavePhotoAsync(stream, photoOrientation, photoFile);
var imageBytes = await ShowPhotoOnScreenThenDeleteAsync(photoFile);
PostToServerAsync(imageBytes);
}
catch (Exception ex)
{
new MessageDialog(ex.Message).ShowAsync();
}
}
private async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, PhotoOrientation photoOrientation, StorageFile photoFile)
{
using (var inputStream = stream)
{
var decoder = await BitmapDecoder.CreateAsync(inputStream);
using (var outputStream = await photoFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
var properties = new BitmapPropertySet { { "System.Photo.Orientation", new BitmapTypedValue(photoOrientation, PropertyType.UInt16) } };
await encoder.BitmapProperties.SetPropertiesAsync(properties);
await encoder.FlushAsync();
}
}
}
Creating a PhotoOrientation object and passing that as part of the input stream when saving the image did the trick.

Categories