How to get an original image size?

rudyrykrudyryk RUMember ✭✭✭
edited February 2015 in Xamarin.Forms

Hi! I have the very basic case, but can't find elegant solution: need to know original image size for layout. But after loading an image to Image view I get -1 value for its width and height.

Here's a code sample, what I'm trying:

var icon = new Image {
    Source = ImageSource.FromFile("icon-edit.png")
};

// This will output -1 values for width and width request
Console.WriteLine("Width={0}, WidthRequest={1}", icon.Width, icon.WidthRequest);

// Adding to relative layout, won't work as expected! Icon's width is calculated as -1.
Children.Add(editIcon,
    Constraint.RelativeToParent((parent) => (parent.Width - icon.Width) / 2),
    Constraint.Constant(10)
);

In the example above icon should be centered horizontally and I could achieve that in some other way. But actually I'll need more sophisticated layout, that's why I need to know image width.

Best Answers

Answers

  • klemikazeklemikaze USMember ✭✭

    OMG nobody really knows answer to this question? I'm struggling with this for two days allready, have you found some solution?

  • The only solution to this that I've found was to use SizeChanged on the image. Once the function is called it should have correct width and height of the image as so:
    prodphoto.SizeChanged += ProductSizechange;
    public void ProductSizechange(object sender, EventArgs e)
    {
    ForceLayout();
    DisplayAlert("pls show", prodphoto.Width + " " + prodphoto.Height, "kk");
    }

  • rudyrykrudyryk RUMember ✭✭✭
    edited April 2015

    @AndriusSumtinlol This is something :) But without having robust way of manual calling SizeChanged event it could result strange behavior, when images "jump" to their correct positions after displaying :)

    I've temporarily ended up with providing utility class like that:

    using Xamarin.Forms;
    
    #if __IOS__
    using UIKit;
    #endif
    
    namespace Project
    {
        public static class ImageMeter
        {
            public static Size GetImageSize(string fileName)
            {
                #if __IOS__
                UIImage image = UIImage.FromFile(fileName);
                return new Size((double)image.Size.Width, (double)image.Size.Height);
                #endif
    
                return Size.Zero;
            }
        }
    }
    

    It is unlikely to be efficient, so I use it rarely as a last resort. And I haven't written a method for Android yet. @klemikaze Check it out!

  • andreacurtiandreacurti ITUniversity ✭✭

    i tried it, but it returns always zero as a value. :(
    Do you know why?

  • DylanLiuDylanLiu USUniversity ✭✭

    Seriously, I think there should be a built in readonly attribute Size in the Image class in Xamarin.forms

  • JGoldbergerJGoldberger USMember, Forum Administrator, Xamarin Team, University Xamurai

    @DylanLiu ,

    Although the FFImageLoading example provided by DanielL works great, I agree that something built-in would be nice. Please add a user voice request to our user voice page for this enhancement request:
    xamarin.uservoice.com

    The more people that vote for a feature on our user voice page, the more likely it would be implemented.

  • RobOllerRobOller USMember ✭✭

    I'm trying to use FFImageLoading to get the original image dimesions but the .Success event is not being triggered.

            private double determinRatio(string photoString)
            {
                double ratio;
                var cachedImage = new CachedImage();
    
                cachedImage.Success += (sender, e) =>
                {
                    double h = e.ImageInformation.OriginalHeight;
                    double w = e.ImageInformation.OriginalWidth;
    
                    ratio = w/h;
                };
    
                cachedImage.Source = (ImageSource)converter.Convert(photoString, null, null, null);
    
                return ratio;
            }
    
  • I have the same problem like RoberOller events on FFImageLoading is not triggering.

  • DanielLDanielL PLInsider ✭✭✭✭

    @RobertOller What platform?

  • RobOllerRobOller USMember ✭✭
    edited June 2017

    Xamarin.Forms utilizing PCL libraries for Android and iOS devices. We were attempting to determine the original photo's ratio (since device camera's can have different ratios) and use that to resize the image prior to uploading.

    We ended up abandoning this idea and using the plugin below that allows us to reduce quality and size of images based on percentages.

    https://github.com/jamesmontemagno/MediaPlugin

  • igorityigority Member ✭✭

    @DanielL said:
    @RobertOller What platform?

    I tried it as well, Success event never triggered either. Android platform, tested on multiple API versions.

  • DooksDooks ZAMember ✭✭✭
    edited January 8

    I have the following method which works for iOS:

    public static CGSize GetImageSizeFromPath(string FilePath)
    {
        // Make sure to add
        // using ImageIO;
    
        using (var src = CGImageSource.FromUrl(NSUrl.FromFilename(FilePath)))
        {
            var imgStatus = src.GetStatus(0);
            var options = new CGImageOptions() { ShouldCache = false };
    
            // MAKE SURE to provide an index or else the PixelWidth and PixelHeight will be NULL
            var properties = src.GetProperties(0, options);
    
            return new CGSize((int)properties.PixelWidth, (int)properties.PixelHeight);
        }
    }
    

    Using it:

    var imgSize = Methods.GetImageSizeFromPath(imgPath);
    

    For Android you can do something like:

    using (var opt = new BitmapFactory.Options() { InJustDecodeBounds = true })
    using (BitmapFactory.DecodeFile(FilePath, opt))
    {
        width = opt.OutWidth;
        height = opt.OutHeight;
    }
    
  • Eclipsed4utooEclipsed4utoo USMember ✭✭
    edited January 30

    @DanielL I know it's been a while, but I just ran across this thread and wanted to confirm what @igority @RobOller @LukaszDzwoniarski.5212 stated. Seems that the Success event does not fire. I'm trying to run this code in my XF app on iOS with the latest version of FFImageLoading 2.4.4.859.

    I tried using ImageSource.FromFile and ImageSource.FromStream, and neither worked.

    private async Task<double> GetImageRatio()
    {
        var ratio = 0d;
        var cachedImage = new CachedImage {
            WidthRequest = 500,
            HeightRequest = 500,
            DownsampleToViewSize = true
        };
    
        var task = new TaskCompletionSource<double>();
        cachedImage.Success += (sender, e) =>
        {
            var h = e.ImageInformation.OriginalHeight;
            var w = e.ImageInformation.OriginalWidth;
    
            var r = w / h;
            task.TrySetResult(r);
        };
    
        cachedImage.Error += (sender, e) => {
            task.TrySetException(e.Exception);
        };
    
        cachedImage.Source = ImageSource.FromFile(_selectedFile.Path);// ImageSource.FromStream(() => _selectedFile.GetStream());
    
        ratio = await task.Task;
    
        return ratio;
    }
    
  • NMackayNMackay GBInsider, University mod

    @Eclipsed4utoo said:
    @DanielL I know it's been a while, but I just ran across this thread and wanted to confirm what @igority @RobOller @LukaszDzwoniarski.5212 stated. Seems that the Success event does not fire. I'm trying to run this code in my XF app on iOS with the latest version of FFImageLoading 2.4.4.859.

    I tried using ImageSource.FromFile and ImageSource.FromStream, and neither worked.

    private async Task GetImageRatio()
    {
    var ratio = 0d;
    var cachedImage = new CachedImage {
    WidthRequest = 500,
    HeightRequest = 500,
    DownsampleToViewSize = true
    };

      var task = new TaskCompletionSource<double>();
      cachedImage.Success += (sender, e) =>
      {
          var h = e.ImageInformation.OriginalHeight;
          var w = e.ImageInformation.OriginalWidth;
    
          var r = w / h;
          task.TrySetResult(r);
      };
    
      cachedImage.Error += (sender, e) => {
          task.TrySetException(e.Exception);
      };
    
      cachedImage.Source = ImageSource.FromFile(_selectedFile.Path);// ImageSource.FromStream(() => _selectedFile.GetStream());
    
      ratio = await task.Task;
    
      return ratio;
    

    }

    Post the issue on the appropriate forum, it won't get picked up here

    https://github.com/luberda-molinet/FFImageLoading

Sign In or Register to comment.