How to write to InMemoryRandomAccessStream and then read? - c#

I want to write an Image to a stream and read it afterwards.
Im on Win 10 UWP.
My code:
InMemoryRandomAccessStream imrasIn = new InMemoryRandomAccessStream();
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), imrasIn);
DetectedFaces = await _faceClient.DetectAsync(imrasIn.GetInputStreamAt(0).AsStreamForRead());
It does not work, DetectAsync gets an empty stream (Error: Image size is too small).
Do I need other classes? CapturePhotoToStreamAsync wants an IRandomAccessStream and DetectAsync wants a Stream.

I had to rewind the stream before reading (and after writing to it):
imrasIn.Seek(0);

Related

convert stream to audio file

I send an audio file to a server API in MultiPartFormData. for this purpose, first, I convert storage File to Byte format, then I convert Byte to Stream and after that I post with MultiPartFormData request.That server answer my request in MultiPartformData format with an another Audio file too.
I receive that respond in HttpResponceMesseage, my question is how can I convert it to mp3 file?
I am using windows iot with UWP coding platform.
multipartContent.Add(new ByteArrayContent(await GetBytesAsync(storageFile)),"audio","audio.mp3");
request.Content = multipartContent;
var response = await httpClient.SendAsync(request);
var content = new StreamReader(await response.Content.ReadAsStreamAsync()).ReadToEnd();
In UWP, if you want to write to a file using stream, we will following the four-step model:
Open the file to get a stream
Get an output stream.
Create a DataWriter object and call the corresponding Write method.
Commit the data in the data writer and flush the output stream.
Please see Create, write, and read a file and Best practices for writing to files for more information.
The official File access sample for your reference.
I done it with extra following code.
first, I convert response to byte[] array, then I write bytes to file within new task thread,that because of main thread correspond to UI won't let another Async task run on it.
var response = await httpClient.SendAsync(request);
byte[] x=await response.Content.ReadAsByteArrayAsync();
await Task.Run(() =>
System.IO.File.WriteAllBytes(storageFile.Path,x));

Is there a build in TwoWay Stream

I have a webapi (asp.net core) that receive a file and post to another webAPI
for now, I create a FileStream , and using HttpClient to Post this file.
But I wonder is that a two way Stream that can replace the FileStream, I mean a Stream that's ReadAsync will wait until it have enough bytes for read's buffer.
var content = new MultipartFormDataContent();
// the problem is here, the stream must be ready for "read to end",
// so I buffered the uploaded file to a FileStream
content.Add(new StreamContent(filestream),"file1","myfilename");
await client.PostAsync("url",content )

Stream pass through

Considered we have two methods:
Task DownloadFromAToStreamAsync(Stream destinationStream);
Task UploadToBFromStreamAsync(Stream sourceStream);
Now we need to download content from A and upload it to B in a single operation.
One of the solutions:
using (var stream = new MemoryStream())
{
await DownloadFromAToStreamAsync(stream);
stream.Seek(0, SeekOrigin.Begin);
await UploadToBFromStreamAsync(stream);
}
But this solution requires the whole stream content to be loaded in memory.
How to solve the task more efficiently?
Change the Download method to accept an additional size parameter which indicates how much to download. Then loop downloading and uploading untill a download returns an empty stream.

C# / WinRT: How to save image to file

I'm an iOS developer learning Windows Store App development with no previous Microsoft technology experience.
I need to save an image to a file. I figured this would be easy, but I've been at it for a day and I've got nothing to show for it. Either this is extremely difficult in Windows, or I'm missing something due to ignorance of the platform / APIs.
The source of the image I need to save is Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap. RenderTargetBitmap can return an image as either a source for Windows.UI.Xaml.Controls.Image or as a IBuffer.
I can verify that RenderTargetBitmap is rendering the image correctly. However, I have not been able to save the image to a file. I'd hoped that Image would have a Save() method, but it doesn't. So I figured I'd need to use the IBuffer somehow. I got close, I was able to save the buffer to disk, but it was unencoded, so I couldn't open it in anything.
So, next, I tried converting the buffer to a stream, encoding that into PNG with BitmapEncoder. That worked, but that left me with my PNG data in a IRandomAccessStream. I have no idea how to save a IRandomAccessStream to a file.
I tried 5-10 different convoluted approaches, such as going through type conversion hell to attempt to turn a IRandomAccessStream into an IBuffer so I could use .WriteAsync() on a file stream. I tried using a DataWriter on a file stream fed by a DataReader on my IRandomAccessStream but I ran into a type mismatch problem. Etc, etc.
So, how can I save my file? Here's what I got so far:
private async void saveButton_Click(object sender, RoutedEventArgs e)
{
//Create a new temporary image for saving
//Image tempImage = new Image();
//Create a render object
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
//Render the app's display buffer
await renderTargetBitmap.RenderAsync(null);
//Set the temp image to the contents of the app's display buffer
//tempImage.Source = renderTargetBitmap;
//Create a new file picker, set the default name, and extenstion
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedFileName = "New LightTable.png";
savePicker.FileTypeChoices.Add("Image", new List<string>(){".png"});
//Get the file the user selected
StorageFile saveFile = await savePicker.PickSaveFileAsync();
//Only move on if the user actually selected a file
if (saveFile != null)
{
//Get a buffer of the pixels captured from the screen
Windows.Storage.Streams.IBuffer buffer = await renderTargetBitmap.GetPixelsAsync();
//Get a stream of the data in the buffer
System.IO.Stream stream = buffer.AsStream();
//Convert the stream into a IRandomAccessStream because I don't know what I'm doing.
Windows.Storage.Streams.IRandomAccessStream raStream = stream.AsRandomAccessStream();
//Attempt to encode the stream into a PNG
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, raStream);
//Get a stream for the file the user selected
Windows.Storage.Streams.IRandomAccessStream fileStream = await saveFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
//FIND SOME WAY TO SAVE raStream TO fileStream
//Something like:
// await fileStream.WriteAsync(raStream.AsStreamForRead());
}
}
Either I'm just missing the very end: how to write my raStream to a file, or my approach is totally off.
I appreciate the help. Keep in mind I've only been developing with Microsoft tech for a week now. I have no .NET, Silverlight, or other MS tech experience. Saving an encoded image from a UIImage control on iOS is a single method call, so the shear complexity of the solution I'm circling makes me think I'm missing something really easy that I just don't know about.
You need to set the pixel data into the StorageFile stream. See http://basquang.wordpress.com/2013/09/26/windows-store-8-1-save-visual-element-to-bitmap-image-file/ for an example.

Streaming with go-between in Windows 8

I want to stream data from a server into a MediaElement in my Windows 8 Store (formerly Metro) app. However, I need to "record" the stream while it is streaming, so it can be served from cache if re-requested, so I don't want to feed the URL directly into the MediaElement.
Currently, the stumbling block is that MediaElement.SetSource() accepts an IRandomAccessStream, not a System.IO.Stream, which is what I get from HttpWebResponse.GetResponseStream().
The code I have now, which does not work:
var request = WebRequest.CreateHttp(url);
request.AllowReadStreamBuffering = false;
request.BeginGetResponse(ar =>
{
var response = ((HttpWebResponse)request.EndGetResponse(ar));
// this is System.IO.Stream:
var stream = response.GetResponseStream();
// this needs IRandomAccessStream:
MediaPlayer.SetSource(stream, "audio/mp3");
}, null);
Is there a solution that allows me to stream audio, but allows me to copy the stream to disk when it has finished reading from the remote side?
I haven't experimented with the following idea, but it might work: You could start streaming the web data into a file and then, after a few seconds (for buffering), pass that file to the MediaElement.
I noticed that MediaElement can be picky about opening a file that is being written into, but I have seen it work. Though, I can't say why it sometimes work and why it sometimes doesn't.
I guess this would help you to convert Stream to IRandomAccessStream
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
using (Stream stream = response.GetResponseStream();)
{
await stream.CopyToAsync(ras.AsStreamForWrite());
}

Categories

Resources