How to save edited image? - ios4

I have UIImagePicker to select the image. After selecting the image I am editing it and now I want to save that image.
Can anyone please tell me how can I save the image to Photo Album?

take a look at this tutorial
http://iosdevelopertips.com/camera/camera-application-to-take-pictures-and-save-images-to-photo-album.html
here is my code to get image if the image is edited then edited image will be taken into account.
if not edited then original image will be taken
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage *image;
if (picker.editing == YES) {
image = [info objectForKey:#"UIImagePickerControllerEditedImage"];
}
else {
image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
// [picker release];
// [self dismissModalViewControllerAnimated:YES];
}

You can use this function
UIImageWriteToSavedPhotosAlbum(UIImage *yourImage, id completionTarget, SEL completionSelector, void *contextInfo);
See the answer to this question...And about completionTarget and completionSelector, from documentation...
The use of the completionTarget, completionSelector, and contextInfo
parameters is optional and necessary only if you want to be notified
asynchronously when the function finishes writing the image to the
user’s Camera Roll or Saved Photos album. If you do not want to be
notified, pass nil for these parameters.

Related

Branch Universal Deep Link does not display custom view controller elements

So I have a Universal link that leads to a view controller in my app. On that particular view controller I display a couple of images as well as a web view. The webView displays a url chosen by the user. How do I save this custom url so that it is displayed every time someone clicks the link? I think the code to this is under:
#synthesize deepLinkingCompletionDelegate;
-(void)configureControlWithData:(NSDictionary *)data {
NSString *string = data[#"favoriteArticle"];
Alex from Branch.io here:
To accomplish this, you need to do two things.
Step 1
Store the URL of the article you want to load as one of the Branch link custom parameters. Full instructions on how to do that here, but essentially:
BranchUniversalObject *branchUniversalObject = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:#"item/12345"];
branchUniversalObject.title = #"My Content Title";
branchUniversalObject.contentDescription = #"My Content Description";
branchUniversalObject.imageUrl = #"https://example.com/mycontent-12345.png";
[branchUniversalObject addMetadataKey:#"favorite_article" value:#"https://example.com/path/to/article"]; // this is used to route inside the app
[branchUniversalObject addMetadataKey:#"property2" value:#"red"];
BranchLinkProperties *linkProperties = [[BranchLinkProperties alloc] init];
linkProperties.feature = #"sharing";
linkProperties.channel = #"facebook";
[linkProperties addControlParam:#"$desktop_url" withValue:#"https://example.com/path/to/article"]; // this is used for desktop visitors
[linkProperties addControlParam:#"$ios_url" withValue:#"https://example.com/path/to/article"]; // this is used for iOS mobile visitors without the app installed
Step 2
Then when the app opens after a link click, watch for that data key. Again, full instructions, but basically:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// initialize the session, setup a deep link handler
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions
andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
// start setting up the view controller hierarchy
UINavigationController *navC = (UINavigationController *)self.window.rootViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *nextVC;
// If the key 'favoriteArticle' is present in the deep link dictionary
// then load the picture screen with the appropriate picture
NSString * favoriteArticle = [params objectForKey:#"favorite_article"];
if (favoriteArticle) {
nextVC = [storyboard instantiateViewControllerWithIdentifier:#"ArticleVC"];
[nextVC setArticleUrl: favoriteArticle];
} else {
nextVC = [storyboard instantiateViewControllerWithIdentifier:#"MainVC"];
}
// navigate!
[navC setViewControllers:#[nextVC] animated:YES];
}];
return YES;
}
After this, in your ArticleVC, retrieve the favoriteArticle value and use it for your webview.
Step 2 (Alternate)
The configureControlWithData method you mentioned is used in the automatic deep link routing implementation. You may be able to adapt this to work with a webview, but I haven't personally tried that. It would look something like this:
#synthesize deepLinkingCompletionDelegate;
- (void)configureControlWithData:(NSDictionary *)data {
NSString *favoriteArticle = data[#"favorite_article"];
// load the webview with the URL stored inside favoriteArticle
}

Threading issue with UICollectionview loading images from CloudKit

I'm having a threading issue loading images in a collectionview where the data is coming from cloudkit. I know this is a threading/blocking issue because before I implemented CK, I dumped some images in a folder on my desktop and read/parsed them from there and had no issue. With CK, I just created a handful of records via the dashboard and I'm successfully getting the expected records returned and use the images from those results to populate the CV cells. I store the CK query results in an array and use the size of that array to set the numberOfItemsInSection delegate.
Here's the issue...in the numberOfItemsInSection delegate method, I'm calling the model class, which executes the CK query. Since that is obviously a network call, I put that in a background thread. From logging, I can see the query execute and the results come back very quickly - within 2-3 seconds. However, the CV cells never display and I don't see the custom cell get initialized (via logging). But if I tap the camera button and take a photo, which I've implemented, I take the resulting image and add it to the array, then call reloadData on the CV and all the cells (and images) appear, including the new image just taken with the camera.
By accident, I found out a hack that somewhat works, which is calling reloadData on the CV inside the background thread of the numberOfItemsInSection delegate method. As a result, I thought I might have stumbled on to the solution by switching back to the main thread when calling reloadData, but that put it in a sort of endless loop of continuously calling the numberOfItemsInSection method and cellForItemAtIndexPath and made it to where it lagged to a point that you could barely scroll and tapping on any of the cells wouldn't do anything.
At this point, after trying many, many various things, I'm at a complete loss on how to fix this. I know this is probably a pretty easy solution as it's very common to load images asynchronously to populate a collectionview or tableview. Can someone please provide some guidance? Thanks in advance!!!
#property (nonatomic) NSInteger numberOfItemsInSection;
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSLog(#"***numberOfItemsInSection***");
dispatch_queue_t fetchQ = dispatch_queue_create("load image data", NULL);
dispatch_async(fetchQ, ^{
self.numberOfItemsInSection = [self.imageLoadManager.imageDataArray count];
[self.myCollectionView reloadData]; // should be done on main thread!
});
NSLog(#"numberOfItemsInSection: %ld", (long)self.numberOfItemsInSection);
return self.numberOfItemsInSection;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell"; // string value identifier for cell reuse
ImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
NSLog(#"cellForItemAtIndexPath: section:%ld row:%ld", (long)indexPath.section, (long)indexPath.row);
cell.layer.borderWidth = 1.0;
cell.layer.borderColor = [UIColor grayColor].CGColor;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
ImageData *imageData = [self.imageLoadManager imageDataForCell:indexPath.row]; // maps the model to the UI
dispatch_async(dispatch_get_main_queue(), ^{
if (imageData.imageURL.path) {
cell.imageView.image = [UIImage imageWithContentsOfFile:imageData.imageURL.path];
[cell setNeedsLayout];
} else {
// if imageURL is nil, then image is coming in from the camera as opposed to the cloud
cell.imageView.image = imageData.image;
[cell setNeedsLayout];
}
});
return cell;
}
before returning self.numberOfItemsInSection you should wait until the async call is finished. You can do that using semaphores. But then why are you doing this async? You are just getting the count of an array. And then you shouldn't reloadData there. Where do you start your CloudKit query? are you doing that onViewDidLoad? That is also an async operation. When that completes just doe a reloadData of your collectionView. Besides that doing this would be enough:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.imageLoadManager.imageDataArray count];
}
If you really want to use async there, then you do have to wait for the result. You could change your code to something like:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSLog(#"***numberOfItemsInSection***");
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_queue_t fetchQ = dispatch_queue_create("load image data", NULL);
dispatch_async(fetchQ, ^{
self.numberOfItemsInSection = [self.imageLoadManager.imageDataArray count];
[self.myCollectionView reloadData]; // should be done on main thread!
dispatch_semaphore_signal(sema);
});
NSLog(#"numberOfItemsInSection: %ld", (long)self.numberOfItemsInSection);
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return self.numberOfItemsInSection;
}
And then why do you go to the main queue in cellForItemAtIndexPath? It's already executed on the main queue.

download Route me online tiles into database

working on iPhone osm maps app (Route me).well initialising and downloading online maps was easy but real problem lies in saving the tiles through the code while u are online and reuse them while you are offline.i checked blogs regarding the same but everyone is saving the images externally and importing it in project and then showing them,which is not my requirement.please help me to save the tile image route me picks from online source
here is how i am using online route me maps
-(void) viewDidLoad
{
[RMMapView class];
mapView.contents.tileSource = [[RMOpenStreetMapSource alloc] init];
currentMarker = [[RMMarker alloc]initWithUIImage:[UIImage imageNamed:#"radarLocatorLite.png"] anchorPoint:CGPointMake(0.5, 0.5)];
markerManager = [mapView markerManager];
locationManager.delegate=self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest ;
locationManager.distanceFilter =0;
[mapView.contents setZoom:17.0f];
[markerManager addMarker:currentMarker AtLatLong:currentLocation.coordinate];
[self initCompassView];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentLocation =newLocation;
[mapView moveToLatLong:newLocation.coordinate];
[markerManager moveMarker:currentMarker AtLatLon: newLocation.coordinate];
[currentRoutePath addLineToLatLong:newLocation.coordinate];
[[mapView.contents overlay] addSublayer:currentRoutePath];
// NSLog(#"i reached inside location update%f",currentRoutePath.lineWidth);
}
I have an iOS app that uses static map images saved in a sqlite database. There are some references as to how to do that, but it took me lots of trial-and-error effort to make sense of them and make it work.
It seems that you should be able to have a sqlite database and save the downloaded images into it as your app downloads them. Then you'd have to know what tile source to use: the sqlite database if the app is offline, the OSM site when online.
The structure of the database is:
tilekey text // a hash that route-me uses to locate the correct tile
zoom integer
row integer
col integer
zoom integer
image blob this stores the actual image of the map
I use a Python script to populate the database, as I want the app to always use the static map images from the database, never to use a real-time download from OSM.
Please let me know if you'd like more information, but if you search for using static maps with route-me, you should find how this is done. Good luck!
finally resolved problem by just a minor change in few places
Step 1: Go to this site "http://shiki.me/blog/offline-maps-in-ios-using-openstreetmap-and-route-me/" and follow instructions to download tile images from online and create of zip of the folder.remember the tile images folder are in order ->zoom level folder->x coord foler->y coord image respectively.
step 2: unzip the zip file in ur app at some folder
step 3:go to the file "RMAbstractMercatorWebSource.m" in map view project
and replace the following folders
-(NSString*) tileFile: (RMTile) tile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Tiles"];
NSString *absPath=[NSString stringWithFormat:#"%#/%d/%d/%d.png", path,tile.zoom, tile.x, tile.y];
NSLog(#"file path >>>.............%#",absPath);
return absPath;
}//I unzipped the zip file at tiles folder
-(NSString*) tilePath
{
return nil;
}
-(RMTileImage *)tileImage:(RMTile)tile
{
RMTileImage *image;
tile = [tileProjection normaliseTile:tile];
NSString *file = [self tileFile:tile];
if(file && [[NSFileManager defaultManager] fileExistsAtPath:file])
{
image = [RMTileImage imageForTile:tile fromFile:file];
}
else if(networkOperations)
{
image = [RMTileImage imageForTile:tile withURL:[self tileURL:tile]];
}
else
{
image = [RMTileImage dummyTile:tile];
}
return image;
}
this in turns first look in cache then check the specified directory and finally go for online osm tile images

Handle touch event in uiimage in uiwebview

I am drawing one image (called image1) on top of the another image (called main image) And saved that image locally. Now I am loading the "main image" in the UIWebview. It is fine. But now I need to handle event when touch on the "image1".
Please help me.
Thanks,
Jasmine.
Try this
EDITED
create a UIWebView object 'webview' and create a UITapGestureRecognizer object 'TapGesture'
then
TapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapAction:)];
TapGesture.numberOfTapsRequired = 1;
TapGesture.delegate = self;
[self.webview TapGesture];
In this case once you click the image it will call 'tapAction ' method ,In that you can add your code
in TapAction you can add
[UIView animateWithDuration:1.0 animations:^
{
// you can add zooming frame here
}
completion:^(BOOL finished)
{
[self performTransition:UIViewAnimationOptionTransitionCrossDissolve];
}
];

UIGraphicsGetImageFromCurrentImageContext memory leak for scaling image

My iPhone application downloads image files from a server, stores it into NSTemporaryDirectory() and then loads the image in the UI asynchronously. Code flow is like this:
Show view with loading activity indicator and run a image downloader in the background.
Once the image is downloaded, it is written to a file.
A timer in the loading view keep checking for the availability of file in the temp directory and once available, loads the image from file and adds the image to the UI.
Before adding the image, it is scaled to required size.
Problem is, I use UIGraphicsGetImageFromCurrentImageContext to scale the image. Looks like the memory used by the image context is not getting cleaned. The app memory just keeps increasing as more files get downloaded.
Some code below:
Code to scale the image:
-(UIImage*)scaleToSize:(CGSize)size image:(UIImage *)imageref
{
UIGraphicsBeginImageContext(size);
[imageref drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
Loading image from temp directory:
-(void)loadImageFromFile: (NSString *) path
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
UIImage * imm = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
[self performSelectorOnMainThread:#selector(insertImage:) withObject:imm waitUntilDone:YES];
[pool release];
}
Adding image to view (subset of code):
self.imageContainer = [[UIImageView alloc] initWithFrame:CGRectMake(0,80,320,250)];
[self addSubview:self.imageContainer];
self.imageContainer.image = [self scaleToSize:CGSizeMake(320.0f, 250.0f) image:imm];
[imageContainer release];
What am I missing here ?
One way of avoiding the leak from UIGraphicsGetImageFromCurrentImageContext is to not call it at all by resizing the container instead of resizing image directly:
self.imageContainer.contentMode = UIViewContentModeScaleAspectFit;
self.imageContainer.frame = CGRectMake(self.imageContainer.frame.origin.x, self.imageContainer.frame.origin.y, 320.0f, 250.0f);

Resources