I want save some string with image in particular album.
so I used [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
to add assets.
but when I get photos from album it doesn't have exif data.
my code for save EXIF data is here . Any answer please.
- (void)addImageToCameraRoll:(UIImage *)image didfinish:(NSString *)albumName {
void (^saveBlock)(PHAssetCollection *assetCollection) = ^void(PHAssetCollection *assetCollection) {
NSData* jpeg = UIImageJPEGRepresentation(image, 1.0f);
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) jpeg, NULL);
CFStringRef imageType = CGImageSourceGetType(source);
NSDictionary *metadata = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL));
NSMutableDictionary *metadataAsMutable = [metadata mutableCopy];
NSMutableDictionary *EXIFDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
NSMutableDictionary *GPSDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyGPSDictionary]mutableCopy];
if(!EXIFDictionary){
//if the image does not have an EXIF dictionary (not all images do), then create one for us to use
EXIFDictionary = [NSMutableDictionary dictionary];
}
if(!GPSDictionary){
GPSDictionary = [NSMutableDictionary dictionary];
}
[GPSDictionary setValue:[NSNumber numberWithFloat:1.1] forKey:(NSString*)kCGImagePropertyGPSLatitude];
[GPSDictionary setValue:[NSNumber numberWithFloat:2.2] forKey:(NSString*)kCGImagePropertyGPSLongitude];
[EXIFDictionary setValue:#"my string to exif" forKey:(NSString *)kCGImagePropertyExifUserComment];
[metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
[metadataAsMutable setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
NSMutableData *resultData = [NSMutableData data];
CGImageDestinationRef imgDest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)(resultData), imageType, 1, NULL);
//copy image data
CGImageDestinationAddImageFromSource(imgDest, source, 0, (CFDictionaryRef) metadataAsMutable);
BOOL success = CGImageDestinationFinalize(imgDest);
UIImage * image1 = [[UIImage alloc] initWithData:resultData];
//Add assets
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image1];
PHObjectPlaceholder *assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset;
PHAssetCollectionChangeRequest *albumChangeRequest =
[PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[albumChangeRequest addAssets:#[ assetPlaceholder ]];
}
completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(#"Error creating asset: %#", error);
}else{
}
}];
};
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:#"localizedTitle = %#", albumName];
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions];
if (fetchResult.count > 0) {
saveBlock(fetchResult.firstObject);
}
else {
__block PHObjectPlaceholder *albumPlaceholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
albumPlaceholder = changeRequest.placeholderForCreatedAssetCollection;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[albumPlaceholder.localIdentifier] options:nil];
if (fetchResult.count > 0) {
saveBlock(fetchResult.firstObject);
}
} else {
NSLog(#"Error creating album: %#", error);
}
}];
}
}
I am using PHImageManager for getting images.
To Save the detail with Photo using Photos framework, You have to write the image to a temporary file and add the metadata to the temporary file using CGImageDestinationAddImage.
Then you can read the data from the temporary file and save it to the Photos library by using [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL].
Related
I am trying to delete a photo from the photo gallery of the phone, but the deleted image was in the deleted directory, there is a way to delete the picture which is in the deleted directory of the phone?
There is my code :
-(void)deleteCaptureProcess{
PHAsset *asset = nil;
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:YES]];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
if (fetchResult != nil && fetchResult.count > 0) {
// get last photo from Photos
asset = [fetchResult lastObject];
}
if (asset) {
PHContentEditingInputRequestOptions *editOptions = [[PHContentEditingInputRequestOptions alloc] init];
[asset requestContentEditingInputWithOptions:editOptions completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
if (contentEditingInput.fullSizeImageURL) {
NSLog(#"¨PATH %#",contentEditingInput.fullSizeImageURL);
NSArray *lines = [[NSString stringWithFormat:#"%#", contentEditingInput.fullSizeImageURL] componentsSeparatedByString: #"/"];
NSString *imageNZma = lines[[lines count]-1];
NSMutableArray *persons = [[NSMutableArray alloc]initWithCapacity:0];
[persons addObject:contentEditingInput.fullSizeImageURL];
__block PHAssetCollection *albumCollection = [[PHAssetCollection alloc] init];
PHFetchOptions *albumOptions = [[PHFetchOptions alloc] init];
[albumOptions setPredicate:[NSPredicate predicateWithFormat:#"estimatedAssetCount >= 0"]];
NSLog(#"%#",albumOptions);
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// Request creating an asset from the image.
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageNamed:imageNZma]];
// Request editing the album.
PHAssetCollectionChangeRequest* albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:albumCollection];
// Get a placeholder for the new asset and add it to the album editing request.
PHObjectPlaceholder* assetPlaceholder = [createAssetRequest placeholderForCreatedAsset]; [albumChangeRequest addAssets:#[ assetPlaceholder ]];
} completionHandler:^(BOOL success, NSError* error) {
NSLog(#"Finished adding asset. %#", (success ? #"Success" : error));
}];
__block PHObjectPlaceholder *assetPlaceholder = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest * request = [PHAssetChangeRequest creationRequestForAssetFromImage: [UIImage imageNamed:imageNZma]];
assetPlaceholder = request.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
NSLog(#"creation success %d - error: %# - place: %#", success, error, assetPlaceholder);
PHFetchResult * result = [PHAsset fetchAssetsWithLocalIdentifiers: #[assetPlaceholder.localIdentifier] options: nil];
NSLog(#"Asset fetching: %#", result);
[[PHPhotoLibrary sharedPhotoLibrary] performChanges: ^{
[PHAssetChangeRequest deleteAssets: #[asset]];
} completionHandler:^(BOOL success, NSError *error) {
// NSLog(#"deletion success %d - error: %# - place: %#", success, error, assetPlaceholder);
}];
}];
}
}];
}
}
So my question is : there is a way to delete directly the image from the deleted folder after the image in gallery was deleted ?
Thank for help
I need a little bit of help in here, I have a method that saves an UIImage into the my custom images folder, but images saving into the camera roll folder as well which is i don't want.
Please, can anyone suggest me how can i restrict to save into camera roll folder ?
NSString *albumName = #"myApp";
void (^saveBlock)(PHAssetCollection *assetCollection) = ^void(PHAssetCollection *assetCollection) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[assetCollectionChangeRequest addAssets:#[[assetChangeRequest placeholderForCreatedAsset]]];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(#"Error creating asset: %#", error);
}
}];
};
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:#"localizedTitle = %#", albumName];
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions];
if (fetchResult.count > 0) {
saveBlock(fetchResult.firstObject);
} else {
__block PHObjectPlaceholder *albumPlaceholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumName];
albumPlaceholder = changeRequest.placeholderForCreatedAssetCollection;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[albumPlaceholder.localIdentifier] options:nil];
if (fetchResult.count > 0) {
saveBlock(fetchResult.firstObject);
}
} else {
NSLog(#"Error creating album: %#", error);
}
}];
}
NSLog(#"Count : %lu",(unsigned long)[arrForHereLoImages count]);
Camera Roll contains all the devices pictures. This is by design in iOS. You can't prevent that.
Your image is not saved twice but actually saved in the camera roll and referenced in your custom Album.
I have more than 10 videos url in one view which is coming from Web service. I am showing these videos thumbnails in UITableview.
I am Using following code where I m Saving These Videos to gallery in particular folder
This is my code::
NSURL *url = [NSURL URLWithString:Urlstr];
NSData *data = [NSData dataWithContentsOfURL:url];
// Write it to cache directory
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"file.mov"];
[data writeToFile:path atomically:YES];
// After that use this path to save it to PhotoLibrary
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library addAssetsGroupAlbumWithName:#"MyFolderName" resultBlock:^(ALAssetsGroup *group)
{
//How to get the album URL?
// saving the video in gallery though file path and document directory
[library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(#"%#", error.description);
}else {
NSLog(#"Done :)");
}
}];
}
failureBlock:^(NSError *error) {
//Handle the error
}];
Now the issues is it is not saving my video to My folder. But it creates the folder and saving the video in default video folder of gallery.
Anyone please suggest me why it going like this.
- (void)createAlbumInPhotosLibrary:(NSString *)photoAlbumName videoAtFile:(NSURL *)videoURL {
// RELIVIT_moments
__block PHFetchResult *photosAsset;
__block PHAssetCollection *collection;
__block PHObjectPlaceholder *placeholder;
// Find the album
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:#"title = %#", photoAlbumName];
collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
subtype:PHAssetCollectionSubtypeAny
options:fetchOptions].firstObject;
// Create the album
if (!collection)
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:photoAlbumName];
placeholder = [createAlbum placeholderForCreatedAssetCollection];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[placeholder.localIdentifier]
options:nil];
collection = collectionFetchResult.firstObject;
[self saveVideoInRelivitFolderSetPlaceHolder:placeholder photosAsset:photosAsset collection:collection VideoAtFile:videoURL];
}
}];
} else {
[self saveVideoInRelivitFolderSetPlaceHolder:placeholder photosAsset:photosAsset collection:collection VideoAtFile:videoURL];
}
}
- (void)saveVideoInRelivitFolderSetPlaceHolder:(PHObjectPlaceholder *)placeholderLocal photosAsset:(PHFetchResult *)photosAssetLocal collection:(PHAssetCollection *)collectionLocal VideoAtFile:(NSURL *)videoURL {
__block PHFetchResult *photosAsset = photosAssetLocal;
__block PHAssetCollection *collection = collectionLocal;
__block PHObjectPlaceholder *placeholder = placeholderLocal;
// Save to the album
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:videoURL];
placeholder = [assetRequest placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection
assets:photosAsset];
[albumChangeRequest addAssets:#[placeholder]];
} completionHandler:^(BOOL success, NSError *error) {
if (success)
{
NSLog(#"done");
}
else
{
NSLog(#"%#", error.localizedDescription);
}
}];
}
I am using following code to save image to my custom folder created in iOS photo gallery:
I get this error: Error Domain=NSCocoaErrorDomain Code=-1 "(null)"
Can anyone help me out on this ?
+(BOOL)saveToAlbum:(NSString*)albumName image:(UIImage*)image{
__block PHFetchResult *photosAsset;
__block PHAssetCollection *collection;
__block PHObjectPlaceholder *placeholder;
__block BOOL retStat = false;
NSData *newImageSize = UIImageJPEGRepresentation(image, 1);
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageWithData:newImageSize]];
placeholder = [assetRequest placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:[self findAlbumAssetCollection:albumName] options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection
assets:photosAsset];
[albumChangeRequest addAssets:#[placeholder]];
} completionHandler:^(BOOL success, NSError *error) {
if (success){
retStat = true;
}
else{
NSLog(#"%#", error);
}}];
}
Answering here so someone can find this in google search results and save themselves the time I wasted: If you get this error creating an asset, check your phone storage. I got this error as a propagation of another silent error because my phone had 0 bytes (yes, 0 bytes) available storage space.
Thanks Mr.T for providing me a hint(collection was nil at albumChangeRequest)..Here is the correct solution for this.
+(BOOL)saveToAlbum:(NSString*)albumName image:(UIImage*)image{
__block BOOL retStat = false;
NSData *newImageSize = UIImageJPEGRepresentation(image, 1);
UIImage *imageNew = [UIImage imageWithData:newImageSize];
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHFetchResult *photosAsset;
PHAssetCollection *collection = [self findAlbumAssetCollection:albumName];
PHObjectPlaceholder *placeholder;
placeholder = [[PHAssetChangeRequest creationRequestForAssetFromImage:imageNew] placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection assets:photosAsset];
[albumChangeRequest addAssets:#[placeholder]];
} completionHandler:^(BOOL success, NSError *error) {
if (success){
retStat = true;
}
else{
NSLog(#"%#", error);
}}];
return retStat;}
+(PHAssetCollection*)findAlbumAssetCollection:(NSString*)albumName{
PHAssetCollection *collection;
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:#"title = %#", albumName];
collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
subtype:PHAssetCollectionSubtypeAny
options:fetchOptions].firstObject;
return collection;
}
How can I export video using AVAssetExportSession and save result video in a custom album, for example My Own Videos?
First you need to create a folder:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSString *folderName = #"My Own Videos";
[library addAssetsGroupAlbumWithName:folderName
resultBlock:^(ALAssetsGroup *group)
{
NSLog(#"Added folder:%#", folderName);
}
failureBlock:^(NSError *error)
{
NSLog(#"Error adding folder");
}];
Then, find the folder:
__block ALAssetsGroup* folder;
[library enumerateGroupsWithTypes:ALAssetsGroupAlbum
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if ([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString:folderName])
{
folder = group;
}
}
failureBlock:^(NSError* error)
{
// Error handling.
}];
And add your video to it. Save the asset to Library:
AVURLAsset *videoAsset = ...
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset
presetName:AVAssetExportPreset1280x720];
exportSession.outputURL = [[NSFileManager defaultManager] URLForInterviewWithFileName:newFileName];
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^{ ...
And put it into the album:
[folder addAsset:asset];
Hope it helps.
after export session (when you have the url)
-(void)saveVideoUrl:(NSURL*)url toCollection:(NSString *)collectionTitle {
NSLog(#"entered %s", __PRETTY_FUNCTION__);
__block PHFetchResult *photosAsset;
__block PHAssetCollection *collection;
__block PHObjectPlaceholder *placeholder;
// Find the album
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:#"title = %#", collectionTitle];
// this is how we get a match for album Title held by 'collectionTitle'
collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:fetchOptions].firstObject;
// check if album exists
if (!collection)
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
NSLog(#" Album did not exist, now creating album: %#",collectionTitle);
// Create the album
PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionTitle];
placeholder = [createAlbum placeholderForCreatedAssetCollection];
} completionHandler:^(BOOL didItSucceed, NSError *error) {
if (didItSucceed)
{
PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[placeholder.localIdentifier] options:nil];
collection = collectionFetchResult.firstObject;
}
}];
}
// Save to the album
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
placeholder = [assetRequest placeholderForCreatedAsset];
photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection assets:photosAsset];
[albumChangeRequest addAssets:#[placeholder]];
} completionHandler:^(BOOL didItSucceed, NSError *error) {
if (didItSucceed)
{ // if YES
NSLog(#" Looks like Image was saved in camera Roll as %#", placeholder.localIdentifier);
NSLog(#"placeholder holds %#", placeholder.debugDescription );
}
else
{
NSLog(#"%#", error);
}
}];
}