1/* xscreensaver, Copyright (c) 1992-2019 Jamie Zawinski <jwz@jwz.org> 2 * 3 * Permission to use, copy, modify, distribute, and sell this software and its 4 * documentation for any purpose is hereby granted without fee, provided that 5 * the above copyright notice appear in all copies and that both that 6 * copyright notice and this permission notice appear in supporting 7 * documentation. No representations are made about the suitability of this 8 * software for any purpose. It is provided "as is" without express or 9 * implied warranty. 10 */ 11 12/* iOS 8+ code to choose and return a random image from the photo library. 13 */ 14 15#ifdef USE_IPHONE // whole file 16 17#import <Photos/Photos.h> 18#import "grabscreen.h" 19#import "yarandom.h" 20 21void 22ios_load_random_image (void (*callback) (void *uiimage, const char *fn, 23 int width, int height, 24 void *closure), 25 void *closure, 26 int width, int height) 27{ 28 // If the user has not yet been asked for authoriziation, pop up the 29 // auth dialog now and re-invoke this function once it has been 30 // answered. The callback will run once there has been a Yes or No. 31 // Otherwise, we'd return right away with colorbars even if the user 32 // then went on to answer Yes. 33 // 34 PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; 35 if (status == PHAuthorizationStatusNotDetermined) { 36 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 37 ios_load_random_image (callback, closure, width, height); 38 }]; 39 return; 40 } 41 42 // The rest of this is synchronous. 43 44 PHFetchOptions *opt = [[PHFetchOptions new] autorelease]; 45 opt.includeAssetSourceTypes = (PHAssetSourceTypeUserLibrary | 46 PHAssetSourceTypeCloudShared | 47 PHAssetSourceTypeiTunesSynced); 48 PHFetchResult *r = [PHAsset 49 fetchAssetsWithMediaType: PHAssetMediaTypeImage 50 options: opt]; 51 NSUInteger n = [r count]; 52 PHAsset *asset = n ? [r objectAtIndex: random() % n] : NULL; 53 54 __block UIImage *img = 0; 55 __block const char *fn = 0; 56 57 if (asset) { 58 PHImageRequestOptions *opt = [[PHImageRequestOptions alloc] init]; 59 opt.synchronous = YES; 60 61 // Get the image bits. 62 // 63 int size = width > height ? width : height; 64 [[PHImageManager defaultManager] 65 requestImageForAsset: asset 66 targetSize: CGSizeMake (size, size) 67 contentMode: PHImageContentModeDefault 68 options: opt 69 resultHandler:^void (UIImage *image, NSDictionary *info) { 70 img = [image retain]; 71 }]; 72 73 // Get the image name. 74 // 75 [[PHImageManager defaultManager] 76 requestImageDataForAsset: asset 77 options: opt 78 resultHandler:^(NSData *imageData, NSString *dataUTI, 79 UIImageOrientation orientation, 80 NSDictionary *info) { 81 // Looks like UIImage is pre-rotated to compensate for 'orientation'. 82 NSString *path = [info objectForKey:@"PHImageFileURLKey"]; 83 if (path) 84 fn = [[[path lastPathComponent] stringByDeletingPathExtension] 85 cStringUsingEncoding:NSUTF8StringEncoding]; 86 }]; 87 } 88 89 if (img) 90 callback (img, fn, [img size].width, [img size].height, closure); 91 else 92 callback (0, 0, 0, 0, closure); 93} 94 95#endif // USE_IPHONE - whole file 96