Exporting the map image

886
12
07-18-2011 10:22 AM
RickJones
Occasional Contributor II
Where would I look for a function to export the mapview's image?
I've tried the reference.
0 Kudos
12 Replies
NimeshJarecha
Esri Regular Contributor
Rick,

There is no direct function in ArcGIS API for iOS to export image of mapView. You need to use iOS SDK to do so. It's very simple. Here is the code...

- (IBAction)exportMapViewImage:(id)sender {

//export image of mapView
UIGraphicsBeginImageContext(self.mapView.frame.size);
[self.mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//save image to photo album
UIImageWriteToSavedPhotosAlbum(screenshot,self,@selector(image:didFinishSavingWithError:contextInfo:),nil);
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    // Was there an error?
    if (error != NULL)
    {
  // Show error message...
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
              message:[error localizedDescription]
                delegate:nil
             cancelButtonTitle:@"OK"
             otherButtonTitles:nil];
  [alert show];
  [alert release];
    }
    else  // No errors
    {
  // Show message image successfully saved
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Image Saved"
              message:@"Image saved to photo album successfully!"
                delegate:nil
             cancelButtonTitle:@"OK"
             otherButtonTitles:nil];
  [alert show];
  [alert release];
    }
}


Regards,
Nimesh
0 Kudos
RickJones
Occasional Contributor II
Nimesh,

Thank you for the snippet. I was unable to get it to work however.
I get "Error, Data unavailable" when it executes.

I don't see a property or method for AGSMapView called layer, but the compiler doesn't complain.
(I've tried 1.8 and 2.0).

I thought perhaps it was my Feature layers, so I created a new ViewDemo with Dynamic layer, and still got the error.
0 Kudos
NimeshJarecha
Esri Regular Contributor
Looks like you're testing in Simulator. Try testing on device. The layer property of mapView is inherited property of UIView.

Send your project if you're unable to get it to work.

Regards,
Nimesh
0 Kudos
RickJones
Occasional Contributor II
Thank you, it does work on the device.
And now, it works on the simulator.

What's interesting is, the saved image shows gridlines for the Tiles, while the screen image doesn't.
0 Kudos
ChristopherEbright
New Contributor III
Thanks Nimesh, that is a neat little trick.
I am going to try and extend that to export pdf to email.

Chris
0 Kudos
NimeshJarecha
Esri Regular Contributor
Rick,

Glad to know that it works for you now. 🙂 Not sure why the grid lines coming in the image.

Chris,

You're welcome 🙂

Regards,
Nimesh
0 Kudos
BedaKuster
New Contributor
Did anyone find out how to make an image without gridlines?
0 Kudos
Nicholas-Furness
Esri Regular Contributor
Hi all,

Took a little bit of sleuthing and reading up of Apple's documentation, but I did in the end manage to get rid of those pesky "grid lines". They're doubtless tile boundaries that aren't being drawn to the graphics context in the same way as to the screen. To me it smacked of some rounding during rendering, or anti-aliasing.

Sure enough, to get rid of them you need to add this line:

CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), NO);


However, you will notice if you're using a retina display, that the captured image is different to the on-screen one. To fix that, you need to begin the Image Context with some options other than the defaults adopted by UIGraphicsBeginImageContext().

This is some serious Apple silliness, but at least the documentation is there to guide you. So, use the following:

UIGraphicsBeginImageContextWithOptions(self.mapView.frame.size, NO, 0.0f);


By specifying a scale of 0.0f, you are telling the renderer to use the device's main display's resolution. On a retina display, you'd get the same effect if you used 2.0f, but 0.0f will work on any device.

You might also get away with YES instead of NO for the opaque parameter if you know enough about the layers you're rendering etc. etc..

So, the final code looks something like this:

UIGraphicsBeginImageContextWithOptions(self.mapView.frame.size, NO, 0.0f);
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), NO);

[self.mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//save image to photo album
UIImageWriteToSavedPhotosAlbum(screenshot,self,@selector(image:didFinishSavingWithError:contextInfo:),nil);


Hope this helps!

By the way, I still haven't got this to work in the simulator. Rick - do you remember how you got that to work?

Nick.
0 Kudos
RickJones
Occasional Contributor II
I spoke too soon. It no longer works in simulator. I get Data Unavailable now.
0 Kudos