10#include <android/bitmap.h>
15#include "third_party/skia/include/codec/SkCodecAnimation.h"
24AndroidImageGenerator::AndroidImageGenerator(sk_sp<SkData>
data)
25 : data_(
std::move(
data)), image_info_(SkImageInfo::MakeUnknown(-1, -1)) {}
27const SkImageInfo& AndroidImageGenerator::GetInfo() {
28 header_decoded_latch_.Wait();
32unsigned int AndroidImageGenerator::GetFrameCount()
const {
36unsigned int AndroidImageGenerator::GetPlayCount()
const {
41 unsigned int frame_index) {
44 .disposal_method = SkCodecAnimation::DisposalMethod::kKeep};
47SkISize AndroidImageGenerator::GetScaledDimensions(
float desired_scale) {
48 return GetInfo().dimensions();
51bool AndroidImageGenerator::GetPixels(
const SkImageInfo& info,
54 unsigned int frame_index,
55 std::optional<unsigned int> prior_frame) {
56 fully_decoded_latch_.Wait();
58 if (!software_decoded_data_) {
62 if (kRGBA_8888_SkColorType != info.colorType()) {
66 switch (info.alphaType()) {
67 case kOpaque_SkAlphaType:
68 if (kOpaque_SkAlphaType != GetInfo().alphaType()) {
72 case kPremul_SkAlphaType:
82 memcpy(pixels, software_decoded_data_->data(),
83 software_decoded_data_->size());
87void AndroidImageGenerator::DecodeImage() {
90 header_decoded_latch_.Signal();
91 fully_decoded_latch_.Signal();
94void AndroidImageGenerator::DoDecodeImage() {
106 jobject direct_buffer =
107 env->NewDirectByteBuffer(
const_cast<void*
>(data_->data()), data_->size());
109 auto bitmap = std::make_unique<fml::jni::ScopedJavaGlobalRef<jobject>>(
111 g_decode_image_method, direct_buffer,
112 reinterpret_cast<jlong
>(
this)));
115 if (bitmap->is_null()) {
119 AndroidBitmapInfo info;
120 [[maybe_unused]]
int status;
121 if ((status = AndroidBitmap_getInfo(env, bitmap->obj(), &info)) < 0) {
122 FML_DLOG(ERROR) <<
"Failed to get bitmap info, status=" << status;
125 FML_DCHECK(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);
130 if ((status = AndroidBitmap_lockPixels(env, bitmap->obj(), &pixel_lock)) <
132 FML_DLOG(ERROR) <<
"Failed to lock pixels, error=" << status;
136 SkData::ReleaseProc on_release = [](
const void* ptr,
void* context) ->
void {
140 AndroidBitmap_unlockPixels(env, bitmap->
obj());
144 software_decoded_data_ = SkData::MakeWithProc(
145 pixel_lock, info.width * info.height *
sizeof(uint32_t), on_release,
149bool AndroidImageGenerator::Register(JNIEnv* env) {
151 env, env->FindClass(
"io/flutter/embedding/engine/FlutterJNI"));
156 "(Ljava/nio/ByteBuffer;J)Landroid/graphics/Bitmap;");
159 static const JNINativeMethod header_decoded_method = {
160 .name =
"nativeImageHeaderCallback",
161 .signature =
"(JII)V",
162 .fnPtr =
reinterpret_cast<void*
>(
163 &AndroidImageGenerator::NativeImageHeaderCallback),
168 <<
"Failed to register FlutterJNI.nativeImageHeaderCallback method";
175std::shared_ptr<ImageGenerator> AndroidImageGenerator::MakeFromData(
178 std::shared_ptr<AndroidImageGenerator> generator(
182 task_runner, [generator]() { generator->DecodeImage(); });
184 if (generator->IsValidImageData()) {
191void AndroidImageGenerator::NativeImageHeaderCallback(JNIEnv* env,
193 jlong generator_address,
199 generator->image_info_ = SkImageInfo::Make(
200 width,
height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
201 generator->header_decoded_latch_.
Signal();
204bool AndroidImageGenerator::IsValidImageData() {
210 return GetInfo().height() != -1;
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
static jmethodID g_decode_image_method
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
static fml::jni::ScopedJavaGlobalRef< jclass > * g_flutter_jni_class
JNIEnv * AttachCurrentThread()
bool CheckException(JNIEnv *env)
Info about a single frame in the context of a multi-frame image, useful for animation and blending.
std::optional< unsigned int > required_frame
std::shared_ptr< const fml::Mapping > data