[darwin][ios][macos] map snapshotter - add MGLMapSnapshot wrapper
This commit is contained in:
committed by
Ivo van Dongen
parent
dde1a92291
commit
3cdb249c70
@@ -69,23 +69,42 @@ MGL_EXPORT
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
An image generated by a snapshotter object.
|
||||
*/
|
||||
@interface MGLMapSnapshot : NSObject
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
/**
|
||||
A block to processes the result or error of a snapshot request.
|
||||
|
||||
@param snapshot The `UIImage` that was generated or `nil` if an error occurred.
|
||||
@param error The error that occured or `nil` when successful.
|
||||
Converts the specified map coordinate to a point in the coordinate space of the image.
|
||||
*/
|
||||
typedef void (^MGLMapSnapshotCompletionHandler)(UIImage* _Nullable snapshot, NSError* _Nullable error);
|
||||
- (CGPoint)pointForCoordinate:(CLLocationCoordinate2D)coordinate;
|
||||
|
||||
/**
|
||||
The image of the map’s content.
|
||||
*/
|
||||
@property(nonatomic, readonly) UIImage *image;
|
||||
#else
|
||||
/**
|
||||
Converts the specified map coordinate to a point in the coordinate space of the image.
|
||||
*/
|
||||
- (NSPoint)pointForCoordinate:(CLLocationCoordinate2D)coordinate;
|
||||
|
||||
/**
|
||||
The image of the map’s content.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSImage *image;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
A block to processes the result or error of a snapshot request.
|
||||
|
||||
@param snapshot The `NSImage` that was generated or `nil` if an error occurred.
|
||||
@param error The eror that occured or `nil` when succesful.
|
||||
@param snapshot The `MGLMapSnapshot` that was generated or `nil` if an error occurred.
|
||||
@param error The error that occured or `nil` when successful.
|
||||
*/
|
||||
typedef void (^MGLMapSnapshotCompletionHandler)(NSImage* _Nullable snapshot, NSError* _Nullable error);
|
||||
#endif
|
||||
typedef void (^MGLMapSnapshotCompletionHandler)(MGLMapSnapshot* _Nullable snapshot, NSError* _Nullable error);
|
||||
|
||||
/**
|
||||
An immutable utility object for capturing map-based images.
|
||||
@@ -93,20 +112,18 @@ typedef void (^MGLMapSnapshotCompletionHandler)(NSImage* _Nullable snapshot, NSE
|
||||
### Example
|
||||
|
||||
```swift
|
||||
var camera = MGLMapCamera()
|
||||
camera.centerCoordinate = CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365)
|
||||
camera.pitch = 20
|
||||
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), fromDistance: 100, pitch: 20, heading: 0)
|
||||
|
||||
var options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
|
||||
let 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
|
||||
}
|
||||
let snapshotter = MGLMapSnapshotter(options: options)
|
||||
snapshotter.start { (snapshot, error) in
|
||||
if error != nil {
|
||||
// error handler
|
||||
} else {
|
||||
// image handler
|
||||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
@@ -141,7 +158,8 @@ MGL_EXPORT
|
||||
/**
|
||||
The zoom level.
|
||||
|
||||
The default zoom level is 0. This overwrites the camera zoom level if set.
|
||||
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 zoomLevel;
|
||||
|
||||
@@ -169,7 +187,7 @@ MGL_EXPORT
|
||||
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.
|
||||
*/
|
||||
@property (nonatomic) NSURL* styleURL;
|
||||
@property (nonatomic, nullable) NSURL *styleURL;
|
||||
|
||||
/**
|
||||
The size of the output image, measured in points.
|
||||
|
||||
@@ -49,6 +49,33 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
|
||||
@end
|
||||
|
||||
@interface MGLMapSnapshot()
|
||||
- (instancetype)initWithImage:(nullable MGLImage *)image scale:(CGFloat)scale pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn;
|
||||
|
||||
@property (nonatomic) CGFloat scale;
|
||||
@end
|
||||
|
||||
@implementation MGLMapSnapshot {
|
||||
mbgl::MapSnapshotter::PointForFn _pointForFn;
|
||||
}
|
||||
- (instancetype)initWithImage:(nullable MGLImage *)image scale:(CGFloat)scale pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_pointForFn = std::move(pointForFn);
|
||||
_scale = scale;
|
||||
_image = image;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CGPoint)pointForCoordinate:(CLLocationCoordinate2D)coordinate
|
||||
{
|
||||
mbgl::ScreenCoordinate sc = _pointForFn(MGLLatLngFromLocationCoordinate2D(coordinate));
|
||||
return CGPointMake(sc.x * self.scale, sc.y * self.scale);
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MGLMapSnapshotter()
|
||||
@property (nonatomic) MGLMapSnapshotOptions *options;
|
||||
@end
|
||||
@@ -117,7 +144,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
_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, mbgl::MapSnapshotter::PointForFn pointForFn) {
|
||||
_loading = false;
|
||||
if (mbglError) {
|
||||
NSString *description = @(mbgl::util::toString(mbglError).c_str());
|
||||
@@ -171,7 +198,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
|
||||
// Dispatch result to origin queue
|
||||
dispatch_async(queue, ^{
|
||||
completion(compositedImage, nil);
|
||||
MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage scale:self.options.scale pointForFn:pointForFn];
|
||||
completion(snapshot, nil);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -189,7 +217,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
- (NSURL *)styleURL
|
||||
{
|
||||
NSString *styleURLString = @(_mbglMapSnapshotter->getStyleURL().c_str());
|
||||
return styleURLString && styleURLString.length > 0 ? [NSURL URLWithString:styleURLString] : nil;
|
||||
return styleURLString.length ? [NSURL URLWithString:styleURLString] : nil;
|
||||
}
|
||||
|
||||
- (void)setStyleURL:(NSURL *)url
|
||||
|
||||
@@ -278,6 +278,24 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
|
||||
//#-end-example-code
|
||||
}
|
||||
|
||||
func testMGLMapSnapshotter() {
|
||||
//#-example-code
|
||||
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), fromDistance: 100, pitch: 20, heading: 0)
|
||||
|
||||
let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
|
||||
options.zoomLevel = 10
|
||||
|
||||
let snapshotter = MGLMapSnapshotter(options: options)
|
||||
snapshotter.start { (snapshot, error) in
|
||||
if error != nil {
|
||||
// error handler
|
||||
} else {
|
||||
// image handler
|
||||
}
|
||||
}
|
||||
//#-end-example-code
|
||||
}
|
||||
|
||||
// For testMGLMapView().
|
||||
func myCustomFunction() {}
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@
|
||||
|
||||
// Create and start the snapshotter
|
||||
MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
|
||||
[snapshotter startWithCompletionHandler: ^(UIImage *image, NSError *error) {
|
||||
[snapshotter startWithCompletionHandler: ^(MGLMapSnapshot* snapshot, NSError *error) {
|
||||
if (error) {
|
||||
NSLog(@"Could not load snapshot: %@", [error localizedDescription]);
|
||||
} else {
|
||||
imageView.image = image;
|
||||
imageView.image = snapshot.image;
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
|
||||
|
||||
// Create and start the snapshotter
|
||||
snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
|
||||
[snapshotter startWithCompletionHandler:^(NSImage *image, NSError *error) {
|
||||
[snapshotter startWithCompletionHandler:^(MGLMapSnapshot *snapshot, NSError *error) {
|
||||
if (error) {
|
||||
NSLog(@"Could not load snapshot: %@", error.localizedDescription);
|
||||
} else {
|
||||
@@ -182,7 +182,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
|
||||
NSURL *fileURL = panel.URL;
|
||||
|
||||
NSBitmapImageRep *bitmapRep;
|
||||
for (NSImageRep *imageRep in image.representations) {
|
||||
for (NSImageRep *imageRep in snapshot.image.representations) {
|
||||
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
|
||||
bitmapRep = (NSBitmapImageRep *)imageRep;
|
||||
break; // stop on first bitmap rep we find
|
||||
@@ -190,7 +190,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
|
||||
}
|
||||
|
||||
if (!bitmapRep) {
|
||||
bitmapRep = [NSBitmapImageRep imageRepWithData:image.TIFFRepresentation];
|
||||
bitmapRep = [NSBitmapImageRep imageRepWithData:snapshot.image.TIFFRepresentation];
|
||||
}
|
||||
|
||||
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileURL.pathExtension, NULL /* inConformingToUTI */);
|
||||
|
||||
Reference in New Issue
Block a user