| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 | 
using System;using System.Drawing;using System.IO;using System.Threading.Tasks;using AVFoundation;using CoreGraphics;using CoreMedia;using Foundation;using UIKit;using Xamarin.Essentials;using MobileCoreServices;[assembly: Xamarin.Forms.Dependency(typeof(InABox.Mobile.iOS.ImageToolsiOS))]namespace InABox.Mobile.iOS{        public class ImageToolsiOS : IImageTools    {        public byte[] CreateVideoThumbnail(byte[] video, int maxwidth, int maxheight)        {            byte[] result = null;            var filename = Path.Combine(                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),                $"{Guid.NewGuid().ToString()}.tmp"            );            File.WriteAllBytes(filename,video);            // perhaps? on IOS, try to use - NSUrl.FromFilename (path) instead of - new Foundation.NSUrl(url)            var asset = AVAsset.FromUrl(NSUrl.FromFilename(filename));            AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(asset);            //AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(AVAsset.FromUrl((new Foundation.NSUrl(filename))));            imageGenerator.AppliesPreferredTrackTransform = true;            CMTime actualTime;            NSError error;            CGImage cgImage = imageGenerator.CopyCGImageAtTime(new CMTime(1, 1), out actualTime, out error);            using (var ms = new MemoryStream())            {                var png = new UIImage(cgImage).AsPNG().AsStream();                png.CopyTo(ms);                result = ms.ToArray();            }            if (result != null)                result = ScaleImage(result, new Size(maxwidth, maxheight), 60);                        File.Delete(filename);            return result;        }                public byte[] CreateThumbnail(byte[] source, int maxwidth, int maxheight)        {            return ScaleImage(source, new Size(maxwidth, maxheight), 60);        }                public async Task<FileResult> PickPhotoAsync(int? compression, Size? constraints)        {            return await MainThread.InvokeOnMainThreadAsync(async () =>                await InternalGetPhotoAsync<Permissions.Photos>(UIImagePickerControllerSourceType.PhotoLibrary, compression, constraints));        }                 public async Task<FileResult> CapturePhotoAsync(int? compression, Size? constraints)        {            return await MainThread.InvokeOnMainThreadAsync(async () =>                await InternalGetPhotoAsync<Permissions.Camera>(UIImagePickerControllerSourceType.Camera, compression, constraints));        }        private async Task<FileResult> InternalGetPhotoAsync<TPermission>(UIImagePickerControllerSourceType source, int? compression, Size? constraints)            where TPermission : Permissions.BasePermission, new()        {            var taskCompletionSource = new TaskCompletionSource<FileResult>();            if (await Permissions.RequestAsync<TPermission>() == PermissionStatus.Granted)            {                var imagePicker = new UIImagePickerController                {                    SourceType = source,                    MediaTypes = new string[] { UTType.Image }                };                                var viewController = Platform.GetCurrentUIViewController();                imagePicker.AllowsEditing = false;                imagePicker.FinishedPickingMedia += async (sender, e) =>                {                    var jpegFilename = Path.Combine(FileSystem.CacheDirectory, $"{Guid.NewGuid()}.jpg");                    var source = e.Info[UIImagePickerController.OriginalImage] as UIImage;                    var rotated = AutoRotateImage(source);                    var scaled = ScaleImage(rotated, constraints);                    var result = scaled.AsJPEG(new nfloat(compression ?? 100)/100);                    await viewController.DismissViewControllerAsync(true);                    if (result.Save(jpegFilename, false, out var error))                    {                        taskCompletionSource.TrySetResult(new FileResult(jpegFilename));                    }                    else                    {                        taskCompletionSource.TrySetException(new Exception($"Error saving the image: {error}"));                    }                    imagePicker?.Dispose();                    imagePicker = null;                };                imagePicker.Canceled += async (sender, e) =>                {                    await viewController.DismissViewControllerAsync(true);                    taskCompletionSource.TrySetResult(null);                    imagePicker?.Dispose();                    imagePicker = null;                };                await viewController.PresentViewControllerAsync(imagePicker, true);            }            else            {                taskCompletionSource.TrySetResult(null);                taskCompletionSource.TrySetException(new PermissionException("Camera permission not granted"));            }            return await taskCompletionSource.Task;        }                private UIImage AutoRotateImage(UIImage source)        {            var rotation = source.Orientation switch            {                UIImageOrientation.Right => 90F,                UIImageOrientation.Up => 0F,                UIImageOrientation.Left => -90F,                UIImageOrientation.Down => 180F,                _ => 0F            };            return RotateImage(source, rotation);        }        private UIImage RotateImage(UIImage source, float rotation)        {            UIImage imageToReturn = null;            float radians = -1 * ((float)(rotation * Math.PI) / 180);            bool isLandscape = false;            var x = source.Size.Width / 2;            var y = source.Size.Height / 2;            //https://stackoverflow.com/a/8536553            CGAffineTransform transform = new CGAffineTransform((nfloat)Math.Cos(radians), (nfloat)Math.Sin(radians), -(nfloat)Math.Sin(radians), (nfloat)Math.Cos(radians), (nfloat)(x - x * Math.Cos(radians)) + (nfloat)(y * Math.Sin(radians)), (nfloat)(y - x * Math.Sin(radians) - y * Math.Cos(radians)));            var diff = (source.Size.Height - source.Size.Width) / 2;            bool translateWidthAndHeight = false;            if (rotation == 90)            {                translateWidthAndHeight = true;                transform.Translate(diff, -diff);            }            else if (rotation == 180)            {                //Transform.Translate(image.Size.Width, -image.Size.Height);            }            else if (rotation == 270)            {                translateWidthAndHeight = true;                transform.Translate(diff, -diff);            }            else if (rotation == 360)            {            }            if (translateWidthAndHeight)            {                //now draw image                using (var context = new CGBitmapContext(IntPtr.Zero,                                                        (int)source.Size.Height,                                                        (int)source.Size.Width,                                                        source.CGImage.BitsPerComponent,                                                        source.CGImage.BitsPerComponent * (int)source.Size.Width,                                                        source.CGImage.ColorSpace,                                                        source.CGImage.BitmapInfo))                {                    context.ConcatCTM(transform);                    context.DrawImage(new RectangleF(PointF.Empty, new SizeF((float)source.Size.Width, (float)source.Size.Height)), source.CGImage);                    using (var imageRef = context.ToImage())                    {                        imageToReturn = new UIImage(imageRef);                    }                }            }            else            {                //now draw image                using (var context = new CGBitmapContext(IntPtr.Zero,                                                        (int)source.Size.Width,                                                        (int)source.Size.Height,                                                        source.CGImage.BitsPerComponent,                                                        source.CGImage.BitsPerComponent * (int)source.Size.Height,                                                        source.CGImage.ColorSpace,                                                        source.CGImage.BitmapInfo))                {                    context.ConcatCTM(transform);                    context.DrawImage(new RectangleF(PointF.Empty, new SizeF((float)source.Size.Width, (float)source.Size.Height)), source.CGImage);                    using (var imageRef = context.ToImage())                    {                        imageToReturn = new UIImage(imageRef);                    }                }            }            return imageToReturn;        }        private UIImage ScaleImage(UIImage sourceImage, Size? constraints)        {            var maxwidth = constraints?.Width ?? sourceImage.Size.Width;            var maxheight = constraints?.Height ?? sourceImage.Size.Height;            var wRatio = maxwidth < sourceImage.Size.Width                ? maxwidth / (double)sourceImage.Size.Width                : 1.0F;            var hRatio = maxheight < sourceImage.Size.Height                ? maxheight / (double)sourceImage.Size.Height                : 1.0F;            var ratio = Math.Min(hRatio, wRatio);            if (ratio < 1.0F)            {                var width = ratio * sourceImage.Size.Width;                var height = ratio * sourceImage.Size.Height;                UIGraphics.BeginImageContext(new CGSize(width, height));                sourceImage.Draw(new CGRect(0, 0, width, height));                var resultImage = UIGraphics.GetImageFromCurrentImageContext();                UIGraphics.EndImageContext();                return resultImage;            }            return sourceImage;        }        public byte[] RotateImage(byte[] source, float angle, int quality = 100)        {            byte[] result = { };            using (UIImage src = UIImage.LoadFromData(NSData.FromArray(source)))            {                if (src != null)                {                    var scaled = RotateImage(src, angle);                    using (NSData imageData = scaled.AsJPEG(new nfloat((float)quality / 100F)))                    {                        result = new byte[imageData.Length];                        System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, result, 0,                            Convert.ToInt32(imageData.Length));                    }                }            }            return result;        }        public byte[] ScaleImage(byte[] source, Size? constraints, int quality = 100)        {            byte[] result = { };            using (UIImage src = UIImage.LoadFromData(NSData.FromArray(source)))            {                if (src != null)                {                    var scaled = ScaleImage(src, constraints);                    using (NSData imageData = scaled.AsJPEG(new nfloat((float)quality / 100F)))                    {                        result = new byte[imageData.Length];                        System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, result, 0,                            Convert.ToInt32(imageData.Length));                    }                }            }            return result;        }    }    }
 |