コード例 #1
0
        private void Handle_PickedImages(object sender, MultiAssetEventArgs e)
        {
            ImageEntries = new List <ImageEntry>();
            var phAssetArray = e.Assets;
            var manager      = PHImageManager.DefaultManager;

            using (var options = new PHImageRequestOptions
            {
                Synchronous = true,
                DeliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat,
                ResizeMode = PHImageRequestOptionsResizeMode.Exact
            })
            {
                foreach (var asset in phAssetArray)
                {
                    if (asset.MediaType == PHAssetMediaType.Video)
                    {
                        HandleVideoSelected();
                        return;
                    }
                    manager.RequestImageForAsset(asset, new CGSize(asset.PixelWidth, asset.PixelHeight),
                                                 PHImageContentMode.Default, options, (result, info) =>
                    {
                        var resources = PHAssetResource.GetAssetResources(asset);
                        var name      = resources != null && resources.Length > 0
                                ? resources[0].OriginalFilename
                                : string.Empty;
                        ImageEntries.Add(new ImageEntry(result.ToSKImage(), name, (DateTime)asset.CreationDate,
                                                        null));
                    });
                }

                LaunchAnalysisScreen(ImageEntries);
            }
        }
コード例 #2
0
        private static void StoreImageData(PHAsset asset, int quality, float scale, bool rotate, MediaFile tempMedia,
                                           NSDictionary info, NSData data, TaskCompletionSource <string> tcs)
        {
            var targetDir = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

            try
            {
                var error = (NSError)info["PHImageErrorKey"];
                if (error != null)
                {
                    var description = error.LocalizedDescription;
                    var reason      = error.UserInfo.ValueForKey((NSString)"NSUnderlyingError");
                    throw new Exception($"{description}. {reason}");
                }

                var resources   = PHAssetResource.GetAssetResources(asset);
                var orgFilename = resources[0].OriginalFilename;
                orgFilename = orgFilename.EndsWith(".JPG", StringComparison.OrdinalIgnoreCase)
                                ? orgFilename
                                : $"{orgFilename}.JPG";
                var path        = Path.Combine(targetDir, orgFilename);
                var fullimage   = CIImage.FromData(data);
                var image       = UIImage.LoadFromData(data);
                var scaledImage = image.ScaleImage(scale);
                if (rotate)
                {
                    scaledImage = scaledImage.RotateImage();
                }

                SaveTempImage(fullimage, scaledImage, path, quality, rotate);
                var dateString = fullimage.Properties.Exif?.Dictionary?.ValueForKey(ImageIO.CGImageProperties.ExifDateTimeOriginal)?.ToString();
                if (dateString != null)
                {
                    tempMedia.MediaTakenAt = DateTime.ParseExact(dateString, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture);
                }
                else
                {
                    tempMedia.MediaTakenAt = null;
                }

                int.TryParse(fullimage.Properties?.Orientation.ToString(), out tempMedia.Orientation);
                tempMedia.Latitude     = fullimage.Properties?.Gps?.Latitude;
                tempMedia.LatitudeRef  = fullimage.Properties?.Gps?.Dictionary.ValueForKey(ImageIO.CGImageProperties.GPSLatitudeRef).ToString() ?? string.Empty;
                tempMedia.Longitude    = fullimage.Properties?.Gps?.Longitude;
                tempMedia.LongitudeRef = fullimage.Properties?.Gps?.Dictionary.ValueForKey(ImageIO.CGImageProperties.GPSLongitudeRef).ToString() ?? string.Empty;
                tcs.TrySetResult(path);
            }
            catch (Exception ex)
            {
                tcs.TrySetException(ex);
            }
        }
コード例 #3
0
        public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
        {
            var cell = (GMGridViewCell)CollectionView.DequeueReusableCell(GMGridViewCellIdentifier, indexPath);

            var asset = (PHAsset)AssetsFetchResults[indexPath.Item];

            if (cell != null)
            {
                // Increment the cell's tag
                var currentTag = cell.Tag + 1;
                cell.Tag = currentTag;

                _imageManager.RequestImageForAsset(asset,
                                                   AssetGridThumbnailSize,
                                                   PHImageContentMode.AspectFill,
                                                   new PHImageRequestOptions {
                    DeliveryMode = PHImageRequestOptionsDeliveryMode.Opportunistic, ResizeMode = PHImageRequestOptionsResizeMode.Fast
                },
                                                   (image, info) => {
                    // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used.
                    if (cell.Tag == currentTag && cell.ImageView != null && image != null)
                    {
                        cell.ImageView.Image = image;
                    }
                });
            }

            cell.Bind(asset);
            cell.ShouldShowSelection = _picker.AllowsMultipleSelection;

            // Optional protocol to determine if some kind of assets can't be selected (long videos, etc...)
            cell.IsEnabled = _picker.VerifyShouldEnableAsset(asset);

            if (_picker.SelectedAssets.Contains(asset))
            {
                cell.Selected = true;
                CollectionView.SelectItem(indexPath, false, UICollectionViewScrollPosition.None);
            }
            else
            {
                cell.Selected = false;
            }

            var resources = PHAssetResource.GetAssetResources(asset);
            var name      = resources != null && resources.Length > 0
                ? resources[0].OriginalFilename
                : string.Empty;

            ConfigureSelectCellAccessibilityAttributes(cell, cell.Selected, name);
            return(cell);
        }
コード例 #4
0
        private static string StorePickedVideo(PHAsset asset)
        {
            var tcs          = new TaskCompletionSource <string>();
            var task         = tcs.Task;
            var imageManager = PHImageManager.DefaultManager;

            using (var requestOptions = new PHVideoRequestOptions
            {
                NetworkAccessAllowed = true,
                DeliveryMode = PHVideoRequestOptionsDeliveryMode.MediumQualityFormat
            })
            {
                imageManager.RequestExportSession(asset, requestOptions, AVAssetExportSession.PresetPassthrough, (exportSession, info) =>
                {
                    Task.Factory.StartNew(async() =>
                    {
                        var targetDir = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                        var error     = (NSError)info["PHImageErrorKey"];
                        if (error != null)
                        {
                            var description = error.LocalizedDescription;
                            var reason      = error.UserInfo.ValueForKey((NSString)"NSUnderlyingError");
                            tcs.SetException(new FileLoadException($"{description}. {reason}"));
                            return;
                        }

                        var resources   = PHAssetResource.GetAssetResources(asset);
                        var orgFilename = resources[0].OriginalFilename;
                        var path        = Path.Combine(targetDir, orgFilename);
                        File.Delete(path);
                        exportSession.OutputUrl      = new NSUrl($"file://{path}");
                        exportSession.OutputFileType = AVFileType.Mpeg4;
                        await exportSession.ExportTaskAsync();
                        if (exportSession.Status == AVAssetExportSessionStatus.Completed)
                        {
                            tcs.TrySetResult(path);
                        }
                        else
                        {
                            tcs.SetException(new Exception(exportSession.Error.Description));
                        }
                    });
                });
            }

            return(task.Result);
        }
コード例 #5
0
        private void RefreshResources()
        {
            var resources = PHAssetResource.GetAssetResources(Asset);
            var list      = new List <PHAssetResource>(resources.Length);

            foreach (var resource in resources)
            {
                if (resource.ResourceType == PHAssetResourceType.Photo ||
                    resource.ResourceType == PHAssetResourceType.Video ||
                    resource.ResourceType == PHAssetResourceType.Audio)
                {
                    FileName = resource.OriginalFilename;
                }

                list.Add(resource);
            }

            Resources = list.AsReadOnly();
        }
コード例 #6
0
        private void RefreshResources()
        {
            var resources = PHAssetResource.GetAssetResources(Asset);
            var list      = new List <PHAssetResource>(resources.Length);

            foreach (var resource in resources)
            {
                if (resource.ResourceType == PHAssetResourceType.Photo ||
                    resource.ResourceType == PHAssetResourceType.Video ||
                    resource.ResourceType == PHAssetResourceType.Audio)
                {
                    var dtstr = CreationDate.ToLocalTime().ToString("yyyy-MM-dd HH_mm");
                    FileName = $"{dtstr} {resource.OriginalFilename}";
                }

                list.Add(resource);
            }

            Resources = list.AsReadOnly();
        }
コード例 #7
0
        static FileResult DictionaryToMediaFile(NSDictionary info)
        {
            if (info == null)
            {
                return(null);
            }

            PHAsset phAsset  = null;
            NSUrl   assetUrl = null;

            if (Platform.HasOSVersion(11, 0))
            {
                assetUrl = info[UIImagePickerController.ImageUrl] as NSUrl;

                // Try the MediaURL sometimes used for videos
                if (assetUrl == null)
                {
                    assetUrl = info[UIImagePickerController.MediaURL] as NSUrl;
                }

                if (assetUrl != null)
                {
                    if (!assetUrl.Scheme.Equals("assets-library", StringComparison.InvariantCultureIgnoreCase))
                    {
                        return(new UIDocumentFileResult(assetUrl));
                    }

                    phAsset = info.ValueForKey(UIImagePickerController.PHAsset) as PHAsset;
                }
            }

            if (phAsset == null)
            {
                assetUrl = info[UIImagePickerController.ReferenceUrl] as NSUrl;

                if (assetUrl != null)
                {
                    phAsset = PHAsset.FetchAssets(new NSUrl[] { assetUrl }, null)?.LastObject as PHAsset;
                }
            }

            if (phAsset == null || assetUrl == null)
            {
                var img    = info.ValueForKey(UIImagePickerController.OriginalImage) as UIImage;
                var imgUrl = info.ValueForKey(UIImagePickerController.ImageUrl) as NSString;

                if (img != null)
                {
                    var rotatedImg = CorrectImageRotation(img);

                    return(new UIImageFileResult(rotatedImg ?? img));
                }
            }

            if (phAsset == null || assetUrl == null)
            {
                return(null);
            }

            string originalFilename;

            if (Platform.HasOSVersion(9, 0))
            {
                originalFilename = PHAssetResource.GetAssetResources(phAsset).FirstOrDefault()?.OriginalFilename;
            }
            else
            {
                originalFilename = phAsset.ValueForKey(new NSString("filename")) as NSString;
            }

            return(new PHAssetFileResult(assetUrl, phAsset, originalFilename));
        }
コード例 #8
0
        static FileResult DictionaryToMediaFile(NSDictionary info)
        {
            if (info == null)
            {
                return(null);
            }

            PHAsset phAsset  = null;
            NSUrl   assetUrl = null;

            if (OperatingSystem.IsIOSVersionAtLeast(11, 0))
            {
                assetUrl = info[UIImagePickerController.ImageUrl] as NSUrl;

                // Try the MediaURL sometimes used for videos
                if (assetUrl == null)
                {
                    assetUrl = info[UIImagePickerController.MediaURL] as NSUrl;
                }

                if (assetUrl != null)
                {
                    if (!assetUrl.Scheme.Equals("assets-library", StringComparison.OrdinalIgnoreCase))
                    {
                        return(new UIDocumentFileResult(assetUrl));
                    }

                    phAsset = info.ValueForKey(UIImagePickerController.PHAsset) as PHAsset;
                }
            }

#if !MACCATALYST
            if (phAsset == null)
            {
                assetUrl = info[UIImagePickerController.ReferenceUrl] as NSUrl;

                if (assetUrl != null)
                {
                    phAsset = PHAsset.FetchAssets(new NSUrl[] { assetUrl }, null)?.LastObject as PHAsset;
                }
            }
#endif

            if (phAsset == null || assetUrl == null)
            {
                var img = info.ValueForKey(UIImagePickerController.OriginalImage) as UIImage;

                if (img != null)
                {
                    return(new UIImageFileResult(img));
                }
            }

            if (phAsset == null || assetUrl == null)
            {
                return(null);
            }

            string originalFilename = PHAssetResource.GetAssetResources(phAsset).FirstOrDefault()?.OriginalFilename;
            return(new PHAssetFileResult(assetUrl, phAsset, originalFilename));
        }
コード例 #9
0
        async void FinishedPickingAssets(object sender, MultiAssetEventArgs args)
        {
            IList <MediaFile> results = new List <MediaFile>();
            TaskCompletionSource <IList <MediaFile> > tcs = new TaskCompletionSource <IList <MediaFile> >();

            var options = new Photos.PHImageRequestOptions()
            {
                NetworkAccessAllowed = true
            };

            options.Synchronous  = false;
            options.ResizeMode   = PHImageRequestOptionsResizeMode.Fast;
            options.DeliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
            bool completed = false;

            for (var i = 0; i < args.Assets.Length; i++)
            {
                var asset = args.Assets[i];

                string fileName = string.Empty;
                if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                {
                    fileName = PHAssetResource.GetAssetResources(asset).FirstOrDefault().OriginalFilename;
                }

                switch (asset.MediaType)
                {
                case PHAssetMediaType.Video:

                    PHImageManager.DefaultManager.RequestImageForAsset(asset, new SizeF(150.0f, 150.0f),
                                                                       PHImageContentMode.AspectFill, options, async(img, info) =>
                    {
                        var startIndex = fileName.IndexOf(".", StringComparison.CurrentCulture);

                        string path = "";
                        if (startIndex != -1)
                        {
                            path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, $"{fileName.Substring(0, startIndex)}-THUMBNAIL.JPG");
                        }
                        else
                        {
                            path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, string.Empty);
                        }

                        if (!File.Exists(path))
                        {
                            img.AsJPEG().Save(path, true);
                        }

                        TaskCompletionSource <string> tvcs = new TaskCompletionSource <string>();

                        var vOptions = new PHVideoRequestOptions();
                        vOptions.NetworkAccessAllowed = true;
                        vOptions.Version      = PHVideoRequestOptionsVersion.Original;
                        vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.FastFormat;


                        PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) =>
                        {
                            var vPath = FileHelper.GetOutputPath(MediaFileType.Video, TemporalDirectoryName, fileName);

                            if (!File.Exists(vPath))
                            {
                                AVAssetExportSession exportSession = new AVAssetExportSession(avAsset, AVAssetExportSession.PresetHighestQuality);

                                exportSession.OutputUrl      = NSUrl.FromFilename(vPath);
                                exportSession.OutputFileType = AVFileType.QuickTimeMovie;


                                exportSession.ExportAsynchronously(() =>
                                {
                                    Console.WriteLine(exportSession.Status);

                                    tvcs.TrySetResult(vPath);
                                    //exportSession.Dispose();
                                });
                            }
                        });

                        var videoUrl = await tvcs.Task;
                        var meFile   = new MediaFile()
                        {
                            Type        = MediaFileType.Video,
                            Path        = videoUrl,
                            PreviewPath = path
                        };
                        results.Add(meFile);
                        OnMediaPicked?.Invoke(this, meFile);

                        if (args.Assets.Length == results.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(results);
                        }
                    });



                    break;

                default:

                    Photos.PHImageManager.DefaultManager.RequestImageData(asset, options, (data, dataUti, orientation, info) =>
                    {
                        string path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, fileName);

                        if (!File.Exists(path))
                        {
                            Debug.WriteLine(dataUti);
                            var imageData = data;
                            //var image = UIImage.LoadFromData(imageData);

                            //if (imageScale < 1.0f)
                            //{
                            //    //begin resizing image
                            //    image = image.ResizeImageWithAspectRatio((float)imageScale);
                            //}

                            //if (imageQuality < 100)
                            //{
                            //    imageData = image.AsJPEG(Math.Min(imageQuality,100));
                            //}

                            imageData?.Save(path, true);
                        }

                        var meFile = new MediaFile()
                        {
                            Type        = MediaFileType.Image,
                            Path        = path,
                            PreviewPath = path
                        };

                        results.Add(meFile);
                        OnMediaPicked?.Invoke(this, meFile);
                        if (args.Assets.Length == results.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(results);
                        }
                    });

                    break;
                }
            }


            mediaPickTcs?.TrySetResult(await tcs.Task);
        }
コード例 #10
0
        async Task <MediaFile> GetPictureMediaFile(NSDictionary info)
        {
            var image = (UIImage)info[UIImagePickerController.EditedImage] ?? (UIImage)info[UIImagePickerController.OriginalImage];

            if (image == null)
            {
                return(null);
            }

            var pathExtension = ((info[UIImagePickerController.ReferenceUrl] as NSUrl)?.PathExtension == "PNG") ? "png" : "jpg";

            var path = GetOutputPath(MediaImplementation.TypeImage,
                                     options.Directory ?? ((IsCaptured) ? string.Empty : "temp"),
                                     options.Name, pathExtension);

            var cgImage = image.CGImage;

            var   percent   = 1.0f;
            float newHeight = image.CGImage.Height;
            float newWidth  = image.CGImage.Width;

            if (options.PhotoSize != PhotoSize.Full)
            {
                try
                {
                    switch (options.PhotoSize)
                    {
                    case PhotoSize.Large:
                        percent = .75f;
                        break;

                    case PhotoSize.Medium:
                        percent = .5f;
                        break;

                    case PhotoSize.Small:
                        percent = .25f;
                        break;

                    case PhotoSize.Custom:
                        percent = (float)options.CustomPhotoSize / 100f;
                        break;
                    }

                    if (options.PhotoSize == PhotoSize.MaxWidthHeight && options.MaxWidthHeight.HasValue)
                    {
                        var max = Math.Max(image.CGImage.Width, image.CGImage.Height);
                        if (max > options.MaxWidthHeight.Value)
                        {
                            percent = (float)options.MaxWidthHeight.Value / (float)max;
                        }
                    }

                    if (percent < 1.0f)
                    {
                        //begin resizing image
                        image = image.ResizeImageWithAspectRatio(percent);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Unable to compress image: {ex}");
                }
            }


            NSDictionary meta = null;

            try
            {
                if (options.SaveMetaData)
                {
                    if (source == UIImagePickerControllerSourceType.Camera)
                    {
                        meta = info[UIImagePickerController.MediaMetadata] as NSDictionary;
                        if (meta != null && meta.ContainsKey(ImageIO.CGImageProperties.Orientation))
                        {
                            var newMeta = new NSMutableDictionary();
                            newMeta.SetValuesForKeysWithDictionary(meta);
                            var newTiffDict = new NSMutableDictionary();
                            newTiffDict.SetValuesForKeysWithDictionary(meta[ImageIO.CGImageProperties.TIFFDictionary] as NSDictionary);
                            newTiffDict.SetValueForKey(meta[ImageIO.CGImageProperties.Orientation], ImageIO.CGImageProperties.TIFFOrientation);
                            newMeta[ImageIO.CGImageProperties.TIFFDictionary] = newTiffDict;

                            meta = newMeta;
                        }
                        var location = options.Location;
                        if (meta != null && location != null)
                        {
                            meta = SetGpsLocation(meta, location);
                        }
                    }
                    else
                    {
                        var url = info[UIImagePickerController.ReferenceUrl] as NSUrl;
                        if (url != null)
                        {
                            meta = PhotoLibraryAccess.GetPhotoLibraryMetadata(url);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Unable to get metadata: {ex}");
            }

            //iOS quality is 0.0-1.0
            var quality    = pathExtension == "jpg" ? (options.CompressionQuality / 100f) : 0f;
            var savedImage = false;

            if (meta != null)
            {
                savedImage = SaveImageWithMetadata(image, quality, meta, path, pathExtension);
            }

            if (!savedImage)
            {
                var finalQuality = quality;
                var imageData    = pathExtension == "png" ? image.AsPNG() : image.AsJPEG(finalQuality);

                //continue to move down quality , rare instances
                while (imageData == null && finalQuality > 0)
                {
                    finalQuality -= 0.05f;
                    imageData     = image.AsJPEG(finalQuality);
                }

                if (imageData == null)
                {
                    throw new NullReferenceException("Unable to convert image to jpeg, please ensure file exists or lower quality level");
                }


                imageData.Save(path, true);
                imageData.Dispose();
            }


            string aPath = null;

            if (source != UIImagePickerControllerSourceType.Camera)
            {
                //try to get the album path's url
                var url = (NSUrl)info[UIImagePickerController.ReferenceUrl];
                aPath = url?.AbsoluteString;
            }
            else
            {
                if (options.SaveToAlbum)
                {
                    try
                    {
                        var library   = new ALAssetsLibrary();
                        var albumSave = await library.WriteImageToSavedPhotosAlbumAsync(cgImage, meta);

                        aPath = albumSave.AbsoluteString;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("unable to save to album:" + ex);
                    }
                }
            }

            Func <Stream> getStreamForExternalStorage = () =>
            {
                if (options.RotateImage)
                {
                    return(RotateImage(image, options.CompressionQuality, pathExtension));
                }
                else
                {
                    return(File.OpenRead(path));
                }
            };

            string originalFilename = null;

            if (info.TryGetValue(UIImagePickerController.PHAsset, out var assetObj))
            {
                var asset = (PHAsset)assetObj;
                if (asset != null)
                {
                    originalFilename = PHAssetResource.GetAssetResources(asset)?.FirstOrDefault()?.OriginalFilename;
                }
            }

            return(new MediaFile(path, () => File.OpenRead(path), streamGetterForExternalStorage: () => getStreamForExternalStorage(), albumPath: aPath, originalFilename: originalFilename));
        }
コード例 #11
0
ファイル: MediaPicker.ios.cs プロジェクト: sung-su/maui
        static FileResult DictionaryToMediaFile(NSDictionary info)
        {
            if (info == null)
            {
                return(null);
            }

            PHAsset phAsset  = null;
            NSUrl   assetUrl = null;

            if (OperatingSystem.IsIOSVersionAtLeast(11, 0))
            {
                assetUrl = info[UIImagePickerController.ImageUrl] as NSUrl;

                // Try the MediaURL sometimes used for videos
                if (assetUrl == null)
                {
                    assetUrl = info[UIImagePickerController.MediaURL] as NSUrl;
                }

                if (assetUrl != null)
                {
                    if (!assetUrl.Scheme.Equals("assets-library", StringComparison.OrdinalIgnoreCase))
                    {
                        return(new UIDocumentFileResult(assetUrl));
                    }
#pragma warning disable CA1416 // TODO: 'UIImagePickerController.PHAsset' is only supported on: 'ios' from version 11.0 to 14.0
                    phAsset = info.ValueForKey(UIImagePickerController.PHAsset) as PHAsset;
#pragma warning restore CA1416
                }
            }

#if !MACCATALYST
#pragma warning disable CA1416 // TODO: 'UIImagePickerController.ReferenceUrl' is unsupported on 'ios' 11.0 and later
            if (phAsset == null)
            {
                assetUrl = info[UIImagePickerController.ReferenceUrl] as NSUrl;

                if (assetUrl != null)
                {
                    phAsset = PHAsset.FetchAssets(new NSUrl[] { assetUrl }, null)?.LastObject as PHAsset;
                }
            }
#pragma warning restore CA1416 // 'PHAsset.FetchAssets(NSUrl[], PHFetchOptions?)' is unsupported on 'ios' 11.0 and later
#endif

            if (phAsset == null || assetUrl == null)
            {
                var img = info.ValueForKey(UIImagePickerController.OriginalImage) as UIImage;

                if (img != null)
                {
                    return(new UIImageFileResult(img));
                }
            }

            if (phAsset == null || assetUrl == null)
            {
                return(null);
            }
#pragma warning disable CA1416 // https://github.com/xamarin/xamarin-macios/issues/14619
            string originalFilename = PHAssetResource.GetAssetResources(phAsset).FirstOrDefault()?.OriginalFilename;
#pragma warning restore CA1416
            return(new PHAssetFileResult(assetUrl, phAsset, originalFilename));
        }
コード例 #12
0
        async Task <IList <MediaAsset> > LoadMediaAsync()
        {
            IList <MediaAsset> assets = new List <MediaAsset>();
            var imageManager          = new PHCachingImageManager();
            var hasPermission         = await RequestPermissionAsync();

            if (hasPermission)
            {
                await Task.Run(async() =>
                {
                    var thumbnailRequestOptions                  = new PHImageRequestOptions();
                    thumbnailRequestOptions.ResizeMode           = PHImageRequestOptionsResizeMode.Fast;
                    thumbnailRequestOptions.DeliveryMode         = PHImageRequestOptionsDeliveryMode.FastFormat;
                    thumbnailRequestOptions.NetworkAccessAllowed = true;
                    thumbnailRequestOptions.Synchronous          = true;

                    var requestOptions                  = new PHImageRequestOptions();
                    requestOptions.ResizeMode           = PHImageRequestOptionsResizeMode.Exact;
                    requestOptions.DeliveryMode         = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
                    requestOptions.NetworkAccessAllowed = true;
                    requestOptions.Synchronous          = true;

                    var fetchOptions             = new PHFetchOptions();
                    fetchOptions.SortDescriptors = new NSSortDescriptor[] { new NSSortDescriptor("creationDate", false) };
                    fetchOptions.Predicate       = NSPredicate.FromFormat($"mediaType == {(int)PHAssetMediaType.Image} || mediaType == {(int)PHAssetMediaType.Video}");
                    var fetchResults             = PHAsset.FetchAssets(fetchOptions);
                    var tmpPath       = Path.GetTempPath();
                    var allAssets     = fetchResults.Select(p => p as PHAsset).ToArray();
                    var thumbnailSize = new CGSize(300.0f, 300.0f);

                    imageManager.StartCaching(allAssets, thumbnailSize, PHImageContentMode.AspectFit, thumbnailRequestOptions);
                    imageManager.StartCaching(allAssets, PHImageManager.MaximumSize, PHImageContentMode.AspectFit, requestOptions);


                    foreach (var result in fetchResults)
                    {
                        var phAsset = (result as PHAsset);
                        var name    = PHAssetResource.GetAssetResources(phAsset)?.FirstOrDefault()?.OriginalFilename;
                        var asset   = new MediaAsset()
                        {
                            Id   = phAsset.LocalIdentifier,
                            Name = name,
                            Type = phAsset.MediaType == PHAssetMediaType.Image ? MediaAssetType.Image : MediaAssetType.Video,
                        };

                        imageManager.RequestImageForAsset(phAsset, thumbnailSize, PHImageContentMode.AspectFit, thumbnailRequestOptions, (image, info) =>
                        {
                            if (image != null)
                            {
                                NSData imageData = null;
                                if (image.CGImage.RenderingIntent == CGColorRenderingIntent.Default)
                                {
                                    imageData = image.AsJPEG(0.8f);
                                }
                                else
                                {
                                    imageData = image.AsPNG();
                                }

                                if (imageData != null)
                                {
                                    var fileName  = Path.Combine(tmpPath, $"tmp_thumbnail_{Path.GetFileNameWithoutExtension(name)}.jpg");
                                    NSError error = null;
                                    imageData.Save(fileName, true, out error);
                                    if (error == null)
                                    {
                                        asset.PreviewPath = fileName;
                                    }
                                }
                            }
                        });
                        switch (phAsset.MediaType)
                        {
                        case PHAssetMediaType.Image:

                            imageManager.RequestImageForAsset(phAsset, PHImageManager.MaximumSize, PHImageContentMode.AspectFit, requestOptions, (image, info) =>
                            {
                                if (image != null)
                                {
                                    NSData imageData = null;
                                    if (image.CGImage.RenderingIntent == CGColorRenderingIntent.Default)
                                    {
                                        imageData = image.AsJPEG(0.8f);
                                    }
                                    else
                                    {
                                        imageData = image.AsPNG();
                                    }

                                    if (imageData != null)
                                    {
                                        var fileName  = Path.Combine(tmpPath, $"tmp_{name}");
                                        NSError error = null;
                                        imageData.Save(fileName, true, out error);
                                        if (error == null)
                                        {
                                            asset.Path = fileName;
                                        }
                                    }
                                }
                            });
                            break;

                        case PHAssetMediaType.Video:
                            var videoRequestOptions = new PHVideoRequestOptions();
                            videoRequestOptions.NetworkAccessAllowed = true;
                            var tcs = new TaskCompletionSource <bool>();
                            imageManager.RequestAvAsset(phAsset, null, (vAsset, audioMix, info) =>
                            {
                                var avAsset   = vAsset as AVUrlAsset;
                                var avData    = NSData.FromUrl(avAsset.Url);
                                NSError error = null;
                                var path      = Path.Combine(tmpPath, $"tmp_{name}");
                                avData.Save(path, true, out error);
                                if (error == null)
                                {
                                    asset.Path = path;


                                    tcs.TrySetResult(true);
                                }
                                else
                                {
                                    tcs.TrySetResult(false);
                                }
                            });
                            await tcs.Task;
                            break;
                        }

                        UIApplication.SharedApplication.InvokeOnMainThread(delegate
                        {
                            OnMediaAssetLoaded?.Invoke(this, new MediaEventArgs(asset));
                        });
                        assets.Add(asset);

                        if (requestStop)
                        {
                            break;
                        }
                    }
                });

                imageManager.StopCaching();
            }

            return(assets);
        }
コード例 #13
0
        protected void Internal_FillCache()
        {
            if (_bCached)
            {
                return;
            }
            _globalLock.EnterWriteLock();

            try
            {
                if (_bCached)
                {
                    return;
                }

                var cacheDir    = new Dictionary <string, PHAssetCollection>();
                var cachePhoto  = new Dictionary <string, PHPhotoItem>();
                var collections = PHAssetCollection.FetchAssetCollections(PHAssetCollectionType.SmartAlbum, PHAssetCollectionSubtype.SmartAlbumUserLibrary, null);
                foreach (PHAssetCollection asset in collections)
                {
                    cacheDir["/" + asset.LocalizedTitle] = asset;

                    var assets = PHAsset.FetchAssets(asset, null);
                    foreach (PHAsset photo in assets)
                    {
                        var assetResources = PHAssetResource.GetAssetResources(photo);
                        var original       = assetResources.FirstOrDefault(x => x.ResourceType == PHAssetResourceType.Video ||
                                                                           x.ResourceType == PHAssetResourceType.Photo ||
                                                                           x.ResourceType == PHAssetResourceType.Audio);

                        if (original == null)
                        {
                            continue;
                        }

                        var   dt       = photo.CreationDate.ToDateTime();
                        var   dtstr    = dt.ToLocalTime().ToString("yyyy-MM-dd HH_mm");
                        var   filename = $"{dtstr} {original.OriginalFilename}";
                        UPath up       = Path.Combine(asset.LocalizedTitle, filename);
                        var   item     = new PHPhotoItem {
                            Col   = asset,
                            Asset = photo,
                            Res   = original
                        };
                        item.Path   = new Lazy <string>(item.FillPath);
                        item.Length = new Lazy <long>(item.FillLength);

                        cachePhoto[up.ToAbsolute().ToString().ToUpperInvariant()] = item;

                        var originalName = Path.GetFileNameWithoutExtension(original.OriginalFilename);
                        foreach (var resource in assetResources)
                        {
                            if (resource == original)
                            {
                                continue;
                            }
                            if (string.IsNullOrEmpty(resource.OriginalFilename))
                            {
                                continue;
                            }

                            var extension = Path.GetExtension(resource.OriginalFilename) ?? string.Empty;
                            var fileName  = $"{dtstr} {originalName} ({resource.ResourceType:G}){extension}";

                            up = Path.Combine(asset.LocalizedTitle, fileName);


                            item = new PHPhotoItem {
                                Col   = asset,
                                Asset = photo,
                                Res   = resource
                            };
                            item.Path   = new Lazy <string>(item.FillPath);
                            item.Length = new Lazy <long>(item.FillLength);

                            cachePhoto[up.ToAbsolute().ToString().ToUpperInvariant()] = item;
                        }
                    }
                }

                _cacheDir   = cacheDir;
                _cachePhoto = cachePhoto;
                _bCached    = true;
                Task.Run(() => {
                    Parallel.ForEach(cachePhoto, new ParallelOptions {
                        MaxDegreeOfParallelism = 2 * Environment.ProcessorCount
                    },
                                     x => {
                        _ = x.Value.Length.Value;
                        _ = x.Value.Path.Value;
                    });
                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                _globalLock.ExitWriteLock();
            }
        }
コード例 #14
0
 public static long?UserInfoGetSize(this PHAssetResource resource)
 {
     return((resource.ValueForKey(new NSString("fileSize")) as NSNumber)?.Int64Value);
 }
コード例 #15
0
        MediaFile GetPictureMediaFile(ALAsset asset, long index = 0)
        {
            var rep = asset.DefaultRepresentation;

            if (rep == null)
            {
                return(null);
            }

            var cgImage = rep.GetImage();

            UIImage image            = null;
            string  originalFilename = null;

            if (cgImage == null)
            {
                var fetch = PHAsset.FetchAssets(new[] { asset.AssetUrl }, null);
                var ph    = fetch.firstObject as PHAsset;
                originalFilename = PHAssetResource.GetAssetResources(ph)?.FirstOrDefault()?.OriginalFilename;
                var manager   = PHImageManager.DefaultManager;
                var phOptions = new PHImageRequestOptions
                {
                    Version = PHImageRequestOptionsVersion.Original,
                    NetworkAccessAllowed = true,
                    Synchronous          = true
                };

                phOptions.ProgressHandler = (double progress, NSError error, out bool stop, NSDictionary info) =>
                {
                    Debug.WriteLine($"Progress: {progress.ToString()}");

                    stop = false;
                };

                if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
                {
                    manager.RequestImageDataAndOrientation(ph, phOptions, (data, i, orientation, k) =>
                    {
                        if (data != null)
                        {
                            image = new UIImage(data, 1.0f);
                        }
                    });
                }
                else
                {
                    manager.RequestImageData(ph, phOptions, (data, i, orientation, k) =>
                    {
                        if (data != null)
                        {
                            image = new UIImage(data, 1.0f);
                        }
                    });
                }
                phOptions?.Dispose();
                fetch?.Dispose();
                ph?.Dispose();
            }
            else
            {
                image = new UIImage(cgImage, 1.0f, (UIImageOrientation)rep.Orientation);
            }

            var path = MediaPickerDelegate.GetOutputPath(MediaImplementation.TypeImage,
                                                         options.Directory ?? "temp",
                                                         options.Name, asset.AssetUrl?.PathExtension, index);
            var isPng = Path.GetExtension(path).ToLowerInvariant() == ".png";

            cgImage?.Dispose();
            cgImage = null;
            rep?.Dispose();
            rep = null;

            //There might be cases when the original image cannot be retrieved while image thumb was still present.
            //Then no need to try to save it as we will get an exception here
            //TODO: Ideally, we should notify the client that we failed to get original image
            //TODO: Otherwise, it might be confusing to the user, that he saw the thumb, but did not get the image
            if (image == null)
            {
                return(null);
            }

            if (isPng)
            {
                image.AsPNG().Save(path, true);
            }
            else
            {
                image.AsJPEG().Save(path, true);
            }

            image?.Dispose();
            image = null;
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Default);

            string aPath = null;
            //try to get the album path's url
            var url = asset.AssetUrl;

            aPath = url?.AbsoluteString;

            return(new MediaFile(path, () => File.OpenRead(path), albumPath: aPath, originalFilename: originalFilename));
        }