1

I need to save an image at Parse, so I need to convert it to byte[]. Any idea how can I achieve this? I've searched for it but none of the options worked for me. I'm using a shared Xamarin Forms project. Here's an example with text :

byte[] data = System.Text.Encoding.UTF8.GetBytes("Working at Parse is great!");
ParseFile file = new ParseFile("resume.txt", data);

I'm beginner and I really need help !

[EDIT] : For some reason, Xamarin will not let me use "System.Drawing.Image". I've searched a lot, and I found this but I can't make it work :

public static byte[] ReadFully(System.IO.Stream input)
{
    using (var ms = new MemoryStream())
    {
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

Thanks in advance .

MtDias
  • 21
  • 1
  • 3
  • 2
    Possible duplicate of [Fastest way to convert Image to Byte array](http://stackoverflow.com/questions/17352061/fastest-way-to-convert-image-to-byte-array) – CSharpie Oct 23 '15 at 16:57
  • 1
    Where is your image coming from? Is it a file on disk, or an asset/resource embedded directly in your project? – Jason Oct 23 '15 at 16:57
  • I'm trying to do something like this: the user chooses the profile photo on the login creation. This part of choosing the image I already have, I need "just" save it to Parse, but Xamarin won'r let me use the "System.Drawining.Image". Any ideia of how can I do this ? Thank you. – MtDias Oct 24 '15 at 04:01
  • "Chooses a photo" from where? A file on disk? The device image library? – Jason Oct 24 '15 at 14:30
  • From the device image library – MtDias Oct 26 '15 at 01:17

2 Answers2

0

If you choose images from photo gallery, you can use this codes. This codes also aim to pick up an image from photo library in iOS and save it to database as a byte array.

You said that you already have an image to display as the login form but someone who see this may not know how to get an image from your photo library in iOS so I write all of the code to archive the way to get an image and convert it to byte array.I use Prism library but any framework is ok.

If you want to only know how to convert an image to a byte array in Xamarin.forms you can go to the bottom of the codes below as MainPage class.

First, you make a new folder and name it Services. Under this folder you make an interface like this.

using System;
using System.Threading.Tasks;
using Xamarin.Forms;
using System.IO;
using Foundation;
namespace TestUIImage.Services
{
    public interface IPicturePicker
    {
        Task<NSUrl> GetNSUrlAsync();
    }
}

Then you write the content of GetNSUrlAsync method. You need two methods GetNSUrl and OnImagePickerCancelled so that user select an image or cancel to select.

using System;
using System.IO;
using UIKit;
using Xamarin.Forms;
using System.Threading.Tasks;
using Foundation;


namespace TestUIImage.Services
{
    public class PicturePickerImplementation : IPicturePicker
    {
        public PicturePickerImplementation()
        {
        }
        TaskCompletionSource<NSUrl> urltaskCompletionSource;
        UIImagePickerController imagePicker;
        public Task<NSUrl> GetNSUrlAsync()
        {
            // Create and define UIImagePickerController
            imagePicker = new UIImagePickerController
            {
                SourceType = UIImagePickerControllerSourceType.PhotoLibrary,
                MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)
            };

            // Set event handlers
            imagePicker.FinishedPickingMedia += GetNSUrl;
            imagePicker.Canceled += OnImagePickerCancelled;

            // Present UIImagePickerController
            UIWindow window = UIApplication.SharedApplication.KeyWindow;
            var viewController = window.RootViewController;
            viewController.PresentModalViewController(imagePicker, true);

            // Return Task object
            urltaskCompletionSource = new TaskCompletionSource<NSUrl>();
            return urltaskCompletionSource.Task;
        }

        void GetNSUrl(object sender, UIImagePickerMediaPickedEventArgs args)
        {
            urltaskCompletionSource.SetResult(args.ImageUrl);
            imagePicker.DismissModalViewController(true);
        }

        void OnImagePickerCancelled(object sender, EventArgs args)
        {
            taskCompletionSource.SetResult(null);
            imagePicker.DismissModalViewController(true);
        }
    }
}

Next, you register your services using DependencyService because selecting an image from your photo gallery in iOS depends on your platform.

using Prism;
using Prism.Ioc;
using TestUIImage.ViewModels;
using TestUIImage.Views;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Prism.Autofac;
using TestUIImage.Services;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace TestUIImage
{
    public partial class App : PrismApplication
    {

        public App() : this(null) { }

        public App(IPlatformInitializer initializer) : base(initializer) { }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            DependencyService.Register<PicturePickerImplementation>();
            await NavigationService.NavigateAsync("NavigationPage/MainPage");
        }

        protected override void RegisterTypes(IContainerRegistry    containerRegistry)
        {
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<MainPage>();
        }
    }
}

Then, you add this code in Info.plist because of the iOS security.

    ...
    <key>NSPhotoLibraryUsageDescription</key>
    <string>Picture Picker uses photo library</string>
</dict>
</plist>

Finally, you can call your services in codebehind. In this time, I used Image controller as TestImage and Button controller as PickPictureButton.

using System;
using System.IO;
using System.Drawing;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Foundation;
using Xamarin.Forms;
using TestUIImage.Services;

namespace TestUIImage.Views
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        async void Handle_Clicked(object sender, System.EventArgs e)
        {
            PickPictureButton.IsEnabled = false;
            NSUrl nSUrl = await DependencyService.Get<IPicturePicker>().GetNSUrlAsync();            
            TestImage.Source = ImageSource.FromStream(() =>
            {
                var ms = new MemoryStream();              
                var imagebytes = File.ReadAllBytes(nSUrl.Path);
                ms.Write(imagebytes, 0, imagebytes.Length);
                ms.Seek(0, SeekOrigin.Begin);
                return ms;
            });
            PickPictureButton.IsEnabled = true;
        }
    }
}
-1

Here's some code to convert a BitmapImage to a byte[]:

    public byte[] ConvertToBytes(BitmapImage bitmapImage)
    {
        if (bitmapImage != null)
        {
            MemoryStream memStream = new MemoryStream();
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
            encoder.Save(memStream);
            return memStream.GetBuffer();
        }
        return null;
    }

Here's some code to convert a byte[] to a BitmapImage:

    private void LoadImage()
    {
        var image = Services.GetImage(_employeeID);
        if (image.Image != null)
        {
            MemoryStream strmImg = new MemoryStream(image.Image);
            BitmapImage myBitmapImage = new BitmapImage();
            myBitmapImage.BeginInit();
            myBitmapImage.StreamSource = strmImg;
            myBitmapImage.DecodePixelWidth = 200;
            myBitmapImage.DecodePixelWidth = 250;
            myBitmapImage.EndInit();
            this.DemographicInformation.Image = myBitmapImage;
        }
    }

This has worked for me many times.

Roka
  • 444
  • 5
  • 23