summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra Soto <fabian.guerra@mapbox.com>2017-10-04 10:03:03 -0400
committerGitHub <noreply@github.com>2017-10-04 10:03:03 -0400
commitf01588cac78b5e5411385faa451080a74320500b (patch)
tree1f0540cf5c71475f0ae6714d70b909338fed9b5f
parent6a846ce5a8ff1d62f4eafa3ef5bd0427096ca9e6 (diff)
downloadqtlocation-mapboxgl-f01588cac78b5e5411385faa451080a74320500b.tar.gz
[ios, macos] Improve snap shotter documentation. (#10020)
* [ios, macos] Improve snap shotter documentation. * [macos] Save snapshots in correct format * [macos] Renamed snapshot item to Export Image * [ios, macos] Clarify Snapshotter documentation. * [ios] Fix snapshot scale * [macOS] Fix snapshotter 4x scaling. * [ios] Fix snapshotter final image scale. * [ios, macos] Update snapshotter size documentation. * [ios, macos] Throw an exception when the snapshotter has already started. * [ios, macos] Add snapshotter header example. * [ios, macos] Use one of the predefined Foundation's exception names.
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.h85
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm78
-rw-r--r--platform/darwin/src/MGLTypes.h2
-rw-r--r--platform/ios/app/MBXSnapshotsViewController.m28
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.h2
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.mm4
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib2
-rw-r--r--platform/macos/app/MapDocument.m51
8 files changed, 160 insertions, 92 deletions
diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h
index a2a4f1b331..615d39bee4 100644
--- a/platform/darwin/src/MGLMapSnapshotter.h
+++ b/platform/darwin/src/MGLMapSnapshotter.h
@@ -12,40 +12,52 @@ MGL_EXPORT
@interface MGLMapSnapshotOptions : NSObject
/**
- Creates a set of options with the minimum required information
- @param styleURL the style url to use
- @param camera the camera settings
- @param size the image size
+ Creates a set of options with the minimum required information.
+
+ @param styleURL URL of the map style to snapshot. The URL may be a full HTTP or HTTPS URL,
+ a Mapbox URL indicating the style’s map ID (`mapbox://styles/{user}/{style`}), or a path
+ to a local file relative to the application’s resource path. Specify `nil` for the default style.
+ @param size The image size.
*/
-- (instancetype)initWithStyleURL:(NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize)size;
+- (instancetype)initWithStyleURL:(nullable NSURL *)styleURL camera:(MGLMapCamera *)camera size:(CGSize)size;
-#pragma mark - Configuring the map
+#pragma mark - Configuring the Map
/**
- The style URL for these options.
+ URL of the map style to snapshot.
*/
-@property (nonatomic, readonly) NSURL* styleURL;
+@property (nonatomic, readonly) NSURL *styleURL;
/**
- The zoom. Default is 0.
+ The zoom level.
+
+ The default zoom level is 0. If this property is non-zero and the camera property
+ is non-nil, the camera’s altitude is ignored in favor of this property’s value.
*/
-@property (nonatomic) double zoom;
+@property (nonatomic) double zoomLevel;
/**
- The `MGLMapcamera` options to use.
+ A camera representing the viewport visible in the snapshot.
+
+ If this property is non-nil and the `coordinateBounds` property is set to a non-empty
+ coordinate bounds, the camera’s center coordinate and altitude are ignored in favor
+ of the `coordinateBounds` property.
*/
-@property (nonatomic) MGLMapCamera* camera;
+@property (nonatomic) MGLMapCamera *camera;
/**
- A region to capture. Overrides the center coordinate
- in the mapCamera options if set
+ The cooordinate rectangle that encompasses the bounds to capture.
+
+ If this property is non-empty and the camera property is non-nil, the camera’s
+ center coordinate and altitude are ignored in favor of this property’s value.
*/
-@property (nonatomic) MGLCoordinateBounds region;
+@property (nonatomic) MGLCoordinateBounds coordinateBounds;
-#pragma mark - Configuring the image
+#pragma mark - Configuring the Image
/**
- The size of the output image. Minimum is 64x64
+ The size of the output image, measured in points.
+
*/
@property (nonatomic, readonly) CGSize size;
@@ -57,18 +69,46 @@ MGL_EXPORT
@end
+#if TARGET_OS_IPHONE
/**
A block to processes the result or error of a snapshot request.
- The result will be either an `MGLImage` or a `NSError`
+ @param snapshot The `UIImage` that was generated or `nil` if an error occurred.
+ @param error The error that occured or `nil` when successful.
+ */
+typedef void (^MGLMapSnapshotCompletionHandler)(UIImage* _Nullable snapshot, NSError* _Nullable error);
+#else
+/**
+ A block to processes the result or error of a snapshot request.
- @param snapshot The image that was generated or `nil` if an error occurred.
+ @param snapshot The `NSImage` that was generated or `nil` if an error occurred.
@param error The eror that occured or `nil` when succesful.
*/
-typedef void (^MGLMapSnapshotCompletionHandler)(MGLImage* _Nullable snapshot, NSError* _Nullable error);
+typedef void (^MGLMapSnapshotCompletionHandler)(NSImage* _Nullable snapshot, NSError* _Nullable error);
+#endif
/**
- A utility object for capturing map-based images.
+ An immutable utility object for capturing map-based images.
+
+ ### Example
+
+ ```swift
+ var camera = MGLMapCamera()
+ camera.centerCoordinate = CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365)
+ camera.pitch = 20
+
+ var options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
+ options.zoomLevel = 10
+
+ var snapshotter = MGLMapSnapshotter(options: options)
+ snapshotter.start { (image, error) in
+ if error {
+ // error handler
+ } else {
+ // image handler
+ }
+ }
+ ```
*/
MGL_EXPORT
@interface MGLMapSnapshotter : NSObject
@@ -92,6 +132,9 @@ MGL_EXPORT
/**
Cancels the snapshot creation request, if any.
+
+ Once you call this method, you cannot resume the snapshot. In order to obtain the
+ snapshot, create a new `MGLMapSnapshotter` object.
*/
- (void)cancel;
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index c81fd39c4a..12b932daa3 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -13,6 +13,7 @@
#import "MGLOfflineStorage_Private.h"
#import "MGLGeometry_Private.h"
#import "NSBundle+MGLAdditions.h"
+#import "MGLStyle.h"
#if TARGET_OS_IPHONE
#import "UIImage+MGLAdditions.h"
@@ -20,12 +21,19 @@
#import "NSImage+MGLAdditions.h"
#endif
+const CGPoint MGLLogoImagePosition = CGPointMake(8, 8);
+const CGFloat MGLSnapshotterMinimumPixelSize = 64;
+
@implementation MGLMapSnapshotOptions
-- (instancetype _Nonnull)initWithStyleURL:(NSURL* _Nonnull)styleURL camera:(MGLMapCamera*)camera size:(CGSize) size;
+- (instancetype _Nonnull)initWithStyleURL:(nullable NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize) size;
{
self = [super init];
if (self) {
+ if ( !styleURL)
+ {
+ styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];
+ }
_styleURL = styleURL;
_size = size;
_camera = camera;
@@ -41,28 +49,34 @@
@end
+@interface MGLMapSnapshotter()
+@property (nonatomic) MGLMapSnapshotOptions *options;
+@end
+
@implementation MGLMapSnapshotter {
- std::shared_ptr<mbgl::ThreadPool> mbglThreadPool;
- std::unique_ptr<mbgl::MapSnapshotter> mbglMapSnapshotter;
- std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> snapshotCallback;
+ std::shared_ptr<mbgl::ThreadPool> _mbglThreadPool;
+ std::unique_ptr<mbgl::MapSnapshotter> _mbglMapSnapshotter;
+ std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> _snapshotCallback;
}
- (instancetype)initWithOptions:(MGLMapSnapshotOptions*)options;
{
self = [super init];
if (self) {
+ _options = options;
_loading = false;
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
- mbglThreadPool = mbgl::sharedThreadPool();
+ _mbglThreadPool = mbgl::sharedThreadPool();
std::string styleURL = std::string([options.styleURL.absoluteString UTF8String]);
// Size; taking into account the minimum texture size for OpenGL ES
+ // For non retina screens the ratio is 1:1 MGLSnapshotterMinimumPixelSize
mbgl::Size size = {
- static_cast<uint32_t>(MAX(options.size.width, 64)),
- static_cast<uint32_t>(MAX(options.size.height, 64))
+ static_cast<uint32_t>(MAX(options.size.width, MGLSnapshotterMinimumPixelSize)),
+ static_cast<uint32_t>(MAX(options.size.height, MGLSnapshotterMinimumPixelSize))
};
float pixelRatio = MAX(options.scale, 1);
@@ -73,17 +87,17 @@
cameraOptions.center = MGLLatLngFromLocationCoordinate2D(options.camera.centerCoordinate);
}
cameraOptions.angle = MAX(0, options.camera.heading) * mbgl::util::DEG2RAD;
- cameraOptions.zoom = MAX(0, options.zoom);
+ cameraOptions.zoom = MAX(0, options.zoomLevel);
cameraOptions.pitch = MAX(0, options.camera.pitch);
// Region
- mbgl::optional<mbgl::LatLngBounds> region;
- if (!MGLCoordinateBoundsIsEmpty(options.region)) {
- region = MGLLatLngBoundsFromCoordinateBounds(options.region);
+ mbgl::optional<mbgl::LatLngBounds> coordinateBounds;
+ if (!MGLCoordinateBoundsIsEmpty(options.coordinateBounds)) {
+ coordinateBounds = MGLLatLngBoundsFromCoordinateBounds(options.coordinateBounds);
}
// Create the snapshotter
- mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(*mbglFileSource, *mbglThreadPool, styleURL, size, pixelRatio, cameraOptions, region);
+ _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(*mbglFileSource, *_mbglThreadPool, styleURL, size, pixelRatio, cameraOptions, coordinateBounds);
}
return self;
}
@@ -96,30 +110,30 @@
- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion;
{
if ([self isLoading]) {
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Already started this snapshotter"};
- NSError *error = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo];
- dispatch_async(queue, ^{
- completion(nil, error);
- });
- return;
+ [NSException raise:NSInternalInconsistencyException
+ format:@"Already started this snapshotter."];
}
_loading = true;
dispatch_async(queue, ^{
- snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image) {
+ _snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image) {
_loading = false;
if (mbglError) {
NSString *description = @(mbgl::util::toString(mbglError).c_str());
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
- NSError *error = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo];
+ NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo];
// Dispatch result to origin queue
dispatch_async(queue, ^{
completion(nil, error);
});
} else {
+#if TARGET_OS_IPHONE
+ MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:self.options.scale];
+#else
MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)];
+#endif
// Process image watermark in a work queue
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
@@ -127,20 +141,30 @@
#if TARGET_OS_IPHONE
UIImage *logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
- UIGraphicsBeginImageContext(mglImage.size);
+ UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
[mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
- [logoImage drawInRect:CGRectMake(8, mglImage.size.height - (8 + logoImage.size.height), logoImage.size.width,logoImage.size.height)];
+ [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width,logoImage.size.height)];
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
#else
NSImage *logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]];
- NSImage *compositedImage = mglImage;
+ NSImage *sourceImage = mglImage;
+
+ NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
+ NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
+ NSImage *compositedImage = nil;
+ NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
+ context:nil
+ hints:nil];
+ compositedImage = [[NSImage alloc] initWithSize:targetSize];
[compositedImage lockFocus];
- [logoImage drawInRect:CGRectMake(8, 8, logoImage.size.width,logoImage.size.height)];
+ [sourceImageRep drawInRect: targetFrame];
+ [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width,logoImage.size.height)];
[compositedImage unlockFocus];
+
#endif
// Dispatch result to origin queue
@@ -150,14 +174,14 @@
});
}
});
- mbglMapSnapshotter->snapshot(snapshotCallback->self());
+ _mbglMapSnapshotter->snapshot(_snapshotCallback->self());
});
}
- (void)cancel;
{
- snapshotCallback.reset();
- mbglMapSnapshotter.reset();
+ _snapshotCallback.reset();
+ _mbglMapSnapshotter.reset();
}
@end
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index b3227e1cdf..5c32791c2f 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -47,6 +47,8 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) {
MGLErrorCodeParseStyleFailed = 4,
/** An attempt to load the style failed. */
MGLErrorCodeLoadStyleFailed = 5,
+ /** An error occurred while snapshotting the map. */
+ MGLErrorCodeSnapshotFailed = 6,
};
/** Options for enabling debugging features in an `MGLMapView` instance. */
diff --git a/platform/ios/app/MBXSnapshotsViewController.m b/platform/ios/app/MBXSnapshotsViewController.m
index d26479f085..ab5ad97c90 100644
--- a/platform/ios/app/MBXSnapshotsViewController.m
+++ b/platform/ios/app/MBXSnapshotsViewController.m
@@ -18,27 +18,27 @@
@implementation MBXSnapshotsViewController {
// Top row
- MGLMapSnapshotter* snapshotterTL;
- MGLMapSnapshotter* snapshotterTM;
- MGLMapSnapshotter* snapshotterTR;
+ MGLMapSnapshotter* topLeftSnapshotter;
+ MGLMapSnapshotter* topCenterSnapshotter;
+ MGLMapSnapshotter* topRightSnapshotter;
// Bottom row
- MGLMapSnapshotter* snapshotterBL;
- MGLMapSnapshotter* snapshotterBM;
- MGLMapSnapshotter* snapshotterBR;
+ MGLMapSnapshotter* bottomLeftSnapshotter;
+ MGLMapSnapshotter* bottomCenterSnapshotter;
+ MGLMapSnapshotter* bottomRightSnapshotter;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Start snapshotters
- snapshotterTL = [self startSnapshotterForImageView:_snapshotImageViewTL coordinates:CLLocationCoordinate2DMake(37.7184, -122.4365)];
- snapshotterTM = [self startSnapshotterForImageView:_snapshotImageViewTM coordinates:CLLocationCoordinate2DMake(38.8936, -77.0146)];
- snapshotterTR = [self startSnapshotterForImageView:_snapshotImageViewTR coordinates:CLLocationCoordinate2DMake(-13.1356, -74.2442)];
+ topLeftSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewTL coordinates:CLLocationCoordinate2DMake(37.7184, -122.4365)];
+ topCenterSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewTM coordinates:CLLocationCoordinate2DMake(38.8936, -77.0146)];
+ topRightSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewTR coordinates:CLLocationCoordinate2DMake(-13.1356, -74.2442)];
- snapshotterBL = [self startSnapshotterForImageView:_snapshotImageViewBL coordinates:CLLocationCoordinate2DMake(52.5072, 13.4247)];
- snapshotterBM = [self startSnapshotterForImageView:_snapshotImageViewBM coordinates:CLLocationCoordinate2DMake(60.2118, 24.6754)];
- snapshotterBR = [self startSnapshotterForImageView:_snapshotImageViewBR coordinates:CLLocationCoordinate2DMake(31.2780, 121.4286)];
+ bottomLeftSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewBL coordinates:CLLocationCoordinate2DMake(52.5072, 13.4247)];
+ bottomCenterSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewBM coordinates:CLLocationCoordinate2DMake(60.2118, 24.6754)];
+ bottomRightSnapshotter = [self startSnapshotterForImageView:_snapshotImageViewBR coordinates:CLLocationCoordinate2DMake(31.2780, 121.4286)];
}
- (MGLMapSnapshotter*) startSnapshotterForImageView:(UIImageView*) imageView coordinates:(CLLocationCoordinate2D) coordinates {
@@ -46,8 +46,8 @@
MGLMapCamera* mapCamera = [[MGLMapCamera alloc] init];
mapCamera.pitch = 20;
mapCamera.centerCoordinate = coordinates;
- MGLMapSnapshotOptions* options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"] camera:mapCamera size:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
- options.zoom = 10;
+ MGLMapSnapshotOptions* options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:[MGLStyle satelliteStreetsStyleURL] camera:mapCamera size:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
+ options.zoomLevel = 10;
// Create and start the snapshotter
MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
diff --git a/platform/ios/src/UIImage+MGLAdditions.h b/platform/ios/src/UIImage+MGLAdditions.h
index 3c179d6324..22bb740242 100644
--- a/platform/ios/src/UIImage+MGLAdditions.h
+++ b/platform/ios/src/UIImage+MGLAdditions.h
@@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable instancetype)initWithMGLStyleImage:(const mbgl::style::Image *)styleImage;
-- (nullable instancetype)initWithMGLPremultipliedImage:(const mbgl::PremultipliedImage&&)mbglImage;
+- (nullable instancetype)initWithMGLPremultipliedImage:(const mbgl::PremultipliedImage&&)mbglImage scale:(CGFloat)scale;
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier;
diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm
index 7cf1ed9bcc..8ab1d5c259 100644
--- a/platform/ios/src/UIImage+MGLAdditions.mm
+++ b/platform/ios/src/UIImage+MGLAdditions.mm
@@ -22,14 +22,14 @@
return self;
}
-- (nullable instancetype)initWithMGLPremultipliedImage:(const mbgl::PremultipliedImage&&)mbglImage
+- (nullable instancetype)initWithMGLPremultipliedImage:(const mbgl::PremultipliedImage&&)mbglImage scale:(CGFloat)scale
{
CGImageRef image = CGImageFromMGLPremultipliedImage(mbglImage.clone());
if (!image) {
return nil;
}
- self = [self initWithCGImage:image scale:1.0 orientation:UIImageOrientationUp];
+ self = [self initWithCGImage:image scale:scale orientation:UIImageOrientationUp];
CGImageRelease(image);
return self;
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 9a53ba9d4b..3243838848 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -128,7 +128,7 @@
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
- <menuItem title="Save snapshot" id="vjX-0E-kLO">
+ <menuItem title="Export Image…" id="vjX-0E-kLO">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="takeSnapshot:" target="-1" id="H06-sU-n4U"/>
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 36ca4ad228..feef53062b 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -162,50 +162,49 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
- (IBAction)takeSnapshot:(id)sender {
MGLMapCamera *camera = self.mapView.camera;
- MGLMapSnapshotOptions* options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:self.mapView.styleURL camera:camera size:self.mapView.bounds.size];
- options.zoom = self.mapView.zoomLevel;
+ MGLMapSnapshotOptions *options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:self.mapView.styleURL camera:camera size:self.mapView.bounds.size];
+ options.zoomLevel = self.mapView.zoomLevel;
// Create and start the snapshotter
snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
- [snapshotter startWithCompletionHandler: ^(NSImage *image, NSError *error) {
+ [snapshotter startWithCompletionHandler:^(NSImage *image, NSError *error) {
if (error) {
- NSLog(@"Could not load snapshot: %@", [error localizedDescription]);
+ NSLog(@"Could not load snapshot: %@", error.localizedDescription);
} else {
- NSWindow* window = [[[self windowControllers] objectAtIndex:0] window];
-
- NSString* newName = [[@"snapshot" stringByDeletingPathExtension] stringByAppendingPathExtension:@"png"];
-
// Set the default name for the file and show the panel.
- NSSavePanel* panel = [NSSavePanel savePanel];
- [panel setNameFieldStringValue:newName];
- [panel beginSheetModalForWindow:window completionHandler:^(NSInteger result){
+ NSSavePanel *panel = [NSSavePanel savePanel];
+ panel.nameFieldStringValue = [self.mapView.styleURL.lastPathComponent.stringByDeletingPathExtension stringByAppendingPathExtension:@"png"];
+ panel.allowedFileTypes = [@[(NSString *)kUTTypePNG] arrayByAddingObjectsFromArray:[NSBitmapImageRep imageUnfilteredTypes]];
+
+ [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
// Write the contents in the new format.
- NSURL* fileURL = [panel URL];
+ NSURL *fileURL = panel.URL;
- NSBitmapImageRep *bitmapRep = nil;
- for (NSImageRep *imageRep in [image representations]) {
- if ([imageRep isKindOfClass:[NSBitmapImageRep class]]){
+ NSBitmapImageRep *bitmapRep;
+ for (NSImageRep *imageRep in image.representations) {
+ if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapRep = (NSBitmapImageRep *)imageRep;
break; // stop on first bitmap rep we find
}
}
if (!bitmapRep) {
- bitmapRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
-
+ bitmapRep = [NSBitmapImageRep imageRepWithData:image.TIFFRepresentation];
}
- NSString *extension = [[fileURL pathExtension] lowercaseString];
- NSBitmapImageFileType fileType;
- if ([extension isEqualToString:@"png"]) {
+ CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileURL.pathExtension, NULL /* inConformingToUTI */);
+ NSBitmapImageFileType fileType = NSTIFFFileType;
+ if (UTTypeConformsTo(uti, kUTTypePNG)) {
fileType = NSPNGFileType;
- } else if ([extension isEqualToString:@"gif"]) {
- fileType = NSGIFFileType;
- } else if ([extension isEqualToString:@"jpg"] || [extension isEqualToString:@"jpeg"]) {
- fileType = NSJPEGFileType;
- } else {
- fileType = NSTIFFFileType;
+ } else if (UTTypeConformsTo(uti, kUTTypeGIF)) {
+ fileType = NSGIFFileType;
+ } else if (UTTypeConformsTo(uti, kUTTypeJPEG2000)) {
+ fileType = NSJPEG2000FileType;
+ } else if (UTTypeConformsTo(uti, kUTTypeJPEG)) {
+ fileType = NSJPEGFileType;
+ } else if (UTTypeConformsTo(uti, kUTTypeBMP)) {
+ fileType = NSBitmapImageFileTypeBMP;
}
NSData *imageData = [bitmapRep representationUsingType:fileType properties:@{}];