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;
- }
- }
-
- }
|