Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Forms: How to load an image from Resources into a byte-array?

I have a (hopefully) simple question (I don’t have found an answer, that fit’s by all of my searches).

I work with Xamarin.Forms 1.4.1-Pre-1. In my app, I have:

byte[] AvatarErfassung; // Bytearray, to later update the webservice
var Avatar = new Image { HeightRequest = 71, WidthRequest = 61, HorizontalOptions = LayoutOptions.Start };
Avatar.Source = "SymbolMann.jpg";  

where the image "SymbolMann.jpg” is included as project-resource (in each project) and showed on a page (without problems).
I now want to put the image in a byte-array to send it to our webservice. I don't have found any way to access the image "SymbolMann.jpg" (to load it in a byte-array) or to use (however) the Avatar.Source therefore.

Question:
How to get the image “SymbolMann.jpg” into the byte-array “AvatarErfassung” ?

Thanks for every answer

Hi Dimitris

Thanks for your (fast) replay.
As I wrote, I work with Xamarin.Forms.
The images are stored as resources: in \Resources\Drawable\ (for Android), \Resources\ (for iOS) and in the root (for WP). I have to load the image on a content-page.

If I overtake your code, to the line:

var assembly = this.GetType().GetTypeInfo().Assembly;

I have the error-message (translated to English):
“System.Type don’t contain a definition for GetTypeInfo method (is a using missing?)”

Do I have to add a specific using?

You write: // you can replace "this.GetType()" with "typeof(MyType)", where MyType is any type in your assembly.

What do I have to place as type?

= typeof(????).GetTypeInfo().Assembly:

Thanks for a further reply.

Update #2:

Firts, thanks for your patience…

Unfortunately in VS2013, I don’t find any function “resolve” that shows me the missing using - but I have find out the missing using my self :-)
In the meantime I have added using System.Reflection;

Now, the line: var assembly = this.GetType().GetTypeInfo().Assembly;

is resolved and compiled without error

Further, I have changed the type of the .jpg from “Android Resource” to “Embedded Ressource”.
The App then crashes in the line: long length = s.Length; as it seems that s is null (I think the jpg is not found)

Further - if I change the type to “Embedded Ressource” - the image is not found any more by Xamarin.Forms (Avatar.Source = "SymbolMann.jpg";)

If I change the type of the .jpg to “Compile” I can’t compile the app.
Error-message: A namespace can’t contain directly members like fields or methods.

So… what is the correct type to the resource (so that it can be loaded with assembly.GetManifestResourceStream()?

Do I have to add something to the filename (SymbolMann.jpg) so that it will be found?

How do I have to change Avatar.Source = "SymbolMann.jpg" so that it is found (if I change the type from “Android Resource” to anything else)?

Once again my needs:
On a registration-page, default-images (symbols) are showed as avatar for man and woman in a standard-Xamarin.Forms image (avatar.source = “SymbolMann.jpg” / “SymbolFrau.jpg”).
The .jpg’s are stored in the standard-directories for each project (Android, iOS and WP) where the are accessible without problems from the image-object.
The user then can take one of the default-images or load another one over mediapicker.
If the user the tap the button “Register”, I have to create a byte-array from the Image to send it via json to our webservice.
If the user select another image via mediapicker, I have access to the stream, the problem is, to become a byte-array from the default-images (in every platform).

Once again thanks for your help...

like image 974
FredyWenger Avatar asked Mar 23 '15 18:03

FredyWenger


2 Answers

I used noelicus given idea and printed all the names from ManifestResourceNames array and I found there my image name as ProjectName.Droid.image_name.jpeg .Then I just changed the method call from assembly.GetManifestResourceStream("image_name.jpg") to assembly.GetManifestResourceStream("ProjectName.Droid.image_name.jpeg").And it worked. So the correct answer would be :

  1. Store the image in root folder at PCL.
  2. Make it's build action in properties as Embedded resource.
  3. Then print <b><i>var names = assembly.GetManifestResourceNames()</i></b> array which will be a string array and can be printed using

    foreach(var data in names){Debug.WriteLine(data);}
    
  4. There you will see the resource name for image and then use the method

    Stream s = assembly.GetManifestResourceStream("resource_name_you_found.format")
    
like image 115
heathorjoker Avatar answered Oct 17 '22 08:10

heathorjoker


Thanks @FredWenger and @Dimitris - here's my solution based on both your answers:

  1. Add your image to the Xamarin Forms (Portable) project wherever you like. I just went for the root: MyProject\DaffyDuck.jpg
  2. Mark the image as an Embedded Resource (file properties -> build action)
  3. Call the function referencing the Embedded Resource like this: ImageDataFromResource("MyProject.DaffyDuck.jpg")
    Notice that you need to include the project name to get the assembly name *.
  4. This is the function:

    public byte[] ImageDataFromResource(string r)
    {
        // Ensure "this" is an object that is part of your implementation within your Xamarin forms project
        var assembly = this.GetType().GetTypeInfo().Assembly; 
        byte[] buffer = null;
    
        using (System.IO.Stream s = assembly.GetManifestResourceStream(r))
        {
            if (s != null)
            {
                long length = s.Length;
                buffer = new byte[length];
                s.Read(buffer, 0, (int)length);
            }
        }
    
        return buffer;
    }
    
  5. If you need to reference the loaded data in an ImageView control do it thus:
    ImageView.Source = ImageSource.FromStream(() => new MemoryStream(imageData));

*NB: If step 3 doesn't work and you want to check your embedded resource names call this: var names = assembly.GetManifestResourceNames(); and see what is listed in your project.

like image 33
noelicus Avatar answered Oct 17 '22 10:10

noelicus