summaryrefslogtreecommitdiff
path: root/platform/android/src
diff options
context:
space:
mode:
authorTobrun Van Nuland <tobrun.van.nuland@gmail.com>2016-07-27 18:39:32 +0200
committerTobrun <tobrun.van.nuland@gmail.com>2016-08-03 14:55:45 -0400
commit6016b2981e73be81f6a74a789ffabb51b7e91700 (patch)
tree4a3a4f50978dbfd2ff9ca304ce7c8638819a973d /platform/android/src
parent9b871a9a0fcbbeb40cec07fc976cbdbaebf00856 (diff)
downloadqtlocation-mapboxgl-6016b2981e73be81f6a74a789ffabb51b7e91700.tar.gz
[android] SurfaceView compatible snapshot api
[android] #5587 - snapshot API on surface view, create Bitmap with a ByteBuffer [android] #5587 - write bitmap to external storage PreMultipliedImage approach callback implemented clean up code introduce bitmap reuse cleanup renaming surfaceContent to bitmap
Diffstat (limited to 'platform/android/src')
-rwxr-xr-xplatform/android/src/jni.cpp12
-rw-r--r--platform/android/src/jni.hpp1
-rwxr-xr-xplatform/android/src/native_map_view.cpp33
-rwxr-xr-xplatform/android/src/native_map_view.hpp3
4 files changed, 48 insertions, 1 deletions
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 5fc29f4c29..5907a0ff9d 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -45,6 +45,7 @@ std::string androidRelease;
jni::jmethodID* onInvalidateId = nullptr;
jni::jmethodID* onMapChangedId = nullptr;
jni::jmethodID* onFpsChangedId = nullptr;
+jni::jmethodID* onSnapshotReadyId = nullptr;
jni::jclass* latLngClass = nullptr;
jni::jmethodID* latLngConstructorId = nullptr;
@@ -1172,6 +1173,13 @@ void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
}
}
+void nativeScheduleTakeSnapshot(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Error(mbgl::Event::JNI, "nativeRenderToOffscreen");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
+ nativeMapView->scheduleTakeSnapshot();
+}
+
// Offline calls begin
jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) {
@@ -1706,6 +1714,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
onInvalidateId = &jni::GetMethodID(env, nativeMapViewClass, "onInvalidate", "()V");
onMapChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onMapChanged", "(I)V");
onFpsChangedId = &jni::GetMethodID(env, nativeMapViewClass, "onFpsChanged", "(D)V");
+ onSnapshotReadyId = &jni::GetMethodID(env, nativeMapViewClass, "onSnapshotReady","([B)V");
#define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
@@ -1786,7 +1795,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeAddSource, "(JLjava/lang/String;Lcom/mapbox/mapboxsdk/style/sources/Source;)V"),
MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V")
+ MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V"),
+ MAKE_NATIVE_METHOD(nativeScheduleTakeSnapshot, "(J)V")
);
// Offline begin
diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp
index 57f84f0ccc..0810ee656d 100644
--- a/platform/android/src/jni.hpp
+++ b/platform/android/src/jni.hpp
@@ -19,6 +19,7 @@ extern std::string androidRelease;
extern jmethodID onInvalidateId;
extern jmethodID onMapChangedId;
extern jmethodID onFpsChangedId;
+extern jmethodID onSnapshotReadyId;
extern bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName);
extern void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 0b849976eb..578e5d0033 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -194,6 +194,35 @@ void NativeMapView::render() {
map->render();
+ if(snapshot){
+ snapshot = false;
+
+ // take snapshot
+ const unsigned int w = fbWidth;
+ const unsigned int h = fbHeight;
+ mbgl::PremultipliedImage image { w, h };
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
+ const size_t stride = image.stride();
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t *rgba = image.data.get();
+ for (int i = 0, j = h - 1; i < j; i++, j--) {
+ std::memcpy(tmp.get(), rgba + i * stride, stride);
+ std::memcpy(rgba + i * stride, rgba + j * stride, stride);
+ std::memcpy(rgba + j * stride, tmp.get(), stride);
+ }
+
+ // encode and convert to jbytes
+ std::string string = encodePNG(image);
+ jbyteArray arr = env->NewByteArray(string.length());
+ env->SetByteArrayRegion(arr,0,string.length(),(jbyte*)string.c_str());
+
+ // invoke Mapview#OnSnapshotReady
+ env->CallVoidMethod(obj, onSnapshotReadyId, arr);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ }
+ }
+
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
if (!eglSwapBuffers(display, surface)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapBuffers() returned error %d",
@@ -436,6 +465,10 @@ void NativeMapView::destroySurface() {
}
}
+void NativeMapView::scheduleTakeSnapshot() {
+ snapshot = true;
+}
+
// Speed
/*
typedef enum {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 40cb012b0b..9b5af76dfe 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -49,6 +49,8 @@ public:
mbgl::EdgeInsets getInsets() { return insets;}
void setInsets(mbgl::EdgeInsets insets_);
+ void scheduleTakeSnapshot();
+
private:
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);
@@ -79,6 +81,7 @@ private:
bool firstTime = false;
bool fpsEnabled = false;
bool sizeChanged = false;
+ bool snapshot = false;
double fps = 0.0;
int width = 0;