I am taking pictures with my camera and when OnPictureTaken is called i get a byte[ ] data. I am trying to convert the byte array to a System.IO.Stream. This helps me to analise the image in the Project Oxford API. I've tried in countless ways to do this but it seems I can't find a solution. I would be very grateful if you help me.
You can use the MemoryStream class, which creates a stream backed by a byte array: MSDN link
When using the Client SDK, wich you can get via NuGet, you need to provide a Stream to methods like VisionServiceClient.AnalyzeImageAsync().
You can create a Stream out of an byte[] and provide it to the SDK like this:
using (var stream = new MemoryStream(yourByteArray))
{
var visionServiceClient = new VisionServiceClient("YOUR_API_KEY");
var visualFeatures = new VisualFeature[] { VisualFeature.Adult, VisualFeature.Categories, VisualFeature.Color, VisualFeature.Description, VisualFeature.Faces, VisualFeature.ImageType, VisualFeature.Tags };
var result = await visionServiceClient.AnalyzeImageAsync(stream, visualFeatures);
}
Hint: In Android you often end up with a Android.Graphics.Bitmap object when working with images. Especially when taking pictures with the camera. You can also convert them to streams with imageBitmap.Compress(Bitmap.CompressFormat.Jpeg, 0, stream); but don't forget to "rewind" the stream with stream.Seek(0, SeekOrigin.Begin);, otherwise the SDK will throw an exception.
Related
So I had this bit of code, that works great in my windows c# application or a framework DLL.
private static Icon? LoadSync(string filepath)
{
Stream imageStreamSource = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
BmpBitmapDecoder decoder = new BmpBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
if (bitmapSource.Format != System.Windows.Media.PixelFormats.Bgr565)
{
Debug.Print($"Image at path `{filepath}` is not RGB565!");
return null;
}
byte[] icon = new byte[bitmapSource.PixelHeight * bitmapSource.PixelWidth * sizeof(short)];
bitmapSource.CopyPixels(icon, bitmapSource.PixelWidth * sizeof(short), 0);
return new Icon() { Width = (ushort)bitmapSource.PixelWidth, Height = (ushort)bitmapSource.PixelHeight, Data = icon };
}
It loads a 16 bit .bmp file into memory, and then gives the pixels to me in the form of a byte array.
However, I encountered a weird compile bug, and my online searches seemed to turn up that it was caused by some odd difference in how a function is declared as an extension method in one instance, but an actual member in another. I forget the details but the proposed solution was to switch to a standard dll from framework. I tried it and it fixed my problem.
But now, reintroducing the above code, I no longer have access to System.Windows.Media.Imaging. So I'm wondering what options I have to be able to accomplish the same thing.
Using the plain old bitmap library, the data is converted to (I think) rgb888 without any option to preserve the format.
If you're wondering why I need a byte array, I'm sending the data on to an arduino with a screen.
I have never done exactly what you're trying to do, but I did recently have to work with images in some C# code. I added the System.Drawing NuGet package and made use of the Image class. This might be a help: https://learn.microsoft.com/en-us/dotnet/api/system.drawing.image?view=windowsdesktop-5.0
I have a video file that's already loaded in memory (an IFormFile that's converted to a byte[]).
I've been trying to figure out how to take that video and get a thumbnail image from it, without having to read/write to disk.
I found use cases for MediaToolkit and FFmpeg here, and Movie Thumbnailer here, but from what I can find, those require the video already be saved to disk and have write access to output the thumbnail to a file.
Is there any way I can take either an IFormFile or byte[] and do something similar to what MediaToolkit is doing while being able to keep the result in memory?
I know a lot of folks are saying byte[] isn't the way to go. In that case, I'm more than happy to convert from IFormFile to a Stream, but I still need a way to do that and keep it in memory.
please try this with Windows.Media.Editing should work, not fully tested..
int frameHeight; // you can set the height
int frameWidth; // ...
TimeSpan getFrameInTime = new TimeSpan(0, 0, 1);
//Using Windows.Media.Editing get your ImageStream
var yourClip = await MediaClip.CreateFromFileAsync(someFile);
var composition = new MediaComposition();
// add the section of the video as needed
composition.Clips.Add(yourClip);
// Answer - now that your have your imageStream, get the thumbnail
var yourImageStream = await composition.GetThumbnailAsync(
getFrameInTime,
Convert.ToInt32(frameWidth),
Convert.ToInt32(frameHeight),
VideoFramePrecision.NearestFrame);
//now create your thumbnail bitmap
var yourThumbnailBitmap = new WriteableBitmap(
Convert.ToInt32(frameWidth),
Convert.ToInt32(frameHeight)
);
yourThumbnailBitmap.SetSource(yourImageStream);
I have to create multiple thumbnails and save on amazon s3 in c#. I don't find library which can create thumbnail from memory stream only from source file. But can't have file source, I have only the stream from the upload and I don't want save localy the file.
Thx for ur help!
Simple c# code can do this for you. You can create a thumbnail from byte array.
First convert your memory stream object to byte array by following code
byte[] bytes = memoryStream.ToArray();
and then you can use below method
public byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
using (MemoryStream ms = new MemoryStream())
using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
{
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
I don't find library which can create thumbnail from memory stream only from
source file
Really? Because I do not need a library for that - I can do that with standard C#.
System.Drawing.Bitmap has a constructor accepting a stream.
But can't have file source,
Actually you can - it is called a temporary file and there is a whole mechanism for that in .NET (and windows). Really.
But it is not needed. Read the manual, create a bitmap (by packing your byte array into a MemoryStream) and it should work.
I am attempting to write an audio file as a .wav in a memorystream out to the response so the client can download it. It looks like on client side when trying to open the file it has a ".partial" extension. It is almost as if the file is not getting released to the client.
The below is my code... Attempting to write the bytes directly to the local machine works fine (you will see that code commented out).
// Initialize a new instance of the speech synthesizer.
using (SpeechSynthesizer synth = new SpeechSynthesizer())
using (MemoryStream stream = new MemoryStream())
{
// Create a SoundPlayer instance to play the output audio file.
MemoryStream streamAudio = new MemoryStream();
// Configure the synthesizer to output to an audio stream.
synth.SetOutputToWaveStream(streamAudio);
synth.Speak("This is sample text-to-speech output. How did I do?");
streamAudio.Position = 0;
// Set the synthesizer output to null to release the stream.
synth.SetOutputToNull();
// Insert code to persist or process the stream contents here.
// THIS IS NOT WORKING WHEN WRITING TO THE RESPONSE, .PARTIAL FILE CREATED
Response.Clear();
Response.ContentType = "audio/wav";
Response.AppendHeader("Content-Disposition", "attachment; filename=mergedoutput.wav");
Response.BinaryWrite(streamAudio.GetBuffer());
Response.Flush();
// THIS WORKS WRITING TO A FILE
//System.IO.File.WriteAllBytes("c:\\temp\\als1.wav", streamAudio.GetBuffer());
}
MemoryStream.GetBuffer is not the correct method to call:
Note that the buffer contains allocated bytes which might be unused.
For example, if the string "test" is written into the MemoryStream
object, the length of the buffer returned from GetBuffer is 256, not
4, with 252 bytes unused. To obtain only the data in the buffer, use
the ToArray method; however, ToArray creates a copy of the data in
memory.
so use MemoryStream.ToArray instead:
Response.BinaryWrite(streamAudio.ToArray());
Looks like the issue was the fact the speak method needs to be run on its own thread. The following provides the solution to get back the byte array properly and then be able to write that to the response.
C# SpeechSynthesizer makes service unresponsive
I have a functioning application in c#/.net that currently accepts raw image data in a bayer format from a set of embedded cameras and converts them to jpeg images. To save transmission time, I have modified the embedded devices to encode the images as jpegs prior to transmission. I'm an experienced embedded programmer but a total c#/.net noob. I have managed to modify the application to save the arrays to file with a jpeg name using this snippet: ( the offset of 5 is to skip header data in the transmission frame)
FileStream stream = File.Create(fileName);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(multiBuff.msgData, 5, multiBuff.dataSize - 5);
writer.Close();
The files open up fine, but now I want to treat the data as a bitmap without having to save & load from file. I tried the following on the data array:
MemoryStream stream = new MemoryStream(data);
BinaryReader reader = new BinaryReader(stream);
byte[] headerData = reader.ReadBytes(5);
Bitmap bmpImage = new Bitmap(stream);
But this throws a parameter not valid exception. As a newbie, I'm a little overwhelmed with all the classes and methods for images and it seems like what I'm doing should be commonplace, but I can't find any examples in the usual places. Any ideas?
I think you are looking for Bitmap.FromStream() :
Bitmap bmpImage = (Bitmap)Bitmap.FromStream(stream);
Actually using new Bitmap(stream) should have worked as well - this means that the data in the stream does not constitute a valid image - are you sure the jpg is valid? Can you save it to disk and open it i.e. in Paint to test?
You use the Image class.
Image image;
using (MemoryStream stream = new MemoryStream(data))
{
image = Image.FromStream(stream);
}
FYI it didn't work because reader.ReadBytes(5) returns the 5 first bytes of stream not the bytes after position 5