【问题标题】:Sending Bitmap to Flutter from Android Platform从 Android 平台发送 Bitmap 到 Flutter
【发布时间】:2019-01-02 02:53:09
【问题描述】:

我正在创建一个图像处理应用程序,因此首先使用 android 平台 api 处理位图广告,然后将其发送到颤振。 我正在使用下面的代码将位图转换为字节 []

  Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
        ByteBuffer allocate = ByteBuffer.allocate(bitmap.getByteCount());
        bitmap.copyPixelsToBuffer(allocate);
        byte[] array = allocate.array();

然后使用方法通道作为 Uint8List 将其发送到颤振 但是当我把它读为 Image.memory() 时。它给了我错误

解码图像失败。数据无效,或者使用不受支持的格式进行编码。 下面是我的主要活动的代码

package com.rahul.flutterappdomain;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;

import com.asksira.bsimagepicker.BSImagePicker;
import com.asksira.bsimagepicker.Utils;

import java.nio.ByteBuffer;

import io.flutter.app.FlutterFragmentActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class ActivityMain extends FlutterFragmentActivity implements BSImagePicker.OnSingleImageSelectedListener{
    private static final String TAG = "DomainFilterFlutterApp";
    private static final String CHANNEL = "com.rummy.io/filter";
    MethodChannel methodChannel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        methodChannel = new MethodChannel(getFlutterView(), CHANNEL);
        methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                if (methodCall.method.equals("openImagePicker")) {
                    showImagePickerDialog();
                    result.success(null);
                }

            }
        });
    }

    private void showImagePickerDialog() {
        String providerAuthority = "com.rahul.ffd.fileprovider";
        BSImagePicker singleSelectionPicker = new BSImagePicker.Builder(providerAuthority)
                .setSpanCount(4)
                .setGridSpacing(Utils.dp2px(4))
                .setPeekHeight(Utils.dp2px(360))
                .build();


        singleSelectionPicker.show(getSupportFragmentManager(), "picker");

    }

    @Override
    public void onSingleImageSelected(Uri uri) {
        Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
        ByteBuffer allocate = ByteBuffer.allocate(bitmap.getByteCount());
        bitmap.copyPixelsToBuffer(allocate);
        byte[] array = allocate.array();

        methodChannel.invokeMethod("setImage", array);
        Log.d(TAG, "onSingleImageSelected: ------------");

    }
}

和我的 dart 文件的代码

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'colors.dart';
//import 'package:image_picker/image_picker.dart';

void main(){runApp(MyApp());}

class MyApp extends StatefulWidget {
  static const platform = const MethodChannel('com.rummy.io/filter');
  String _image;
  Uint8List _image_data ;

  Future<Null> getImage() async {
    platform.invokeMethod("openImagePicker");
  }

  @override
  State<StatefulWidget> createState() {
    var myAppState = MyAppState();
    platform.setMethodCallHandler((MethodCall call) {
      switch (call.method) {
        case 'setImage':
          print('setState');
          myAppState.makeState(call.arguments);
          print('setState');
      }
    });
    return myAppState;
  }
}



class MyAppState extends State<MyApp> {
  void makeState( Uint8List imgData) {
    setState(() {

      widget._image_data = imgData;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: _mAppTheme,
      home: Scaffold(
        appBar: AppBar(
          actions: <Widget>[
            IconButton(
              onPressed: () {},
              icon: Icon(Icons.save),
            )
          ],
        ),
        body: _mBody(widget._image_data),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            widget.getImage();
          },
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.elliptical(12.0, 13.0))),
          child: Icon(Icons.image),
        ),
      ),
    );
  }
  double _discreteValue = 0.0;
  double _discreteValue2 = 0.0;

  Widget _mBody(Uint8List imgData) {

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,

        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Card(

//          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
              child: imgData == null
                  ? Image.asset(
                'images/beauty.jpg',
                fit: BoxFit.contain,

              )
                  : /*Image.file(
                File(img),
                fit: BoxFit.contain,)*/
              Image.memory(imgData),


            ),
          ),
          new Slider(
              value: _discreteValue,
              min: 0.0,
              max: 200.0,
              divisions: 10,
              activeColor: Colors.greenAccent,
              label: '${_discreteValue.round()}',
              onChanged: (double value) {
                setState(() {
                  _discreteValue = value;
                });}),
          new Slider(
              value: _discreteValue2,
              min: 0.0,
              max: 200.0,
              divisions: 10,
              activeColor: Colors.greenAccent,
              label: '${_discreteValue2.round()}',
              onChanged: (double value) {
                setState(() {
                  _discreteValue2 = value;
                });}),
        ],
      ),
    );
  }

/*  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);
    setState(() {
      _image = image;
    });
  }*/
}



final ThemeData _mAppTheme = _buildAppTheme();
ThemeData _buildAppTheme() {
  final ThemeData base = ThemeData.light();
  return base.copyWith(
    accentColor: kShrineBrown900,
    primaryColor: kShrinePink100,
    buttonColor: kShrinePink100,
    scaffoldBackgroundColor: kShrineBackgroundWhite,
    cardColor: kShrineBackgroundWhite,
    textSelectionColor: kShrinePink100,
    errorColor: kShrineErrorRed,
  );
}

【问题讨论】:

  • 您是从 Google 相册应用发送图片吗?
  • 不,我正在使用自定义图像选择器 BSImagePicker,但这没关系,因为我正在获取图像的 uri,然后使用 BitmapFactory 对其进行解码
  • 我觉得在 Flutter 和 Android 之间传递 Image 路径比较好。
  • 您是否尝试将图像保存到缓存并在 Flutter 中读取?

标签: android dart flutter


【解决方案1】:

我收到了同样的错误信息。问题是您在 Java 代码中以错误的方式解码位图图像。这是可行的解决方案

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bitmap.recycle();

// And return byteArray through your MethodChannel

【讨论】:

    【解决方案2】:

    您不能将原始位图传递给Image.memory,因为它不包含足够的信息,尤其是宽度和高度。 Image 构造函数需要可识别的文件格式:JPEG、PNG、GIF、动画 GIF、WebP、动画 WebP、BMP 和 WBMP。

    如果您在此处打开的文件:

    Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
    

    是上述格式之一,然后不要将其解码为 Android 位图,而是将其逐字读取到字节数组中,通过通道发送并将其用作 Image 构造函数的输入。 (或者,如果可以的话,只需将文件路径传回 Dart 并使用 dart:io 并在必要时使用 path_provider 来读取文件。)

    如果您确实需要将原始位图传递给 Image,那么最简单的方法是预先添加一个 Windows 位图 (BMP) 标头。有一个示例 here 用于不寻常的原始位图格式。您的甚至不需要索引颜色图,因为您几乎可以肯定已经拥有 ARGB 像素(通过检查位图大小(以字节为单位 = 4 * 宽度 * 高度)来测试这一点)。

    【讨论】:

    • 如:不要使用 decodeFile 方法,而只是使用常规的 Java 文件 I/O。但是,正如建议的那样,将文件名传递给 Dart 并使用 dart:io 读取它可能更容易。
    【解决方案3】:

    @Ihor Klimov 回答的更多细节

    我通过以下方式将指纹设备中的Java位图转换为:

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    fingerBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] byteArray = stream.toByteArray();
    fingerBitmap.recycle();
    

    然后在 Flutter Dart 中我只使用

    Uint8List fingerImages;
    
      void mapFingerImage(dynamic imageBytes) {
        setState(() {
          fingerImages = imageBytes;
        });
      }
        Image.memory(fingerImages,
                      width: 100,
                      height: 100,
                       fit: BoxFit.contain,)
    

    【讨论】:

      猜你喜欢
      • 2019-05-31
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 2020-03-13
      相关资源
      最近更新 更多