I'm trying to get this mini app to save the photo taken by the camera but I get this error.System.IO.FileNotFoundException: 'The system cannot find the file specified. (Exception from HRESULT: 0x80070002)'
I followed the Microsoft Tutorial but cant get it to work.
private async void btnTakePhoto_Click(object sender, RoutedEventArgs e)
{
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
//StorageFile photo = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/mypic.jpg"));
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;
}
From the above mentioned code snippet remove the line that I have written below.
await photo.DeleteAsync();
After removing the line it works fine.
Related
i need to save the picture getting from the camera in a specific folder but i can't find the way, i онли show it in the xaml.
class CameraOpening{
public async Task<SoftwareBitmapSource> PhotoTake(){
var captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.AllowCropping = false;
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
var bitmapSource = new SoftwareBitmapSource();
if (photo != null){
var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(
"ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await photo.CopyAsync(folder,"ProfilePhoto.jpg",NameCollisionOption.ReplaceExisting);
using (var stream = await photo.OpenAsync(FileAccessMode.Read)){
var decoder = await BitmapDecoder.CreateAsync(stream);
var softwareBitmap = await decoder.GetSoftwareBitmapAsync();
var softwareBitmapBGR8 = SoftwareBitmap.Convert(
softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);}
await photo.DeleteAsync();}
return bitmapSource;}}
public async void Buttonfoto(object sender, RoutedEventArgs e)
{
var cam = new CameraOpening();
imageControl.Source = await cam.PhotoTake();
}
and the xaml has the Image and the Button
there is a way for save the picture taken in a specific directory?
or a copy of it.
Lines:
var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await photo.CopyAsync(folder, "ProfilePhoto.jpg", NameCollisionOption.ReplaceExisting);
already seems to be saving your photo to path ./ProfilePhotoFolder/ProfilePhoto.jpg.
But it will save only if picture was actually taken.
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
// < ... >
if (photo != null) { /* save file! */ }
Check what captureUI.CaptureFileAsync actually returns.
If it's null - nothing will happen.
But if your photo is being taken and already saving itself to ./ProfilePhotoFolder/ProfilePhoto.jpg you can save it again via:
await photo.CopyAsync(folder, "C:\\SomeFolder\\MyPhoto.jpg", NameCollisionOption.ReplaceExisting);
Or copy already created picture via:
File.Copy(".\\ProfilePhotoFolder\\ProfilePhoto.jpg", "C:\\SomeFolder\\MyPhoto.jpg");
More info here:
System.IO and System.IO.File
When I'm using below code for image processing it throws exception at FlushAsync(). Strangely this issue happens for some video files only. Can you help why this happen ?
private async Task<String> PreProcessVideoToGetTextAsync(StorageFile file, int i)
{ /*--------To get frame from video----------*/
var thumbnail = await GetThumbnailAsync(file, i);
BitmapImage bitmapImage = new BitmapImage();
StringBuilder ocr = null;
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
await RandomAccessStream.CopyAsync(thumbnail, randomAccessStream);
randomAccessStream.Seek(0);
SoftwareBitmap inputBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
// create a new stream and encoder for the new image
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder);
BitmapBounds bounds = new BitmapBounds();
bounds.Height = 270;//screnheight/4 =270
bounds.Width = 960;//screenwidth/2 =960
bounds.X = 960;//screenwidth/2 =960
bounds.Y = 810;
enc.BitmapTransform.Bounds = bounds;
// write out to the stream
try
{
await enc.FlushAsync();
}
catch (Exception ex)
{
string exx = ex.ToString();
var dialog = new MessageDialog(exx);
await dialog.ShowAsync();
}
//Remain portion of code
}
I've already used the following code snippet to save video thumbnails in my uwp app, hopefully you can apply a little bit of changes as you want to use it.
private async Task PreProcessVideoToGetTextAsync(string videopath)
{
try
{
SoftwareBitmap softwareBitmap = null;
StorageFile videofile = await StorageFile.GetFileFromPathAsync(videopath);
var thumbnail = await GetThumbnailAsync(videofile);
Windows.Storage.Streams.InMemoryRandomAccessStream randomAccessStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
await Windows.Storage.Streams.RandomAccessStream.CopyAsync(thumbnail, randomAccessStream);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
StorageFile outputFile = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync(Path.GetFileNameWithoutExtension(videopath) + ".jpg");//save path for video thumbnail image in app cache folder
using (Windows.Storage.Streams.IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetSoftwareBitmap(softwareBitmap);
encoder.BitmapTransform.ScaledWidth = 128;//thumbnail width
encoder.BitmapTransform.ScaledHeight = 128;//thumbnail height
encoder.IsThumbnailGenerated = true;
try
{
await encoder.FlushAsync();
if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
{
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
var source = new Windows.UI.Xaml.Media.Imaging.SoftwareBitmapSource();
await source.SetBitmapAsync(softwareBitmap);
return;
}
catch (Exception err)
{
switch (err.HResult)
{
case unchecked((int)0x88982F81): //WINCODEC_ERR_UNSUPPORTEDOPERATION
// If the encoder does not support writing a thumbnail, then try again
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw err;
}
}
if (encoder.IsThumbnailGenerated == false)
{
await encoder.FlushAsync();
}
}
return;
}
catch (Exception)
{
return;
}
finally
{
GC.Collect();
}
}
private async Task<Windows.Storage.Streams.IInputStream> GetThumbnailAsync(StorageFile file)
{
var mediaClip = await Windows.Media.Editing.MediaClip.CreateFromFileAsync(file);
var mediaComposition = new Windows.Media.Editing.MediaComposition();
mediaComposition.Clips.Add(mediaClip);
return await mediaComposition.GetThumbnailAsync(
TimeSpan.Zero, 0, 0, Windows.Media.Editing.VideoFramePrecision.NearestFrame);
}
}
I have a list of Bitmap images. I need to save them to local folder.
This doesn't work on windows 10 Universal application.
var serializer = new DataContractSerializer(typeof(List<BitmapImage>));
using (var stream = await ApplicationData.Current.LocalCacheFolder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting)) {
serializer.WriteObject(stream, collection);
}
WriteObject method throws the following error
Exception thrown: 'System.Runtime.Serialization.InvalidDataContractException' in System.Private.DataContractSerialization.dll
BitmapImage is not serializable. Convert that to a byte array and write that to disk instead:
public static byte[] ConvertToBytes(BitmapImage bitmapImage)
{
using (var ms = new MemoryStream())
{
var btmMap = new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
btmMap.SaveJpeg(ms, bitmapImage.PixelWidth, bitmapImage.PixelHeight, 0, 100);
return ms.ToArray();
}
}
var serializer = new DataContractSerializer(typeof(byte[]));
using (var stream = await ApplicationData.Current.LocalCacheFolder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting)) {
serializer.WriteObject(stream, ConvertToBytes(collection));
}
You cannot extract the bitmap from a BitmapImage. There is no way to save a BitmapImage to file directly. The only way is to remember the original source and save that out. For more details about save BitmapImage to file please reference this thread.
If you know the original source, for example, you read the BitmapImage from the file picked by a FileOpenPicker, then you can read the image file to a WriteableBitmap then you can extract the PixelBuffer, encode it with a BitmapEncoder, and then save the resulting stream to a StorageFile as Rob said. Sample code as follows:
private async void btncreate_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker openpicker = new FileOpenPicker();
openpicker.FileTypeFilter.Add(".jpg");
openpicker.FileTypeFilter.Add(".png");
StorageFile originalimage = await openpicker.PickSingleFileAsync();
WriteableBitmap writeableimage1;
using (IRandomAccessStream stream = await originalimage.OpenAsync(FileAccessMode.Read))
{
SoftwareBitmap softwareBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
writeableimage1 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
writeableimage1.SetSource(stream);
}
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile newimage = await folder.CreateFileAsync(originalimage.Name, CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream ras = await newimage.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ras);
var stream = writeableimage1.PixelBuffer.AsStream();
byte[] buffer = new byte[stream.Length];
await stream.ReadAsync(buffer, 0, buffer.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage1.PixelWidth, (uint)writeableimage1.PixelHeight, 96.0, 96.0, buffer);
await encoder.FlushAsync();
}
}
For list of images, you may need save them one by one.
I have to save a content from Image tag to a file. I used a lot of Uncle Google but he doesn't know :(
private void QRbutton_Click(object sender, RoutedEventArgs e)
{
IBarcodeWriter writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.Common.EncodingOptions
{
Height = 1200,
Width = 1200
}
};
String message = "";
if (String.IsNullOrEmpty(QRtxt.Text))
{
message = "You send empty message. ";
}
else
{
//Saving Input to string
message = QRtxt.Text;
StckPnlProfile_Layout.Visibility = Visibility.Collapsed;
QRsendbtn.Visibility = Visibility.Visible;
}
var result = writer.Write(message);
var wb = result.ToBitmap() as WriteableBitmap;
System.Diagnostics.Debug.WriteLine("BEFORE[Saving image to file]");
QRimage.Source = wb;
}
And there is XAML code of Image:
<Image x:Name="QRimage" Height="300"/>
I think your only option can be using RenderTargetBitmap class , it captures an image from any UIElement inherited class type like Image.
https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.rendertargetbitmap.aspx
HesamM, thank you for your response. Actually I did it in this way:
private async void saveImage(object sender, RoutedEventArgs e)
{
Debug.WriteLine("********** Function STARTED: Save QR code as image to jpg **********");
try
{
System.Diagnostics.Debug.WriteLine("Searching for assets folder.");
var package = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder localFolder = await package.GetFolderAsync("Assets");
StorageFile file = await localFolder.CreateFileAsync("savedimage.jpg", CreationCollisionOption.ReplaceExisting);
var renderTargetBitmap = new RenderTargetBitmap();
System.Diagnostics.Debug.WriteLine("Rendering an image.");
await renderTargetBitmap.RenderAsync(QRimage);
var pixels = await renderTargetBitmap.GetPixelsAsync();
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
System.Diagnostics.Debug.WriteLine("Save QR code to jpg.");
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
bytes);
await encoder.FlushAsync();
}
MessageDialog SuccessMsg = new MessageDialog("Code QR saved.");
await SuccessMsg.ShowAsync();
}
catch (Exception ex)
{
//MessageDialog ErrMsg = new MessageDialog("Error Ocuured!");
System.Diagnostics.Debug.WriteLine("ERROR ZAPISU PLIKU: " + ex);
}
Debug.WriteLine("********** Function STOPPED: Save QR code as image to jpg **********");
}
Is there a way I can get the image as Stream and then store it locally to upload it to server?
So far I found the code below which lets me load the image to an image view , but how do I create a stream from the image source to pass it to SaveToLocalFolderAsync method?
private async void viewActivated(CoreApplicationView sender, IActivatedEventArgs args1)
{
FileOpenPickerContinuationEventArgs args = args1 as FileOpenPickerContinuationEventArgs;
if (args != null)
{
if (args.Files.Count == 0) return;
view.Activated -= viewActivated;
StorageFile storageFile = args.Files[0];
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
await bitmapImage.SetSourceAsync(stream);
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
imgCover.Source = bitmapImage;
//save the image in local folder
//SaveToLocalFolderAsync(stream, "Test.jpg");
}
}
public async Task SaveToLocalFolderAsync(Stream file, string fileName)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await localFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream outputStream = await storageFile.OpenStreamForWriteAsync())
{
await file.CopyToAsync(outputStream);
}
}