How to convert image to base64string Xamarin Forms? - c#

I want to convert my image to base64string. I want to save the base64string to my database. I can get the path of my image. How can I get the image from my path and convert the image to base64string and what datatype do I need to put inorder to save base64string to my database is it BLOB?
try
{
var cafNo = entCafNo.Text;
var time = tpTime.Time;
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", "No Camera Available", "Ok");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(
new StoreCameraMediaOptions
{
SaveToAlbum = true,
Name = cafNo + "_IMG_01.jpg"
}
);
// provide read access to the file
FileStream fs = new FileStream(file.Path, FileMode.Open, FileAccess.Read);
// Create a byte array of file stream length
byte[] ImageData = new byte[fs.Length];
//Read block of bytes from stream into the byte array
fs.Read(ImageData, 0, System.Convert.ToInt32(fs.Length));
//Close the File Stream
fs.Close();
string _base64String = Convert.ToBase64String(ImageData);
entPhoto1Url.Text = _base64String;
}
catch(Exception ex)
{
await DisplayAlert("Error", ex.Message, "OK");
}

Related

Problem converting Image to Base64 in Blazor Server

So I am trying to convert an image base64 that will be uploaded to SQL Server.
Current code is:
private async Task OnInputFileChange(InputFileChangeEventArgs args)
{
var maxFiles = 1;
var maxSize = 512000000;
var format = "image/jpg";
test = "Something";
test1 = args.FileCount.ToString();
foreach (var file in args.GetMultipleFiles(maxFiles))
{
var image = await file.RequestImageFileAsync(format, 500, 500);
test = image.Size.ToString();
buffer = new byte[image.Size];
await image.OpenReadStream(maxAllowedSize: maxSize).ReadAsync(buffer);
test1 = buffer.ToString();
var imageDataUrl = $"data:{format};base64,{Convert.ToBase64String(buffer)}";
imageDataUrls.Add(imageDataUrl);
imageString = imageDataUrl;
}
}
It begins fine, however only the top portion of image is actually converted and in the string is followed by thousands of repeating "A". Reconstructing the image just shows the top portion of the image. What am I doing wrong?
Currently I had not uploaded and redownloaded the string, it is all local until I can figure out what is wrong. I am using the imageString for the image source. I am using .net 6.0.
Try this. Works for me. Files since 1 MB.
public static byte[] GetBytes(Stream stream)
{
var bytes = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
stream.ReadAsync(bytes, 0, bytes.Length);
stream.Dispose();
return bytes;
}
private async Task OnInputFileChange(InputFileChangeEventArgs args)
{
string base64String = "";
try
{
var files = args.GetMultipleFiles();
foreach (var file in files)
{
await using MemoryStream fs = new MemoryStream();
await file.OpenReadStream(maxAllowedSize: 1048576).CopyToAsync(fs);
byte[] somBytes = GetBytes(fs);
base64String = Convert.ToBase64String(somBytes, 0, somBytes.Length);
System.Diagnostics.Debug.Print("Imatge 64: " + base64String + Environment.NewLine);
}
}
catch (Exception e)
{
System.Diagnostics.Debug.Print("ERROR: " + e.Message + Environment.NewLine);
}
}

Saving a Xamarin image to file

Hi so I'm trying to save an image selected by the user to file so that i can later upload it to my mySQL database.
So I have this code:
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Please pick a selfie"
});
var stream = await result.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string filename = Path.Combine(path, "myfile");
using (var streamWriter = new StreamWriter(filename, true))
{
streamWriter.WriteLine(GetImageBytes(stream).ToString());
}
using (var streamReader = new StreamReader(filename))
{
string content = streamReader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(content);
}
Here's the GetImageBytes(..) function:
private byte[] GetImageBytes(Stream stream)
{
byte[] ImageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
ImageBytes = memoryStream.ToArray();
}
return ImageBytes;
}
The code kind of works, it creates a file but doesn't save the image. Instead it saves "System.Bytes[]". It saves the name of the object, not the contents of the object.
myfile
enter image description here
Any help would be really appreciated. Thanks!
StreamWriter is for writing formatted strings, not binary data. Try this instead
File.WriteAllBytes(filename,GetImageBytes(stream));
Encode the byte array as a base64 string, then store that in the file:
private string GetImageBytesAsBase64String(Stream stream)
{
var imageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
imageBytes = memoryStream.ToArray();
}
return Convert.ToBase64String(imageBytes);
}
If you later need to retrieve the image bytes from the file, you can use the corresponding Convert.FromBase64String(imageBytesAsBase64String) method.

Xamarin forms display an image issue

I use a photo picker to let the user choose a profile pic and then I want to display the pic inside of an Image view. the following code works fine for me but then I would like to convert the image to a byte array, once I call the method to convert it the image doesn't display after the user picks it. I also tried to call the method outside the try and catch but no luck.
the image is getting selected (it's getting saved in local storage) so the only issue is that for some reason it doesn't display it in the view.
async void showMediaPicker()
{
var res = await MediaPicker.PickPhotoAsync();
try
{
var stream = await res.OpenReadAsync();
var finalImage = ImageSource.FromStream(() => stream);
myImage.Source = finalImage;
imgBytes = ImageSourceToBytes(finalImage);
}
catch (Exception e)
{
Console.Write("error" + e.Message) ;
}
}
If you want to convert the photo to Byte array , you could use the plugin Media.Plugin from Nuget to pick or take photo . Don't forget to add the relevant permissions on android and iOS platform .
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
DisplayAlert("No Camera", ":( No camera available.", "OK");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
SaveToAlbum = true,
Name = "test.jpg"
});
if (file == null)
return;
Then convert it to Stream firstly before convert it to byte array .
Stream stream = file.GetStream();
public byte[] GetImageStreamAsBytes(Stream input)
{
var buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Now you can get the byte array like following
var imgDate = GetImageStreamAsBytes(stream);

Xamarin Forms saving image in sqlite database

How do I save an image I captured directly to sqlite(sqlite-net-pcl) database?
Here's my code but it can only save in "Internal Storage" of the phone.
private async void TakePhotoButton_Clicked(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", "No Camera Available", "OK");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(
new StoreCameraMediaOptions
{
SaveToAlbum = true,
//Directory = "Sample",
//Name = "Test.jpg"
});
if (file == null)
return;
PathLabel.Text = file.AlbumPath;
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
}
catch (Exception ex)
{
await DisplayAlert("error", ex.ToString(), "OK");
}
}
You should convert the stream to Byte array so that you save them to sqlite.
public byte[] GetImageStreamAsBytes(Stream input)
{
var buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
var imgDate = GetImageStreamAsBytes(file.GetStream());
Concerning the SaveToAlbum option
This will restult in 2 photos being saved for the photo. One in your private folder and one in a public directory that is shown. The value will be returned at AlbumPath. (Source)
Unless you really need the photo in the camera roll, there is no need to use SaveToAlbum.
Anyway, the file is still saved to your apps sandbox (the part of the devices storage that is reserved exclusively for your app) and you can retrieve the path with file.Path.
Having said that, it's easy to obtain the binary data representing your image
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", "No Camera Available", "OK");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions());
if (file == null)
return;
var imageData = File.ReadAllBytes(file.Path);
Obviously (see here and here) it's possibly to store binary data (BLOBs) in an SQLite database. The simplest conceivable model to store an image in the database would be something like
class Image
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public byte[] Data { get; set; }
}
Assuming that _imageRepository is your repository abstraction you are saving the images in, the data could be saved as
// ...
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions());
if (file == null)
return;
var imageData = File.ReadAllBytes(file.Path);
_imageRepository.Add(new Image()
{
Data = imageData
});
Later on, to display the image, you can get the Image from the repository and use the Data property, e.g. by passing it to a MemoryStream (if you need a stream)
// example: Loading by ID, loading all images is conceivable, too
var image = _imageRepository.LoadImage(id);
ImageControl.ImageSource = ImageSource.FromStream(() => new MemoryStream(image.Data));

Cannot read a Bitmap image that I just saved in Base64

I try to load a picture (PNG), save-it in Base64 in a text file and reload it, but I only see gliberish pictures (black and white, very ugly, far from original!) after I load the picture from the text file.
Where's my problem?
BTW all examples (load the picture from image file, save to base64, load from base64) are all taken from SO questions.
First it's how a load the pictures from the PNG file:
try
{
var openFileDialog = new OpenFileDialog
{
CheckFileExists = true,
Multiselect = false,
DefaultExt = "png",
InitialDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
};
if (openFileDialog.ShowDialog() == true)
{
Bitmap img;
using (var stream = File.Open(openFileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
img = new Bitmap(stream);
}
Logo.Source = BitmapToImageSource(img);
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
Save it to base64:
try
{
Bitmap img = BitmapSourceToBitmap2((BitmapSource) Logo.Source);
string base64String;
using (var stream = new MemoryStream())
{
img.Save(stream, ImageFormat.Png);
byte[] imageBytes = stream.ToArray();
base64String = Convert.ToBase64String(imageBytes);
}
string fileName = string.Format(CultureInfo.InvariantCulture, "image{0:yyyyMMddHHmmss}.txt",
DateTime.Now);
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8))
{
writer.Write(base64String);
writer.Flush();
}
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
BitmapSourceToBitmap2:
int width = srs.PixelWidth;
int height = srs.PixelHeight;
int stride = width*((srs.Format.BitsPerPixel + 7)/8);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(height*stride);
srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height*stride, stride);
using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))
{
// Clone the bitmap so that we can dispose it and
// release the unmanaged memory at ptr
return new Bitmap(btm);
}
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
And load it back from the file:
try
{
var openFileDialog = new OpenFileDialog
{
CheckFileExists = true,
Multiselect = false,
DefaultExt = "txt",
InitialDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (openFileDialog.ShowDialog() == true)
{
string base64String;
using (FileStream stream = File.Open(openFileDialog.FileName, FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
base64String = reader.ReadToEnd();
}
}
byte[] binaryData = Convert.FromBase64String(base64String);
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new MemoryStream(binaryData);
bi.EndInit();
Logo.Source = bi;
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
Here is a short code sequence that reads a JPG file into a byte array, creates a BitmapSource from it, then encodes it into a base64 string and writes that to file.
In a second step, the base64 string is read back from the file, decoded and a second BitmapSource is created.
The sample assumes that there is some XAML with two Image elements named image1 and image2.
Step 1:
var imageFile = #"C:\Users\Clemens\Pictures\DSC06449.JPG";
var buffer = File.ReadAllBytes(imageFile);
using (var stream = new MemoryStream(buffer))
{
image1.Source = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
var base64File = #"C:\Users\Clemens\Pictures\DSC06449.b64";
var base64String = System.Convert.ToBase64String(buffer);
File.WriteAllText(base64File, base64String);
Step 2:
base64String = File.ReadAllText(base64File);
buffer = System.Convert.FromBase64String(base64String);
using (var stream = new MemoryStream(buffer))
{
image2.Source = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
In case you need to encode an already existing BitmapSource into a byte array, use code like this:
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
buffer = stream.ToArray();
}

Categories