Add image to photo library from bundle when purchased - iphone

Like in templeRun, we also wish to add inAp purchase to give image.
http://www.youtube.com/watch?v=dYog6yhs0y4
How can I download image placed inside game bundle to iphone's photo library?

Call UIImageWriteToSavedPhotosAlbum , which I believe looks like this:
UIImageWriteToSavedPhotosAlbum(
UIImage* image,
id completionTarget,
SEL completionSelector,
void* contextInfo
);
One way to use it is like this:
UIImage* myImage = [UIImage imageNamed:#"image.png"];
UIImageWriteToSavedPhotosAlbum(myImage, self, #selector(image:didFinishSavingWithError:contextInfo), nil);
You only need to set the completion target and completion selector if you want to be notified if it succeeded or failed. If so, don't forget to add this method to the class:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void*)contextInfo
{
if (error)
{
// Do something on error... (like show a UIAlert for example)
}
else
{
// Do something on success... (maybe show a "Your image was saved" alert
}
}
The image doesn't save right away and might error in the process so this can be useful.
You can also use the ALAssetsLibrary, which I believe would look like this:
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:[myImage CGImage] orientation:(ALAssetOrientation)[myImage imageOrientation] completionBlock:^(NSURL* assetURL, NSError* error)
{
if (error)
{
// Do something on error... (like show a UIAlert for example)
}
else
{
// Do something on success... (maybe show a "Your image was saved" alert
}
}];
Hope this helped.

Create a UIImage object from the picture within your bundle using imageNamed: and then use UIImageWriteToSavedPhotosAlbum() to save it to the Photo Library.
UIImage *image = [UIImage imageNamed:#"wallpaper.jpg"];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
For more information on the options for UIImageWriteToSavedPhotosAlbum() (callback functions, etc.) you can take a look at the UIKit Function Reference.

Related

How can I save an image to the camera roll?

I am new to Xcode (using 4.3) and am not sure how to save an image to the device's camera roll. All that I have done so far is set up an IBAction for the button to save the image. What library method or function can I use to save an image to the user's camera roll?
You use the UIImageWriteToSavedPhotosAlbum() function.
//Let's say the image you want to save is in a UIImage called "imageToBeSaved"
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
Edit:
//ViewController.m
- (IBAction)onClickSavePhoto:(id)sender{
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
}
Here's an answer for iOS8+ using the Photos framework.
Objective-C:
#import <Photos/Photos.h>
UIImage *snapshot = self.myImageView.image;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:snapshot];
changeRequest.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"successfully saved");
}
else {
NSLog(#"error saving to photos: %#", error);
}
}];
Swift:
// Swift 4.0
import Photos
let snapshot: UIImage = someImage
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: snapshot)
}, completionHandler: { success, error in
if success {
// Saved successfully!
}
else if let error = error {
// Save photo failed with error
}
else {
// Save photo failed with no error
}
})
Here's a link to the Apple documentation.
Don't forget to add the appropriate key/value to your info.plist to request permission to access the photo library:
<key>NSCameraUsageDescription</key>
<string>Enable camera access to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Enable photo library access to select a photo from your library.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Enable photo library access to save images to your photo library directly from the app.</string>
For reference, you can save videos in a similar manner:
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, nil, nil, nil);
You might want to save a video to upload to Instagram, for example:
// Save video to camera roll; we can share to Instagram from there.
-(void)didTapShareToInstagram:(id)sender {
UISaveVideoAtPathToSavedPhotosAlbum(self.videoPath, self, #selector(video:didFinishSavingWithError:contextInfo:), (void*)CFBridgingRetain(#{#"caption" : caption}));
}
- (void) video: (NSString *) videoPath
didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfoPtr {
NSDictionary *contextInfo = CFBridgingRelease(contextInfoPtr);
NSString *caption = contextInfo[#"caption"];
NSString *escapedString = [videoPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSString *escapedCaption = [caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:#"instagram://library?AssetPath=%#&InstagramCaption=%#", escapedString, escapedCaption]];
[[UIApplication sharedApplication] openURL:instagramURL];
}
Save the image in photo library in Swift 4
Add "Privacy - Photo Library Additions Usage Description" in info.plist
Then use following code to save image
UIImageWriteToSavedPhotosAlbum(imageView.image!, nil, nil, nil)
Use asImage() to get unique content to save to the camera roll.
If you use asImage() you can save a variety of fun things to the camera roll with just a few lines of code! This can be very powerful if the object has some transparency already incorporated.
asImage() works with UITextView, WKWebView, UIImageView, UIButton, UISlider, UITableView to name some objects (but they may need to be visible when you get the image (having a non zero alpha)). I even use it to capture tiling, but that's loaded into a UIImageView already in my design. I suspect asImage() may work with many more object types too, but I only tried the ones I mentioned.
If it's a UITextView, and you set the background color to .clear then the text gets saved with a transparent background. If your text contains emoji or Memoji, you can now get those images into the camera roll, or into UIImageViews internal to your app. Having Memoji/Emoji with a transparent background in your camera roll where they can be used in any variety of applications is powerful.
Other objects may have some transparency if you crop a photo image to a circle, or set the corner radius to clip off the corners.
Note in my code, pointerToTextObjectSelected is a UITextView
var pointerToTextObjectSelected = UITextView()
// above populated elsewhere
let thisObject = pointerToTextObjectSelected.asImage()
let imageData = thisObject.pngData()
let imageToSave = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(imageToSave!, nil, nil, nil)
// You will need this extension :
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}

loading images from disk in iPhone app is slow

In my iPhone app, I am using the iPhone's camera to take a photo and save it do disk (the application's documents folder). This is how i save it:
[UIImageJPEGRepresentation(photoTaken, 0.0) writeToFile:jpegPath atomically:YES];
Using the most compression, I figured reading the image from disk would be quick. But its not! I use the image as the background image for a button in one of my views. I load it like this:
[self.frontButton setBackgroundImage:[UIImage imageWithContentsOfFile:frontPath] forState:UIControlStateNormal];
When I navigate to the view with this button, it is slow and choppy. How do I fix this?
+imageWithContentsOfFile: is synchronous, so the UI on your main thread is being blocked by the image loading from disk operation and causing the choppiness. The solution is to use a method that loads the file asynchronously from disk. You could also do this in a background thread. This can be done easily by wrapping the +imageWithContentsOfFile: in dispatch_async(), then a nested dispatch_async() on the main queue that wraps -setBackgroundImage: since UIKit methods need to be run on the main thread. If you want the image to appear immediately after the view loads, you'll need to pre-cache the image from disk so it's in-memory immediately when the view appears.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
UIImage *image = [UIImage imageWithContentsOfFile:frontPath];
dispatch_async(dispatch_get_main_queue(), ^{
[self.frontButton setBackgroundImage:image forState:UIControlStateNormal];
});
});
As an aside, if the button image happens a gradient, consider using the following properties to ensure the image file loaded from disk is tiny:
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
or (deprecated, only use if you need to support iOS 4.x):
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight
This is the faster way I know. You'll need to import #import <ImageIO/ImageIO.h>
I use this code to download and compress images during a scroll, inside a scrollview and you barely notice the delay.
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)mutableData, NULL);
CFDictionaryRef options = (CFDictionaryRef)[[NSDictionary alloc] initWithObjectsAndKeys:(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform, (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent, (id)[NSNumber numberWithDouble:200.0], (id)kCGImageSourceThumbnailMaxPixelSize, nil];
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
UIImage *image = [[UIImage alloc] initWithCGImage:thumbnail];
// Cache
NSString *fileName = #"fileName.jpg";
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"thumbnail"];
path = [path stringByAppendingPathComponent:fileName];
if ([UIImagePNGRepresentation(image) writeToFile:path atomically:YES]) {
// Success
}
I face a very similar issue where I had to load hundreds of images from the directory. My performance was quite slow if I used UIImage(contentsOfFile:) method. The below method increased my performance to 70 %.
class ImageThumbnailGenerator: ThumbnailGenerator {
private let url: URL
init(url: URL) {
self.url = url
}
func generate(size: CGSize) -> UIImage? {
guard let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil) else {
return nil
}
let options: [NSString: Any] = [
kCGImageSourceThumbnailMaxPixelSize: Double(max(size.width, size.height) * UIScreen.main.scale),
kCGImageSourceCreateThumbnailFromImageIfAbsent: true
]
return CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as NSDictionary).flatMap { UIImage(cgImage: $0) }
}
}

How to get image path from photo library and how to retrieve the image from photo library in iphone?

I'm new to iphone. In my small application, how to get image path from photo library. I use this following code to getting images and placed in imageview.
-(IBAction) selectimage
{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:picker animated:YES];
[picker release];
}
-(void) imagePickerController:(UIImagePickerController *)UIPicker didFinishPickingMediaWithInfo:(NSDictionary *) info
{
[UIPicker dismissModalViewControllerAnimated:YES];
imageview.image=[info objectForKey:"UIImagePickerControllerOriginalImage"];
NSLog("Image Path=%#",imageview.image);
}
Its succefully placed to Imageview. But i cant get its imagepath. I'm using nslog("%#",imageview.image); it shows "Image Path=" in console.
How can i get its path and how to retrieve photos from photo library. Any body help me. Thanks in advance.
UIImagePickerControllerOriginalImage returns only the image's data, with no reference to its local storage. I haven't used it myself but I guess what you are looking for is
NSURL* localUrl = (NSURL *)[info valueForKey:UIImagePickerControllerReferenceURL];
At least, it's the only way I know of to retrieve any URL.
To retrieve the image, have a look at this question. But also keep in mind, that you already have the image retrieved with
UIImage* image=(UIImage*)[info objectForKey:#"UIImagePickerControllerOriginalImage"];
so ask yourself if you really need this.
Swift 3.0, You can get imageData from referenceURL by following way
let url = URL(string: "assets-library://asset/asset.JPG?id=1000000007&ext=JPG")
let asset = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
guard let result = asset.firstObject else {
return nil
}
let imageManager = PHImageManager.default()
var imageData: Data? = nil
imageManager.requestImageData(for: result, options: nil, resultHandler: { (data, string, orientation, dict) in
imageData = data
})

How to reuse a UIImage

I'm using some sample code I got from a tutorial to create basically a snapshot using AVCamRecorder. It doesn't save a picture, it just displays it in a little rect under the live camera view whenever I click a button. It seemed to be allocating more and more memory each time I clicked the button to update the image, so I put an if (image) {[image release]} and then continued with the rest of the code to capture the image. The problem I ran into there is that eventually I hit an EXC_BAD_ACCESS if I click the button fast enough repeatedly. I tried inserting an if (image) immediately before assigning it to my view, but I still get EXC_BAD_ACCESS. I tried adding an [NSThread sleepForTimeInterval:1] at the end, but that didn't help either. I still get the EXC_BAD_ACCESS after clicking the button several times. Is there a proper way to reuse this view? Thanks
if (image) {
[image release];
exifAttachments = nil;
}
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
exifAttachments = CMGetAttachment(imageDataSamplebuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments) {
// NSLog
} else {
// NSLog
}
NSData *imagedata = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
image = [[UIImage alloc] initWithData:imageData];
if (image) {
self.capturedPicView.image = image;
}
}];`
Is the image variable declared as __block? If not, you may get all sorts of weird things because you can't modify it within a block.
You probably don't need a separate image variable - just do:
self.capturedPicView.image = [[[UIImage alloc] initWithData:imageData] autorelease];
in your block.
P.S. And it looks like your original memory leak was due to not releasing the new image - you could have added autorelease to UIImage creation or just release it right after assigning (UIImageView.image retains it anyway):
image = [[UIImage alloc] initWithData:imageData];
if (image) {
self.capturedPicView.image = image;
[image release];
}

iPhone camera shoots photos rapidly, but has problems saving them

I'm attempting to take and save photos with the camera rapidly, as quickly as the iPhone can. The problem is that they don't save until the end and it then takes forever, or about 1/2 to 3/4 don't save at all (Write busy error or -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL).
I bet I'm just overloading the phone's memory, but I can't think of a way to handle it efficiently. The standard iPhone camera app can handle it just fine -- snap away at almost 1 photo/second and it saves with no problem.
Any ideas on how to manage the process/memory better so that it can save as it goes but still shoot rapidly?
Here's a bit of my code. takePicture is called whenever self.readyToTake = YES.
- (void)takePicture {
self.delegate = self;
[super takePicture];
self.readyToTake = NO;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
if (error)
{
NSLog([NSString stringWithFormat:#"** ERROR SAVING PHOTO: %#", [error localizedDescription]]);
}
}
Thank you for your help!
EDIT
If I resize the photos to much smaller dimensions before saving, like 480x640, I have no problem saving quickly. However, I'm wanting to capture and save full-size images. The native Camera app seems to handle it fine.
you can do like this.
ie., enable taking the next photo only after the previous photo is saved.
Also introduce autorelease pool for memory management.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
[pool drain];
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
if (error)
{
NSLog([NSString stringWithFormat:#"** ERROR SAVING PHOTO: %#", [error localizedDescription]]);
}
self.readyToTake = YES;
}
The first thing I'd try is offloading those calls asynchronously to a dispatch queue:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
});
}
If you're still having trouble, I'd look into AVCaptureSession and friends. This gives you a lot more control and generally better performance. There's a great sample project using this method at the developer portal: SquareCam
EDIT
You could also try using AssetsLibrary instead of UIImageWriteToSavedPhotosAlbum (This is what we use in all our apps) Something like:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
// you probably want to create this once and keep it around as a property
// on your controller
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[library writeImageToSavedPhotosAlbum:image.CGImageRef orientation:(ALAssetOrientation)image.orientation completionBlock:^(NSURL *assetURL, NSError *error) {
// do whatever you need to do when the image is saved
}];
}
there is one best example app on developer.apple.com site in which the solution for your problem is shown in it they save photos for 1second interval automatically when user tap on "timed" button here is its code it surely helps you as i can able to store 5 consicutive photos 1/second speed
Please see page MyViewController.m and after getting images in array you can save them to the photo album using some function on another queue