I have a camera plugin in NativeScript 6.0 that returns a ByteArray under Android when taking a picture. How do I load this into an ImageSource? I cannot load it directly or the app will crash.
You can load a ByteArray using the ImageSource.fromData() method. However, under Android, ImageSource will only accept an input stream:
const input = new java.io.ByteArrayInputStream(myByteArray);
const imageSource = new ImageSource();
imageSource.fromData(input).then(() => {
stuff();
});
Related
Using FilePicker one can open an existing file:
FileResult file = await FilePicker.PickAsync();
TextView textview = FindViewById<TextView>(Resource.Id.textview);
string path = file.FullPath;
var handle = File.Open(path, FileMode.OpenOrCreate);
byte[] data = new byte[10];
handle.Read(data, 0, 10);
Is there a similar way for saving a new file?
For now, the FilePicker plugin is only designed to pick existing files.
On Android and iOS, you could not do that. But on UWP, you could use the FileSavePicker.
Xamarin: https://learn.microsoft.com/en-us/xamarin/essentials/file-picker?tabs=android
UWP: https://learn.microsoft.com/en-us/windows/uwp/files/quickstart-save-a-file-with-a-picker
is there a way to convert a UWP WriteableBitmap to a XamarinForms Image? Trying a simple convert ends up with "cannot implicitly convert type WriteableBitmap to Xamarin Forms Image".
Do I have to convert it before to a base64 string? Or how would you handle that?
thanks
You could find FromStream method in the Xamarin.Forms.ImageSource. For your requirement, you could get stream of WriteableBitmap form uwp project via DependencyService. And converter it to ImageSource in the PCL.
Example:
Interface
public interface IStreamToImage
{
Task GetStreamFormUWP(Action<Stream> StreamBlock);
}
implement
public async Task GetStreamFormUWP(Action<Stream> StreamBlock)
{
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => {
.......
using (Stream stream = MyBitmap.PixelBuffer.AsStream()){
await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
StreamBlock(stream);
}
});
}
Usage
await DependencyService.Get<IStreamToImage>().GetStreamFormUWP( (stream) =>
{
image.Source = ImageSource.FromStream(() => stream);
});
I am using VS 2017 to create a cross platform (UWP, Android, iOS) Xamarin app. I am trying to show all images from a folder on device as thumbnails (similar to gallery app, sample screenshot attached).
I have looked into WrapLayout sample code provided on Xamarin website (Link), but it's loading all images from internet using JSON
protected override async void OnAppearing()
{
base.OnAppearing();
var images = await GetImageListAsync();
foreach (var photo in images.Photos)
{
var image = new Image
{
Source = ImageSource.FromUri(new Uri(photo + string.Format("?width={0}&height={0}&mode=max", Device.OnPlatform(240, 240, 120))))
};
wrapLayout.Children.Add(image);
}
}
async Task<ImageList> GetImageListAsync()
{
var requestUri = "https://docs.xamarin.com/demo/stock.json";
using (var client = new HttpClient())
{
var result = await client.GetStringAsync(requestUri);
return JsonConvert.DeserializeObject<ImageList>(result);
}
}
I have also looked into Xamarin Media Plugin (Link), but it shows only one image at a time. Sample code -
await CrossMedia.Current.Initialize();
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
But I am unable to find a way to implement these two (or any other methods) in such a way that I can create my own gallery section in my app.
You need to create an Activity in your specific platform. This activity will be launched as an intent throught your PCL project using, for instance, Dependency Services.
In this custom Activity you should have a GridView which fills its source from the current directory if the file fits your restrictions, such a specific extension, size, etc.
Finally, to get the selected image you just send the image path or whatever you need to the PCL project with DependencyService.
I have a picture of item in external storage (that was saved by intent in my app). I want to display this picture in Image view in my shared project.
Image.Source takes object of ImageSource type. I tried ImageSource.FromFile, ImageSource.FromStream and even ImageSource.FromUri. The result is always that image is not displayed (no error or exception). I validated that the path to file is correct by first opening it with File.Open one line above.
What is the correct way of displaying pictures from normal storage, not from assets/resources/etc?
This code does not work:
var path = "/storage/emulated/0/Pictures/6afbd8c6-bb1e-49d3-838c-0fa809e97cf1.jpg" //in real app the path is taken from DB
var image = new Image() {Aspect = Aspect.AspectFit, WidthRequest = 200, HeightRequest = 200};
image.Source = ImageSource.FromFile(path);
Your Xamarin Forms PCL don't know what its a URI from Android beacuse its platform specific, so:
ImageSource.FromFile(path);
won't work.
In that case you are handling platform specific features, that is loading an image from Android.
I suggest this approach:
Create an interface on Xamarin Forms PCL like:
public interface IPhoto
{
Task<Stream> GetPhoto ();
}
Then in Android you implement that interface and register the implementation in DependencyService:
[assembly: Xamarin.Forms.Dependency(typeof(PhotoImplementation))]
namespace xpto
{
public class PhotoImplementation : Java.Lang.Object, IPhoto
{
public async Task<Stream> GetPhoto()
{
// Open the photo and put it in a Stream to return
var memoryStream = new MemoryStream();
using (var source = System.IO.File.OpenRead(path))
{
await source.CopyToAsync(memoryStream);
}
return memoryStream;
}
}
}
In the Xamarin Forms PCL code get the image:
var image = ImageSource.FromStream ( () => await DependencyService.Get<IPhoto>().GetPhoto());
For more detail you can consult this.
NOTE1: This will work on iOS if you implement the interface IPhoto too.
NOTE2: There exist a helpful library for this kind of features from Xamarin-Forms-Labs called Camera.
UPDATE (Shared Project solution)
As requested in the comments, to use this in a Shared Project instead of PCL we could do this.
1 - Place the IPhotoInterface in the Shared Project.
2 - Implement the interface in Android/iOS project:
public class PhotoImplementation : IPhoto
{
public async Task<Stream> GetPhoto()
{
// Open the photo and put it in a Stream to return.
}
}
3 - Use it in the Shared Project:
IPhoto iPhotoImplementation;
#if __ANDROID__
iPhotoImplementation = new shared_native.Droid.GetPicture();
#elif __IOS__
iPhotoImplementation = new shared_native.iOS.GetPicture();
#endif
var image = ImageSource.FromStream ( () => await iPhotoImplementation.GetPhoto());
NOTE: shared_native is the namespace of my solution and Droid/iOS are the projects for Android and iOS.
I have svg xml that i can convert to ImageSource or FileImageSource by using XamSVG library in the PCL project of my xamarin.forms.
I want to convert the ImageSource / FileImageSource to byte array (to get the bitmap).
Is this possible ?
ImageSource doesn't expose any mechanism to retrieve the original image source. Instead, you will need to manually keep a reference to the original source you use to create the image.
I've found the solution.
StreamImageSource streamImageSource = (StreamImageSource) some image source...
System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
Task<Stream> task = streamImageSource.Stream(cancellationToken);
Stream stream = task.Result;
Another solution:
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
Stream and MemoryStream are System.IO classes.
Then use it like this:
byte[] TargetImageByte = ReadFully(_data.Source);
_data.source is MediaFile type.