async Task HandleImage()
        {
            NSData bytes = null;

            var s = Element.Source;

            if (s is UriImageSource)
            {
                using (var client = new HttpClient())
                    bytes = NSData.FromArray(await client.GetByteArrayAsync(((UriImageSource)s).Uri));
            }
            else if (s is StreamImageSource)
            {
                bytes = NSData.FromStream(await((StreamImageSource)s).Stream(default(CancellationToken)));
            }
            else if (s is FileImageSource)
            {
                bytes = await Task.Run(() => { return(NSData.FromFile(((FileImageSource)s).File)); });
            }

            if (bytes == null)
            {
                return;
            }

            try
            {
                var sourceRef = CGImageSource.FromData(bytes);
                CreateAnimatedImageView(sourceRef, Control);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to load gif: " + ex.Message);
            }
        }
Example #2
0
 public static CGImage ToCG(this Image image)
 {
     using (var imageSource = CGImageSource.FromData(image.ToNS().AsTiff()))
     {
         return(imageSource.CreateImage(0, null));
     }
 }
Example #3
0
        public Bitmap(string filename, bool useIcm)
        {
            // TODO: Implement useIcm

            if (filename == null)
            {
                throw new ArgumentNullException("Value can not be null");
            }

            try
            {
                imageSource = CGImageSource.FromUrl(NSUrl.FromFilename(filename));
                if (imageSource == null)
                {
                    throw new FileNotFoundException("File {0} not found.", filename);
                }

                InitializeImageFrame(0);
#if DEBUG
                Tag = filename;
#endif
            }
            catch (Exception)
            {
                throw new FileNotFoundException("File {0} not found.", filename);
            }
        }
        protected override async void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == "Renderer")
            {
                if (loaded)
                {
                    return;
                }

                var uriImageSource = Element.Source as UriImageSource;
                if (uriImageSource == null || uriImageSource.Uri == null)
                {
                    return;
                }

                try
                {
                    loaded = true;
                    using (var client = new HttpClient())
                    {
                        var bytes = await client.GetByteArrayAsync(uriImageSource.Uri);

                        var sourceRef = CGImageSource.FromData(NSData.FromArray(bytes));
                        CreateAnimatedImageView(sourceRef, this.Control);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Unable to load gif: " + ex.Message);
                }
            }
        }
Example #5
0
        //http://chadkuehn.com/read-metadata-from-photos-in-c/
        private DateTime?ExtractDateTimeTaken(string path)
        {
            DateTime?     dt              = null;
            NSUrl         url             = new NSUrl(path: path, isDir: false);
            CGImageSource myImageSource   = CGImageSource.FromUrl(url, null);
            var           ns              = new NSDictionary();
            var           imageProperties = myImageSource.CopyProperties(ns, 0);

            var tiff = imageProperties.ObjectForKey(CGImageProperties.TIFFDictionary) as NSDictionary;
            var exif = imageProperties.ObjectForKey(CGImageProperties.ExifDictionary) as NSDictionary;

            //DateTaken
            var dtstr = (exif[CGImageProperties.ExifDateTimeOriginal]).ToString();

            if (string.IsNullOrEmpty(dtstr))
            {
                dtstr = (tiff[CGImageProperties.TIFFDateTime]).ToString();
            }
            if (!string.IsNullOrEmpty(dtstr))
            {
                dt = DateTime.ParseExact(dtstr, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture);
            }

            return(dt);
        }
        public Size GetImageSize(string imagePath)
        {
            try
            {
                NSUrl         url           = new NSUrl(path: imagePath, isDir: false);
                CGImageSource myImageSource = CGImageSource.FromUrl(url, null);
                var           ns            = new NSDictionary();

                //Dimensions
                NSObject width;
                NSObject height;

                using (NSDictionary imageProperties = myImageSource.CopyProperties(ns, 0))
                {
                    var tiff = imageProperties.ObjectForKey(CGImageProperties.TIFFDictionary) as NSDictionary;
                    width  = imageProperties[CGImageProperties.PixelWidth];
                    height = imageProperties[CGImageProperties.PixelHeight];
                }

                return(new Size(Convert.ToInt32(height.ToString()),
                                Convert.ToInt32(width.ToString())));
            }
            catch
            {
                return(Size.Empty);
            }
        }
        public void AvailableDepthDataTypesTest()
        {
#if !MONOMAC
            TestRuntime.AssertDevice();
#endif
            TestRuntime.AssertXcodeVersion(9, 0);

            // xamarinmonkey.heic is the new photo format, also this one includes depth data
            var imgdata = NSData.FromUrl(NSBundle.MainBundle.GetUrlForResource("xamarinmonkey", "heic", "CoreImage"));
            Assert.NotNull(imgdata, "imgdata");

            var imageSource = CGImageSource.FromData(imgdata);
            Assert.NotNull(imageSource, "imageSource");

            // fetching the image count works around a crash in CopyAuxiliaryDataInfo on macOS 10.15 (https://github.com/xamarin/maccore/issues/1802).
            Assert.AreNotEqual(0, imageSource.ImageCount, "ImageCount");

            var info = imageSource.CopyAuxiliaryDataInfo(0, CGImageAuxiliaryDataType.Disparity);
            Assert.NotNull(info, "info");

            NSError err;
            var     depthData = AVDepthData.Create(info, out err);
            Assert.NotNull(depthData, "depthData");
            Assert.NotNull(depthData.AvailableDepthDataTypes, "AvailableDepthDataTypes");
        }
Example #8
0
        private void GoForward(object sender, EventArgs e)
        {
            var croppedPhotos = new List <Tuple <NSDictionary, UIImage> >();

            var currentPhoto = source.ImageAssets.FirstOrDefault(a => a.Asset.LocalIdentifier == source.CurrentlySelectedItem.Item2.LocalIdentifier);

            if (currentPhoto != null)
            {
                currentPhoto.Offset            = _cropView.ContentOffset;
                currentPhoto.Scale             = _cropView.ZoomScale;
                currentPhoto.OriginalImageSize = _cropView.originalImageSize;
                currentPhoto.Orientation       = _cropView.orientation;
            }

            foreach (var item in source.ImageAssets)
            {
                NSDictionary metadata     = null;
                var          croppedPhoto = _cropView.CropImage(item);
                _m.RequestImageData(item.Asset, new PHImageRequestOptions()
                {
                    Synchronous = true
                }, (data, dataUti, orientation, info) =>
                {
                    var dataSource = CGImageSource.FromData(data);
                    metadata       = dataSource.GetProperties(0).Dictionary;
                });

                croppedPhotos.Add(new Tuple <NSDictionary, UIImage>(metadata, croppedPhoto));
            }

            var descriptionViewController = new DescriptionViewController(croppedPhotos, "jpg");

            NavigationController.PushViewController(descriptionViewController, true);
        }
Example #9
0
        private static List <int> GetDelays(CGImageSource source)
        {
            var retval = new List <int>();

            for (int i = 0; i < source?.ImageCount; i++)
            {
                var delayCentiseconds = 1;
                var properties        = source.GetProperties(i, null);
                using (var gifProperties = properties.Dictionary[CGImageProperties.GIFDictionary])
                {
                    if (gifProperties != null)
                    {
                        using (var unclampedDelay = gifProperties.ValueForKey(CGImageProperties.GIFUnclampedDelayTime))
                        {
                            double delayAsDouble = unclampedDelay != null?double.Parse(unclampedDelay.ToString(), CultureInfo.InvariantCulture) : 0;

                            if (delayAsDouble == 0)
                            {
                                using (var delay = gifProperties.ValueForKey(CGImageProperties.GIFDelayTime))
                                    delayAsDouble = delay != null?double.Parse(delay.ToString(), CultureInfo.InvariantCulture) : 0;
                            }

                            if (delayAsDouble > 0)
                            {
                                delayCentiseconds = (int)(delayAsDouble * 100);
                            }
                        }
                    }
                }

                retval.Add(delayCentiseconds);
            }

            return(retval);
        }
Example #10
0
        public void CopyProperties()
        {
            // what we had to answer with 5.2 for http://stackoverflow.com/q/10753108/220643
            IntPtr lib = Dlfcn.dlopen(Constants.ImageIOLibrary, 0);

            try {
                NSString kCGImageSourceShouldCache   = Dlfcn.GetStringConstant(lib, "kCGImageSourceShouldCache");
                NSString kCGImagePropertyPixelWidth  = Dlfcn.GetStringConstant(lib, "kCGImagePropertyPixelWidth");
                NSString kCGImagePropertyPixelHeight = Dlfcn.GetStringConstant(lib, "kCGImagePropertyPixelHeight");

#if MONOMAC
                using (var imageSource = CGImageSource.FromUrl(fileUrl)) {
#else
                using (var imageSource = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
#endif
                    using (var dict = new NSMutableDictionary()) {
                        dict [kCGImageSourceShouldCache] = NSNumber.FromBoolean(false);
                        using (var props = imageSource.CopyProperties(dict)) {
                            Assert.Null(props.ValueForKey(kCGImagePropertyPixelWidth), "kCGImagePropertyPixelWidth");
                            Assert.Null(props.ValueForKey(kCGImagePropertyPixelHeight), "kCGImagePropertyPixelHeight");
                            NSNumber n = (NSNumber)props ["FileSize"];
                            // image is "optimized" for devices (and a lot bigger at 10351 bytes ;-)
                            Assert.That((int)n, Is.AtLeast(7318), "FileSize");
                        }
                    }
                }
            }
            finally {
                Dlfcn.dlclose(lib);
            }
        }
Example #11
0
        public static UIImage AnimateGif(CGImageSource source, nfloat scale, CGImageThumbnailOptions options, TaskParameter parameters)
        {
            if (source == null)
            {
                return(null);
            }

            var frameCount = source.ImageCount;

            // no need to animate, fail safe.
            if (frameCount <= 1)
            {
                using (var imageRef = source.CreateThumbnail(0, options))
                {
                    return(new UIImage(imageRef, scale, UIImageOrientation.Up));
                }
            }

            var frames         = GetFrames(source, options);
            var delays         = GetDelays(source);
            var totalDuration  = delays.Sum();
            var adjustedFrames = AdjustFramesToSpoofDurations(frames, scale, delays, totalDuration);

            return(UIImage.CreateAnimatedImage(adjustedFrames.ToArray(), totalDuration / 100.0));
        }
Example #12
0
        public void FromUrlTest()
        {
#if MONOMAC
            using (var img = CGImageSource.FromUrl(fileUrl)) {
#else
            using (var img = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
#endif
                Assert.NotNull(img, "#a1");
            }

#if MONOMAC
            using (var img = CGImageSource.FromUrl(fileUrl, new CGImageOptions())) {
#else
            using (var img = CGImageSource.FromUrl(NSUrl.FromFilename(filename), new CGImageOptions())) {
#endif
                Assert.NotNull(img, "#b1");
            }

#if MONOMAC
            using (var img = CGImageSource.FromUrl(fileUrl, null)) {
#else
            using (var img = CGImageSource.FromUrl(NSUrl.FromFilename(filename), null)) {
#endif
                Assert.NotNull(img, "#c1");
            }
        }
        protected override async void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            NSData bytes = null;

            var s = Element.Source;

            if (s is UriImageSource)
            {
                using (var client = new HttpClient())
                    bytes = NSData.FromArray(await client.GetByteArrayAsync(((UriImageSource)s).Uri));
            }
            else if (s is StreamImageSource)
            {
                bytes = NSData.FromStream(await((StreamImageSource)s).Stream(default(CancellationToken)));
            }
            else if (s is FileImageSource)
            {
                bytes = await Task.Run(() => { return(NSData.FromFile(((FileImageSource)s).File)); });
            }

            if (bytes == null)
            {
                return;
            }

            try {
                var sourceRef = CGImageSource.FromData(bytes);
                CreateAnimatedImageView(sourceRef, Control);
            } catch (Exception ex) {
                Debug.WriteLine("Unable to load gif: " + ex.Message);
            }
        }
Example #14
0
        public void GetProperties()
        {
#if MONOMAC
            using (var imageSource = CGImageSource.FromUrl(fileUrl)) {
#else
            using (var imageSource = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
#endif
                CGImageOptions options = new CGImageOptions()
                {
                    ShouldCache = false
                };

                var props = imageSource.GetProperties(options);
                Assert.Null(props.PixelWidth, "PixelHeight-0");
                Assert.Null(props.PixelHeight, "PixelWidth-0");
                // image is "optimized" for devices (and a lot bigger at 10351 bytes ;-)
                Assert.That(props.FileSize, Is.AtLeast(7318), "FileSize");

                props = imageSource.GetProperties(0, options);
                Assert.AreEqual(57, props.PixelWidth, "PixelHeight");
                Assert.AreEqual(57, props.PixelHeight, "PixelWidth");
                Assert.AreEqual(CGImageColorModel.RGB, props.ColorModel, "ColorModel");
                Assert.AreEqual(8, props.Depth, "Depth");
            }
        }
Example #15
0
        /// <summary>
        /// Extract a DateTime object from a NSUrl object
        /// </summary>
        /// <param name="url">The url of the file</param>
        /// <returns>
        /// 1. The current date as a Nullable<DateTime> object IF url == null
        /// 2. The date (as a Nullable<DateTime> object) that exists within the file's metadata (pointed to by url) IFF the EXIF data exists
        /// 3. Null if the date cannot be found within the file's metadata
        /// </returns>
        private DateTime?GetDate(NSUrl url)
        {
            DateTime dateTaken;

            // If the provided url is null
            // NOTE: This case will happen if we import from camera
            if (url == null)
            {
                dateTaken = DateTime.Now;
                return(dateTaken);
            }

            CGImageSource source     = CGImageSource.FromUrl(url);
            NSDictionary  ns         = new NSDictionary();
            NSDictionary  properties = source.CopyProperties(ns, 0);

            NSDictionary exifDict = properties?.ObjectForKey(ImageIO.CGImageProperties.ExifDictionary) as NSDictionary;

            if (exifDict != null)
            {
                NSString date = exifDict[ImageIO.CGImageProperties.ExifDateTimeOriginal] as NSString;

                if (!string.IsNullOrEmpty(date) &&
                    DateTime.TryParseExact(date, "yyyy:MM:dd HH:mm:ss", CultureInfo.CurrentCulture, DateTimeStyles.None, out dateTaken))
                {
                    return(dateTaken);
                }
            }

            return(null);
        }
Example #16
0
        public void FromDataProviderTest()
        {
            var file = NSBundle.MainBundle.PathForResource("xamarin2", "png");

#if MONOMAC
            using (var dp = new CGDataProvider(file)) {
#else
            using (var dp = new CGDataProvider(filename)) {
#endif
                using (var img = CGImageSource.FromDataProvider(dp)) {
                    Assert.NotNull(img, "#a1");
                }
            }

#if MONOMAC
            using (var dp = new CGDataProvider(file)) {
#else
            using (var dp = new CGDataProvider(filename)) {
#endif
                using (var img = CGImageSource.FromDataProvider(dp, new CGImageOptions())) {
                    Assert.NotNull(img, "#b1");
                }
            }

#if MONOMAC
            using (var dp = new CGDataProvider(file)) {
#else
            using (var dp = new CGDataProvider(filename)) {
#endif
                using (var img = CGImageSource.FromDataProvider(dp, null)) {
                    Assert.NotNull(img, "#c1");
                }
            }
        }
Example #17
0
        static public FormsCAKeyFrameAnimation CreateAnimationFromCGImageSource(CGImageSource imageSource)
        {
            FormsCAKeyFrameAnimation animation = null;
            float repeatCount = float.MaxValue;
            var   imageCount  = imageSource.ImageCount;

            if (imageCount <= 0)
            {
                return(null);
            }

            using (var imageData = new ImageDataHelper(imageCount))
            {
                if (imageSource.TypeIdentifier == "com.compuserve.gif")
                {
                    var imageProperties = imageSource.GetProperties(null);
                    using (var gifImageProperties = imageProperties?.Dictionary[ImageIO.CGImageProperties.GIFDictionary])
                        using (var repeatCountValue = gifImageProperties?.ValueForKey(ImageIO.CGImageProperties.GIFLoopCount))
                        {
                            if (repeatCountValue != null)
                            {
                                float.TryParse(repeatCountValue.ToString(), out repeatCount);
                            }
                            else
                            {
                                repeatCount = 1;
                            }

                            if (repeatCount == 0)
                            {
                                repeatCount = float.MaxValue;
                            }
                        }
                }

                for (int i = 0; i < imageCount; i++)
                {
                    imageData.AddFrameData(i, imageSource);
                }

                animation = imageData.CreateKeyFrameAnimation();
                if (animation != null)
                {
                    animation.RemovedOnCompletion = false;
                    animation.KeyPath             = "contents";
                    animation.RepeatCount         = repeatCount;
                    animation.Width  = imageData.Width;
                    animation.Height = imageData.Height;

                    if (imageCount == 1)
                    {
                        animation.Duration = double.MaxValue;
                        animation.KeyTimes = null;
                    }
                }
            }

            return(animation);
        }
Example #18
0
        public void RemoveCache()
        {
            TestRuntime.AssertXcodeVersion(5, 0);

            using (var imageSource = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
                imageSource.RemoveCache(0);
            }
        }
Example #19
0
        public Bitmap(string filename)
        {
            // Use Image IO
            CGDataProvider prov = new CGDataProvider(filename);
            var            cg   = CGImageSource.FromDataProvider(prov).CreateImage(0, null);

            InitWithCGImage(cg);
        }
Example #20
0
        private static int GetLoopCount(CGImageSource source)
        {
            var var = source.GetProperties(null);

            using (var gifProperties = var.Dictionary["{GIF}"])
            {
                var loopCount = gifProperties.ValueForKey(new NSString("LoopCount"));
                return(int.Parse(loopCount.ToString()));
            }
        }
Example #21
0
        public Bitmap(Stream stream, bool useIcm)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("Value can not be null");
            }

            imageSource = CGImageSource.FromData(NSData.FromStream(stream));
            InitializeImageFrame(0);
        }
Example #22
0
        public static UIImage AnimateGif(NSData data)
        {
            if (data?.Length == 0)
            {
                return(null);
            }

            using (var source = CGImageSource.FromData(data))
                return(AnimateGifFromSource(source) ?? UIImage.LoadFromData(data));
        }
Example #23
0
        public void CreateIncrementalTest()
        {
            using (var img = CGImageSource.CreateIncremental(null)) {
                Assert.NotNull(img, "#a1");
            }

            using (var img = CGImageSource.CreateIncremental(new CGImageOptions())) {
                Assert.NotNull(img, "#b1");
            }
        }
Example #24
0
        private void InitFromStreamWithSize(Stream stream, int width, int height)
        {
            var data = NSData.FromStream(stream);

            this.imageData = new ReferencedImageData(data, CGImageSource.FromData(data));
            if (!LoadImageWithSize(new Size(width, height)))
            {
                throw new ArgumentOutOfRangeException("stream");
            }
        }
Example #25
0
        private NSData GetDataWriteMetadata(UIImage originalImage, NSDictionary imageMetadata, float compress)
        {
            //return originalImage.AsJPEG(compress); // turn off efix
            CGImageSource      imgSrc       = CGImageSource.FromData(originalImage.AsJPEG(compress));
            NSMutableData      outImageData = new NSMutableData();
            CGImageDestination dest         = CGImageDestination.Create(outImageData, MobileCoreServices.UTType.JPEG, 1, new CGImageDestinationOptions());

            dest.AddImage(imgSrc, 0, imageMetadata);
            dest.Close();
            return(outImageData);
        }
Example #26
0
        public void RemoveCache()
        {
            if (!TestRuntime.CheckSystemAndSDKVersion(7, 0))
            {
                Assert.Ignore("Only on iOS7+");
            }

            using (var imageSource = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
                imageSource.RemoveCache(0);
            }
        }
 public void CreateImageTest()
 {
     using (var imgsrc = CGImageSource.FromUrl(fileUrl)) {
         using (var img = imgsrc.CreateImage(0, null)) {
             Assert.NotNull(img, "#a1");
         }
         using (var img = imgsrc.CreateImage(0, new CGImageOptions())) {
             Assert.NotNull(img, "#b1");
         }
     }
 }
Example #28
0
 public void CreateThumbnailTest()
 {
     using (var imgsrc = CGImageSource.FromUrl(NSUrl.FromFilename(filename))) {
         using (var img = imgsrc.CreateThumbnail(0, null)) {
             Assert.NotNull(img, "#a1");
         }
         using (var img = imgsrc.CreateThumbnail(0, new CGImageThumbnailOptions())) {
             Assert.NotNull(img, "#b1");
         }
     }
 }
Example #29
0
        static CoreGraphics.CGImage[] GetFrames(CGImageSource source, CGImageThumbnailOptions options)
        {
            var retval = new CoreGraphics.CGImage[source.ImageCount];

            for (int i = 0; i < source.ImageCount; i++)
            {
                var frameImage = source.CreateThumbnail(i, options);
                retval[i] = frameImage;
            }

            return(retval);
        }
Example #30
0
        private static List <CoreGraphics.CGImage> GetFrames(CGImageSource source, CGImageThumbnailOptions options)
        {
            var retval = new List <CoreGraphics.CGImage>();

            for (int i = 0; i < source?.ImageCount; i++)
            {
                var frameImage = source.CreateThumbnail(i, options);
                retval.Add(frameImage);
            }

            return(retval);
        }
 public static Size? Measure (CGImageSource source)
 {
     lock (_gate) {
         if (source == null || source.Handle == IntPtr.Zero)
             return null;
         
         try {
             var props = source.CopyProperties ((NSDictionary) null, 0);
             if (props == null || !props.ContainsKey ((NSString) "PixelHeight") || !props.ContainsKey ((NSString) "PixelWidth"))
                 return null;
             
             var orientation = ReadOrientation (props);
             
             return ApplyOrientation (new Size (
                 ((NSNumber) props ["PixelWidth"]).IntValue,
                 ((NSNumber) props ["PixelHeight"]).IntValue
             ), orientation);
             
         } catch {
             return null;
         }
     }
 }
        static CGImage CreateThumbnail (CGImageSource source, int maxPixelSize, CancellationToken token)
        {
            token.ThrowIfCancellationRequested ();

            return source.CreateThumbnail (0, new CGImageThumbnailOptions {
                CreateThumbnailWithTransform = true,
                CreateThumbnailFromImageAlways = true,
                MaxPixelSize = maxPixelSize,
                ShouldCache = false
            });
        }
        private static UIImageView CreateAnimatedImageView(CGImageSource imageSource, UIImageView imageView = null)
        {
            var frameCount = imageSource.ImageCount;

            var frameImages = new List<NSObject>((int)frameCount);
            var frameCGImages = new List<CGImage>((int)frameCount);
            var frameDurations = new List<double>((int)frameCount);

            var totalFrameDuration = 0.0;

            for (int i = 0; i < frameCount; i++)
            {
                var frameImage = imageSource.CreateImage(i, null);

                frameCGImages.Add(frameImage);
                frameImages.Add(NSObject.FromObject(frameImage));

                var properties = imageSource.GetProperties(i, null);
                var duration = properties.Dictionary["{GIF}"];
                var delayTime = duration.ValueForKey(new NSString("DelayTime"));
                duration.Dispose ();
                var realDuration = double.Parse(delayTime.ToString());
                frameDurations.Add(realDuration);
                totalFrameDuration += realDuration;
                frameImage.Dispose ();
            }

            var framePercentageDurations = new List<NSNumber>((int)frameCount);
            var framePercentageDurationsDouble = new List<double>((int)frameCount);
            NSNumber currentDurationPercentage = 0.0f;
            double currentDurationDouble = 0.0f;
            for (int i = 0; i < frameCount; i++)
            {
                if (i != 0)
                {
                    var previousDuration = frameDurations[i - 1];
                    var previousDurationPercentage = framePercentageDurationsDouble[i - 1];

                    var number = previousDurationPercentage + (previousDuration/totalFrameDuration);
                    currentDurationDouble = number;
                    currentDurationPercentage = new NSNumber(number);
                }
                framePercentageDurationsDouble.Add(currentDurationDouble);
                framePercentageDurations.Add(currentDurationPercentage);
            }

            var imageSourceProperties = imageSource.GetProperties(null);
            var imageSourceGIFProperties = imageSourceProperties.Dictionary["{GIF}"];
            var loopCount = imageSourceGIFProperties.ValueForKey(new NSString("LoopCount"));
            var imageSourceLoopCount = float.Parse(loopCount.ToString());
            var frameAnimation = new CAKeyFrameAnimation();
            frameAnimation.KeyPath = "contents";
            if (imageSourceLoopCount <= 0.0f)
            {
                frameAnimation.RepeatCount = float.MaxValue;
            }
            else
            {
                frameAnimation.RepeatCount = imageSourceLoopCount;
            }

            imageSourceGIFProperties.Dispose ();


            frameAnimation.CalculationMode = CAAnimation.AnimationDescrete;
            frameAnimation.Values = frameImages.ToArray();
            frameAnimation.Duration = totalFrameDuration;
            frameAnimation.KeyTimes = framePercentageDurations.ToArray();
            frameAnimation.RemovedOnCompletion = false;
            var firstFrame = frameCGImages[0];
            if(imageView == null)
                imageView = new UIImageView(new CGRect(0.0f, 0.0f, firstFrame.Width, firstFrame.Height));
            else
                imageView.Layer.RemoveAllAnimations();

            imageView.Layer.AddAnimation(frameAnimation, "contents");

            frameAnimation.Dispose ();
            return imageView;
        }