I'm trying to convert mat image to something that I could set as ImageSource on UWP but I could not find any solution.
The only solution I found show me very bad image:
https://i.stack.imgur.com/uB8oT.png
Here's my code:
VideoCapture _capture = new VideoCapture(0);
while (true)
{
using (Mat mat = new Mat())
{
bool ok = _capture.Read(mat);
if (ok)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.High,
async () =>
{
byte[] imageArray = mat.GetRawData();
WriteableBitmap writableBitmap = new WriteableBitmap(mat.Width, mat.Height);
using (MemoryStream memoryStream = new MemoryStream(imageArray))
{
using (Stream stream = writableBitmap.PixelBuffer.AsStream())
{
await memoryStream.CopyToAsync(stream);
}
}
imageCamera.Source = writableBitmap;
});
}
}
how to convert mat to imageSource on UWP
Currently, the Image control only supports images that use BGRA8 encoding and pre-multiplied or no alpha channel. Before attempting to display an image, test to make sure it has the correct format, and if not, use the SoftwareBitmap static Convert method to convert the image to the supported format.
SoftwareBitmap outputBitmap = SoftwareBitmap.CreateCopyFromBuffer(
writeableBitmap.PixelBuffer,
BitmapPixelFormat.Bgra8,
writeableBitmap.PixelWidth,
writeableBitmap.PixelHeight
);
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(outputBitmap);
Related
I am making a Note application where I can draw with Windows ink and also paste images. I want to save the images and ink in a single file. Therefore I am converting the image to a string in base64 format so that I can easily serialize it. My problem is when I try to recreate the image from the string.
My code to decode the image data into a base64 string:
var decoder = await BitmapDecoder.CreateAsync(imageStream);
var pixels = await decoder.GetPixelDataAsync();
var bytes = pixels.DetachPixelData();
base64String = Convert.ToBase64String(bytes);
My code to encode the base64 string into an image again (This code does NOT work! The image is not added to the redCanvas):
var bytes = Convert.FromBase64String(base64String);
BitmapImage bitmapImage = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
bitmapImage.SetSource(stream);
}
Image image = new Image();
image.Source = bitmapImage;
// Add the image to a second canvas
redCanvas.Children.Add(image);
Full code for pasting the image and creating the base64 string:
private async Task myButton_ClickAsync(object sender, RoutedEventArgs e)
{
var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Bitmap))
{
IRandomAccessStreamReference imageReceived = null;
imageReceived = await dataPackageView.GetBitmapAsync();
if (imageReceived != null)
{
using (var imageStream = await imageReceived.OpenReadAsync())
{
var bitmapImage = new BitmapImage();
bitmapImage.SetSource(imageStream);
var decoder = await BitmapDecoder.CreateAsync(imageStream);
var pixels = await decoder.GetPixelDataAsync();
var bytes = pixels.DetachPixelData();
base64String = Convert.ToBase64String(bytes);
TextBox_Image_Base64.Text = base64;
Image image = new Image();
// Add the image to a list of Images
ListImages.Add(image);
blueCanvas.Children.Add(image);
image.Source = bitmapImage;
TextBlock_Status.Text = "Status : Image is retrieved from the
clipboard and pasted successfully.";
}
}
}
else
{
TextBlock_Status.Text = "Status : Bitmap format is not available in clipboard";
}
}
Anyone have any suggestions as to how I can recreate the image from the string?
Screenshot from my app showing that I am able to paste an image and decode it into a string
How to create Image from string in Base64 (UWP)
We suggest you convet stream buffer to Base64 from imageStream diteactly, but not from PixelData. you could use CryptographicBuffer class to approach.
using (var imageStream = await imageReceived.OpenReadAsync())
{
var buffer = new Windows.Storage.Streams.Buffer((uint)imageStream.Size);
await imageStream.ReadAsync(buffer, (uint)imageStream.Size, InputStreamOptions.None);
String strBase64New = CryptographicBuffer.EncodeToBase64String(buffer);
}
Retrive from base64 string
public static async Task<BitmapImage> LoadBase64(string base64)
{
byte[] bytes = Convert.FromBase64String(base64);
var bitmap = new BitmapImage();
using (MemoryStream ms = new MemoryStream(bytes))
{
await bitmap.SetSourceAsync(ms.AsRandomAccessStream());
}
return bitmap;
}
I have an image that's loaded in XAML using a converter. Rather than load this image again, I want to take that image and find the dominant colour to be able to use for other graphics on the page. So far I have this:
var himage = (BitmapImage)image_home.Source;
using (var stream = await himage.OpenReadAsync()) //**can't open himage this way**
{
//Create a decoder for the image
var decoder = await BitmapDecoder.CreateAsync(stream);
//Create a transform to get a 1x1 image
var myTransform = new BitmapTransform { ScaledHeight = 1, ScaledWidth = 1 };
//Get the pixel provider
var pixels = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Rgba8,
BitmapAlphaMode.Ignore,
myTransform,
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
//Get the bytes of the 1x1 scaled image
var bytes = pixels.DetachPixelData();
//read the color
var myDominantColor = Color.FromArgb(255, bytes[0], bytes[1], bytes[2]);
}
Obviously I can't open the BitmapImage himage using OpenReadAsync, what do I need to do there to be able to achieve this?
BitmapDecoder requires RandomAccessStream object to create a new instance. BitmapImage may not be directly extract as RandomAccessStream unless you know the original source. According to your comment, you are binding image Uri to the image control, so you could know the original source and you can get the RandomAccessStream from the BitmapImage's UriSource property by RandomAccessStreamReference class, you don't need load the Image again. Code as follows:
var himage = (BitmapImage)image_home.Source;
RandomAccessStreamReference random = RandomAccessStreamReference.CreateFromUri(himage.UriSource);
using (IRandomAccessStream stream = await random.OpenReadAsync())
{
//Create a decoder for the image
var decoder = await BitmapDecoder.CreateAsync(stream);
...
//read the color
var myDominantColor = Color.FromArgb(255, bytes[0], bytes[1], bytes[2]);
}
I'm pretty new to displaying images in WPF forms, and i'm having trouble when it comes to converting and assigning an Image source for my GUI.
System.Drawing.Image testImg = ImageServer.DownloadCharacterImage(charID, ImageServer.ImageSize.Size128px);
byte[] barr = imgToByteArray(testImg);
CharImage.Source = ByteToImage(barr);
public byte[] imgToByteArray(System.Drawing.Image testImg)
{
using (MemoryStream ms = new MemoryStream())
{
testImg.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
}
public System.Drawing.Image ByteToImage(byte[] barr)
{
MemoryStream ms = new MemoryStream(barr);
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
return returnImage;
}
So i take in an image (JPEG) from the EVE Online C# API Library and then try to convert it to a byte array and back to a proper image. However i always get this error: "Cannot Implicitly convert type 'System.Drawing.Image' to 'System.Windows.Media.ImageSource'" I'm completely dumbfounded on how to solve this.
One possible solution is to save the image files (for example, .jpg) as WPF embedded resource and then use the following code snippet to get BitmapImage:
Listing 1. Get BitmapImage from EmbeddedResource
private string GetAssemblyName()
{
try { return Assembly.GetExecutingAssembly().FullName.Split(',')[0]; }
catch { throw; }
}
private BitmapImage GetEmbeddedBitmapImage(string pathImageFileEmbedded)
{
try
{
// compose full path to embedded resource file
string _fullPath = String.Concat(String.Concat(GetAssemblyName(), "."), pathImageFileEmbedded);
BitmapImage _bmpImage = new BitmapImage();
_bmpImage.BeginInit();
_bmpImage.StreamSource = Assembly.GetExecutingAssembly().GetManifestResourceStream(_fullPath);
_bmpImage.EndInit();
return _bmpImage;
}
catch { throw; }
finally { }
}
Correspondingly, set the Source property of the WPF Image control (for example, Image1) to that BitmapImage returned by function:
Image1.Source = GetEmbeddedBitmapImage(_strEmbeddedPath);
Note: you should reference the following:
using System.Windows.Media.Imaging;
using System.Reflection;
Another possible solution is to get the BitmapImage from image file using Uri object as shown in the following code snippet (Listing 2):
Listing 2. Get BitmapImage from File (use Uri)
private BitmapImage GetBitmapImageFromFile(string ImagePath)
{
Uri BitmapUri;
StreamResourceInfo BitmapStreamSourceInfo;
try
{
// Convert stream to Image.
BitmapImage bi = new BitmapImage();
BitmapUri = new Uri(ImagePath, UriKind.Relative);
BitmapStreamSourceInfo = Application.GetResourceStream(BitmapUri);
bi.BeginInit();
bi.StreamSource = BitmapStreamSourceInfo.Stream;
bi.EndInit();
return bi;
}
catch { throw; }
}
Hope this may help.
System.Drawing.Image is WinForms, not WPF. Your ByteToImage method should return BitmapSource instead.
The probably easiest way to create a BitmapSource from a byte array is BitmapFrame.Create:
public BitmapSource ByteArrayToImage(byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
{
return BitmapFrame.Create(stream,
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
You would assign the return value of the above method to the Source property of an Image control:
image.Source = ByteArrayToImage(barr);
I need to convert an image into a byte array to store it in a database. and also I need to convert that array back to the image. I did google research but I couldn't find a solution because in UWP platform some api doesn't available.
I found the solution from these articles as theoutlander says.
To convert a image into a byte[] i'm going to use the 'OpenSequentialReadAsyn()' method of a storage file.
lets assume that our image is 'file'. to convert it into a byte array do the below
using (var inputStream = await file.OpenSequentialReadAsync())
{
var readStream = inputStream.AsStreamForRead();
var byteArray = new byte[readStream.Length];
await readStream.ReadAsync(byteArray, 0, byteArray.Length);
return byteArray;
}
To convert the byte[] back into a image do the following,
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
{
writer.WriteBytes(this.byteArray);
await writer.StoreAsync();
}
var image = new BitmapImage();
await image.SetSourceAsync(stream);
return image;
}
you can find more in this article.
I cannot decode images back from their encoded form as a (Jpeg) byte array retrieved from my database to be used as image sources for my WPF application.
The code I am using to encode them as a Jpeg byte array is as follows:
public byte[] bytesFromBitmap(BitmapImage bit)
{
byte[] data;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bit));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
return data;
}
This is taking my Image taken directly from a webpage and assigned to an Image control like so:
var img = new BitmapImage(new Uri(entity.Image.ImageSrc)); //the entity has been saved in my DB, having been parsed from html
pbImage.Source = img;
This works just fine, I encode the BitmapImage and it saves just fine. But when I retrieve it from the DB and try to display it in another window, I cannot get it to work after trying every example I can see online - all either render nothing, or a black box or a visual mess not at all similar to the image I encoded.
Neither of the following have worked for me:
public BitmapSource GetBMImage(byte[] data)
{
using (var ms = new MemoryStream(data))
{
JpegBitmapDecoder decoder = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource frame = decoder.Frames[0];
return frame;
}
}
public static BitmapImage ImageFromBytes(byte[] imageData)
{
if (imageData == null)
{
return null;
}
else
{
var image = new BitmapImage();
using (var mem = new MemoryStream())
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
image.Freeze();
return image;
}
} //this throws a 'No imaging component suitable to complete this operation was found' exception
Among other uses of memory streams and decoders I just can't get this to work - can anyone help?