summaryrefslogtreecommitdiff
path: root/platform/android/src/bitmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/src/bitmap.cpp')
-rw-r--r--platform/android/src/bitmap.cpp107
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