diff options
author | Wilhelm Berg <wb@BergWerk-GIS.at> | 2018-09-12 15:07:57 +0200 |
---|---|---|
committer | Wilhelm Berg <wb@BergWerk-GIS.at> | 2018-09-12 15:07:57 +0200 |
commit | 98b34cb0dbf5c50d7f319724c93021418140b15f (patch) | |
tree | 11cd51f86b5c672dda6bfe087f40f77df1553971 /platform/android/src/bitmap.cpp | |
parent | ee17d79f9420eb859303d977955454dacc470db6 (diff) | |
parent | 079ba0209ed383c15123902f0810e658c2b0abf4 (diff) | |
download | qtlocation-mapboxgl-98b34cb0dbf5c50d7f319724c93021418140b15f.tar.gz |
Merge remote-tracking branch 'origin' into bwg-vs2017upstream/bwg-vs2017
# Conflicts:
# cmake/mason-dependencies.cmake
Diffstat (limited to 'platform/android/src/bitmap.cpp')
-rw-r--r-- | platform/android/src/bitmap.cpp | 107 |
1 files changed, 46 insertions, 61 deletions
diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 0d3670b666..eb7c676b12 100644 --- a/platform/android/src/bitmap.cpp +++ b/platform/android/src/bitmap.cpp @@ -8,13 +8,14 @@ namespace android { class PixelGuard { public: - PixelGuard(jni::JNIEnv& env_, jni::Object<Bitmap> bitmap_) : env(env_), bitmap(bitmap_) { + PixelGuard(jni::JNIEnv& env_, const jni::Object<Bitmap>& bitmap_) : env(env_), bitmap(bitmap_) { const int result = AndroidBitmap_lockPixels(&env, jni::Unwrap(*bitmap), reinterpret_cast<void**>(&address)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { throw std::runtime_error("bitmap decoding: could not lock pixels"); } } + ~PixelGuard() { const int result = AndroidBitmap_unlockPixels(&env, jni::Unwrap(*bitmap)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { @@ -26,58 +27,68 @@ public: return address; } - const auto* get() const { - return address; - } - private: jni::JNIEnv& env; - jni::Object<Bitmap> bitmap; + const jni::Object<Bitmap>& bitmap; uint8_t* address; }; -void Bitmap::Config::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Config>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Bitmap::Config> Bitmap::Config::_class; - -jni::Object<Bitmap::Config> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { +jni::Local<jni::Object<Bitmap::Config>> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto& _class = jni::Class<Config>::Singleton(env); switch (value) { case ALPHA_8: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ALPHA_8")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ALPHA_8")); case ARGB_4444: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ARGB_4444")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_4444")); case ARGB_8888: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ARGB_8888")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_8888")); case RGB_565: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "RGB_565")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "RGB_565")); default: throw std::runtime_error("invalid enum value for Bitmap.Config"); } } void Bitmap::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Bitmap>::Find(env).NewGlobalRef(env).release(); - Config::registerNative(env); + jni::Class<Bitmap>::Singleton(env); + jni::Class<Bitmap::Config>::Singleton(env); } -jni::Class<Bitmap> Bitmap::_class; +jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env, + jni::jint width, + jni::jint height, + const jni::Object<Config>& config) { + static auto& _class = jni::Class<Bitmap>::Singleton(env); + static auto method = _class.GetStaticMethod<jni::Object<Bitmap> (jni::jint, jni::jint, jni::Object<Config>)>(env, "createBitmap"); -jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, - jni::jint width, - jni::jint height, - jni::Object<Config> config) { - using Signature = jni::Object<Bitmap>(jni::jint, jni::jint, jni::Object<Config>); - auto method = _class.GetStaticMethod<Signature>(env, "createBitmap"); return _class.Call(env, method, width, height, config); } -jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { +PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) { + AndroidBitmapInfo info; + const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info); + if (result != ANDROID_BITMAP_RESULT_SUCCESS) { + throw std::runtime_error("bitmap decoding: couldn't get bitmap info"); + } + if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { + return Bitmap::GetImage(env, Bitmap::Copy(env, bitmap)); + } + + PixelGuard guard(env, bitmap); + + // Copy the Android Bitmap into the PremultipliedImage. + auto pixels = + std::make_unique<uint8_t[]>(info.width * info.height * PremultipliedImage::channels); + for (uint32_t y = 0; y < info.height; y++) { + auto begin = guard.get() + y * info.stride; + std::copy(begin, begin + info.width * PremultipliedImage::channels, + pixels.get() + y * info.width * PremultipliedImage::channels); + } + + return { Size{ info.width, info.height }, std::move(pixels) }; +} + +jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { auto bitmap = CreateBitmap(env, image.size.width, image.size.height, Config::ARGB_8888); AndroidBitmapInfo info; @@ -102,37 +113,11 @@ jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedIm return bitmap; } -PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { - AndroidBitmapInfo info; - const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info); - if (result != ANDROID_BITMAP_RESULT_SUCCESS) { - // TODO: more specific information - throw std::runtime_error("bitmap decoding: couldn't get bitmap info"); - } - - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { - bitmap = Bitmap::Copy(env, bitmap); - } - - const PixelGuard guard(env, bitmap); - - // Copy the Android Bitmap into the PremultipliedImage. - auto pixels = - std::make_unique<uint8_t[]>(info.width * info.height * PremultipliedImage::channels); - for (uint32_t y = 0; y < info.height; y++) { - auto begin = guard.get() + y * info.stride; - std::copy(begin, begin + info.width * PremultipliedImage::channels, - pixels.get() + y * info.width * PremultipliedImage::channels); - } - - return { Size{ info.width, info.height }, std::move(pixels) }; -} +jni::Local<jni::Object<Bitmap>> Bitmap::Copy(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) { + static auto& klass = jni::Class<Bitmap>::Singleton(env); + static auto copy = klass.GetMethod<jni::Object<Bitmap> (jni::Object<Config>, jni::jboolean)>(env, "copy"); -jni::Object<Bitmap> Bitmap::Copy(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { - using Signature = jni::Object<Bitmap>(jni::Object<Config>, jni::jboolean); - auto static method = _class.GetMethod<Signature>(env, "copy"); - auto config = Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888); - return bitmap.Call(env, method, config, (jni::jboolean) false); + return bitmap.Call(env, copy, Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888), jni::jni_false); } } // namespace android |