I see solution for this problem:
Saving as jpeg from memorystream in c#
but it does not work in winRT.
Is there a simple way to save MemoryStream as JPEG using FileSavePicker?
I tried:
private async void Save_Image(MemoryStream image)
{
// Launch file picker
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("JPeg", new List<string>() { ".jpg", ".jpeg" });
StorageFile file = await picker.PickSaveFileAsync();
if (file == null)
return;
Stream x = await file.OpenStreamForWriteAsync();
image.WriteTo(x)
}
but it is saving blank file. May be I am doing something wrong.
Tried one more approach but again blank image:
private async void Save_Image(MemoryStream image)
{
// Launch file picker
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("JPeg", new List<string>() { ".jpg", ".jpeg" });
StorageFile file = await picker.PickSaveFileAsync();
if (file == null)
return;
int end = (int)image.Length;
byte[] buffer = new byte[end];
await image.ReadAsync(buffer, 0, end);
await FileIO.WriteBytesAsync(file, buffer);
}
Got it! It was the seeking position I was missing and also the "using". Had to set it externally to 0.
Here is the code:
private async void Save_Image(MemoryStream image)
{
// Launch file picker
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("JPeg", new List<string>() { ".jpg", ".jpeg" });
StorageFile file = await picker.PickSaveFileAsync();
if (file == null)
return;
using (Stream x = await file.OpenStreamForWriteAsync())
{
x.Seek(0, SeekOrigin.Begin);
image.WriteTo(x);
}
}
Related
I'm working on a UWP TTS (Text to Speech) application and I'm having trouble saving speech to a file, preferably in Mp3 format. Does anyone know how to do this? In WPF, I used NAUDIO and NAUDIO.LAME, but unfortunately this does not seem to support UWP. I think I have to use Windows.Media.Transcoding API, but I didn't find any examples of how to do that. I found the code below in an article on MSDN, but it is not correct.
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
try
{
SpeechSynthesisStream stream = await WCSVariables.Synthesizer.SynthesizeTextToStreamAsync(rtbText.Text);
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
await FileIO.WriteBufferAsync(file, buffer);
}
}
catch (Exception ex)
{
MessageDialog msgdlg = new MessageDialog(ex.Message);
msgdlg.ShowAsync();
}
********** UPDATE **********
After adding capabilities and file type associations for TXT and MP3, I was able to save the TXT files in any folder, but the MP3 files do not have the correct format. Files are created but do not play audio.
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("Mp3 Audio File", new List<string>() { ".mp3" });
savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
savePicker.SuggestedFileName = "New Document";
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
try
{
if (file.FileType == ".txt")
{
await FileIO.WriteTextAsync(file, rtbText.Text);
}
else
{
string path = file.Path.Remove(file.Path.IndexOf(file.Name), file.Name.Length);
StorageFolder mp3Folder = await StorageFolder.GetFolderFromPathAsync(path);
StorageFile mp3File = await mp3Folder.CreateFileAsync(file.Name, CreationCollisionOption.ReplaceExisting);
SpeechSynthesisStream stream = await WCSVariables.Synthesizer.SynthesizeTextToStreamAsync(rtbText.Text);
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
await FileIO.WriteBufferAsync(mp3File, buffer);
}
}
}
catch (Exception ex)
{
MessageDialog msgdlg = new MessageDialog(ex.Message);
msgdlg.ShowAsync();
}
}
You can first create a .mp3 file and then generate a speech audio stream from a basic text string. After that, write the stream to the file.
StorageFolder folder = KnownFolders.VideosLibrary;
StorageFile file = await folder.CreateFileAsync("MyVideo.mp3",CreationCollisionOption.ReplaceExisting);
if (file != null)
{
try
{
var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Hello World");
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
await FileIO.WriteBufferAsync(file, buffer);
}
}
catch {}
}
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
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);
}
}
I'm trying to save a file to the Documents folder using PickSaveFileAndContinue() method in WP 8.1 RT. Everything is happening fine except the file which gets saved is empty.
When I get the file returned from the following code in OnActivated() method, it's size is zero.
Anyone?
var database = await FileHelper.GetFileAsync(ApplicationData.Current.LocalFolder, DATABASE_NAME);
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("Database File", new List<string>() { ".db" });
savePicker.DefaultFileExtension = ".db";
savePicker.SuggestedFileName = DATABASE_NAME;
savePicker.SuggestedSaveFile = database;
After the location is picked, the following code is executed in App.xaml.cs. I tried doing this inside the same page using a ContinuationManager. But then result is same.
protected async override void OnActivated(IActivatedEventArgs args)
{
byte[] buffer = null;
if(args!=null)
{
if(args.Kind == ActivationKind.PickSaveFileContinuation)
{
var file = ((FileSavePickerContinuationEventArgs)args).File;//This is empty
using (IRandomAccessStreamWithContentType stream = await file.OpenReadAsync())
{
buffer = new byte[stream.Size];
using (DataReader reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(buffer);
}
}
if (file != null)
{
CachedFileManager.DeferUpdates(file);
await FileIO.WriteBytesAsync(file, buffer);
Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
}
}
}
base.OnActivated(args);
}
That's expected. PickSaveFileAndContinue doesn't know what the app wants to save. It just provides an empty StorageFile. The app can then write whatever contents it wants to save into the file.
In my Windows store application, i am displaying a picture using Image control in XAML. Source of the Image control is set, code wise using WriteableBitmap. I am trying to send this image as attachment in email. Is there any easy way for that? I am trying to save that image locally( within application ) and attach that saved image to email. But not able to save locally. Any help is appreciated.
Here is the code.
bitmap = await WriteableBitmapRenderExtensions.Render(dataCanvas);
image.Source = bitmap;
dataCanvas is a Canvas control consists of two images, one place above another. Actually i have to place a sunglass top of users face and display it as another image in xaml. Also email that image.
Check out the WriteableBitmapSaveExtensions class in WinRT XAML Toolkit for all the SaveToFile() extension methods you can use to save your WriteableBitmap.
The core one is this:
public static async Task SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFile outputFile,
Guid encoderId)
{
Stream stream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)writeableBitmap.PixelWidth,
(uint)writeableBitmap.PixelHeight,
96,
96,
pixels);
await encoder.FlushAsync();
using (var outputStream = writeStream.GetOutputStreamAt(0))
{
await outputStream.FlushAsync();
}
}
}
You can get the encoder ID using an overload of the method:
public static async Task<StorageFile> SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFolder storageFolder,
string fileName,
CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
{
StorageFile outputFile =
await storageFolder.CreateFileAsync(
fileName,
options);
Guid encoderId;
var ext = Path.GetExtension(fileName);
if (new[] { ".bmp", ".dib" }.Contains(ext))
{
encoderId = BitmapEncoder.BmpEncoderId;
}
else if (new[] { ".tiff", ".tif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".gif" }.Contains(ext))
{
encoderId = BitmapEncoder.GifEncoderId;
}
else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegEncoderId;
}
else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegXREncoderId;
}
else //if (new [] {".png"}.Contains(ext))
{
encoderId = BitmapEncoder.PngEncoderId;
}
await writeableBitmap.SaveToFile(outputFile, encoderId);
return outputFile;
}
Any subclass of BitmapSource (including WritableBitmap) can be passed to a BitmapEncoder. A BitmapEncoder takes a Stream to which the encoded JPEG, PNG or other image is written.
You can then use a mailer library to reference the stream used by the encoder, or use the Share contract, and pass the stream directly.
Example:
var bitmap = new WritableBitmap();
// ... draw your bitmap
var tempPath = // path to where you want to save (probably in your appx temp);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(bitmap);
using (var fs = new FileStream(tempPath))
{
encoder.Save(fs);
}
// use the image saved to tempPath
// http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh871370.aspx