Getting bytes [] / image stream or ImageSource in Xamarin.Forms?

I searched in Xamarin.Forms.Labs to learn more about how images are accessed and manipulated. Saving an image in the Android / iOS photo gallery works great, as does retrieving an image from any, at least through user interaction.

The problem is that I would like to save some files inside the program. In fact, saving the file itself does not present a problem - I wrote a solution for the / DependencyService interface for this.

What I cannot do is access bytes [] or the stream of the image data itself using an Xamarin.Forms or ImageSource image. Reading a stream in ImageSource is relatively simple with a static method, so how can I get these bytes to save the file in the program itself?

To create this: I am currently working on an application where a user takes / selects photos to include in a form and the form is eventually published on the website. Thus, the ability to really save images or access the data itself for transferring them is pretty good.

+7
android c # ios xamarin
source share
1 answer

One really hacky way to do this is to write your own renderer for your image. Then the rendering will get byte[]/Stream from the inline control. Here's a very crude implementation without error handling to help you get started:

 public class MyImage : Image { public Func<byte[]> GetBytes { get; set; } } 

Here's the iOS renderer:

 public class MyImageRenderer : ImageRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Image> e) { base.OnElementChanged(e); var newImage = e.NewElement as MyImage; if (newImage != null) { newImage.GetBytes = () => { return this.Control.Image.AsPNG().ToArray(); }; } var oldImage = e.OldElement as MyImage; if (oldImage != null) { oldImage.GetBytes = null; } } } 

Android one of them is somewhat larger:

 public class MyImageRenderer : ImageRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Image> e) { base.OnElementChanged(e); var newImage = e.NewElement as MyImage; if (newImage != null) { newImage.GetBytes = () => { var drawable = this.Control.Drawable; var bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888); drawable.Draw(new Canvas(bitmap)); using (var ms = new MemoryStream()) { bitmap.Compress(Bitmap.CompressFormat.Png, 100, ms); return ms.ToArray(); } }; } var oldImage = e.OldElement as MyImage; if (oldImage != null) { oldImage.GetBytes = null; } } } 

And finally, the use is obvious:

 var bytes = myImage.GetBytes?.Invoke(); 

Extending the idea of ​​threading support should be fairly simple. The obvious hurdle is that form management ( MyImage ) maintains a link to its renderer via GetBytes() , but this seems inevitable.

+1
source share

All Articles