Reputation: 72
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");
}
}
Upvotes: 0
Views: 1513
Reputation: 9713
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));
Upvotes: 1
Reputation: 18861
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());
Upvotes: 2