在 Flutter 中将 CameraImage 转换为 ui.Image
Posted
技术标签:
【中文标题】在 Flutter 中将 CameraImage 转换为 ui.Image【英文标题】:Convert a CameraImage to ui.Image in Flutter 【发布时间】:2020-08-09 04:37:15 【问题描述】:[编辑] 问题似乎是我尝试使用的代码在隔离内不起作用。当我在孤立之外尝试相同的颂歌时,它会起作用。所以可能应该检查flutter github上的问题或submut a nex one。 [edit2] 没有发现问题,只提交了一个:https://github.com/flutter/flutter/issues/55654
我可以使用这段代码(https://gist.github.com/Alby-o/fe87e35bc21d534c8220aed7df028e03)将 CameraImage 转换为 png,然后使用 Image 小部件显示 png,但是 png 转换非常慢。 我想将 CameraImage 转换为 ui.Image ,然后使用 RawImage 小部件来显示它。这听起来可能。但是当我尝试这段代码时,我在 ui.decodeImageFromPixels 行上得到一个错误:
Future<ui.Image> makeUiImage(List<int> pixels,int width,int height)
final c = Completer<ui.Image>();
ui.decodeImageFromPixels(
pixels,
width,
height,
ui.PixelFormat.rgba8888,
c.complete,
);
return c.future;
Future<ui.Image> convertCameraImageToUiImage(CameraImage image) async
int startTime = DateTime.now().millisecondsSinceEpoch;
int time;
imglib.Image img = convertCameraImage(image);
time = DateTime.now().millisecondsSinceEpoch;
print("Converted in "+(time-startTime).toString()+"ms img "+img.toString()+" ("+img.width.toString()+","+img.height.toString()+")");
startTime=time;
ui.Image ret = await makeUiImage(img.getBytes(), image.width, image.height);
return ret;
E/flutter (1194): [错误:flutter/runtime/dart_isolate.cc(915)]
未处理的异常:E/flutter (1194):错误:本机函数 找不到“instantiateImageCodec”(5 个参数)
E/flutter (1194): #0 decodeImageFromPixels.
(dart:ui/painting.dart:1740:36) E/flutter (1194): #1 _futurize
(dart:ui/painting.dart:4296:34) E/flutter (1194): #2
decodeImageFromPixels (dart:ui/painting.dart:1739:37) E/flutter (
1194): #3 makeUiImage
(package:flutterapp/utils/image_converter.dart:37:3) E/flutter (
1194): #4 convertCameraImageToUiImage
(package:flutterapp/utils/image_converter.dart:54:24) E/flutter (
1194): #5 processCameraImageIsolate.
(package:flutterapp/cameraoverlay2.dart:448:5) E/flutter (1194): #6
_RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10) E/flutter (1194): #7 _BufferingStreamSubscription._sendData
(dart:async/stream_impl.dart:338:11) E/flutter (1194): #8
_BufferingStreamSubscription._add (dart:async/stream_impl.dart:265:7) E/flutter (1194): #9 _SyncStreamControllerDispatch._sendData
(dart:async/stream_controller.dart:766:19) E/flutter (1194): #10
_StreamController._add (dart:async/stream_controller.dart:642:7) E/flutter (1194): #11 _StreamController.add
(dart:async/stream_controller.dart:588:5) E/flutter (1194): #12 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
【问题讨论】:
你是在 beta 还是 dev 频道上使用 Flutter?通过查看日志,似乎有一个函数instantiateImageCodec
存在于 Flutter API 中,但尚未本地实现(在特定于平台的代码中)
我正在使用“Flutter 1.12.13+hotfix.9 • channel stable •”,并在 android 8.x 设备上进行测试。代码发生在一个隔离中,以防它有用。
刚刚在隔离外测试了相同的代码,并且可以正常工作,所以它与这段代码在隔离中有关。
【参考方案1】:
以下是来自此链接的代码 sn-p,适用于我: https://github.com/flutter/flutter/issues/26348#issuecomment-694092314
创建一个包含以下方法的类或文件:
/// imgLib -> Image package from https://pub.dartlang.org/packages/image
static Future<List<int>> convertImagetoPng(CameraImage image) async
try
imglib.Image img;
if (image.format.group == ImageFormatGroup.yuv420)
img = _convertYUV420(image);
else if (image.format.group == ImageFormatGroup.bgra8888)
img = _convertBGRA8888(image);
imglib.PngEncoder pngEncoder = new imglib.PngEncoder();
// Convert to png
List<int> png = pngEncoder.encodeImage(img);
return png;
catch (e)
print(">>>>>>>>>>>> ERROR:" + e.toString());
return null;
/// CameraImage BGRA8888 -> PNG
/// Color
static imglib.Image _convertBGRA8888(CameraImage image)
return imglib.Image.fromBytes(
(image.planes[0].bytesPerRow / 4).round(),
image.height,
image.planes[0].bytes,
format: imglib.Format.bgra,
);
/// CameraImage YUV420_888 -> PNG -> Image (compresion:0, filter: none)
/// Black
static imglib.Image _convertYUV420(CameraImage image)
var img = imglib.Image(image.width, image.height); // Create Image buffer
Plane plane = image.planes[0];
const int shift = (0xFF << 24);
// Fill image buffer with plane[0] from YUV420_888
for (int x = 0; x < image.width; x++)
for (int planeOffset = 0;
planeOffset < image.height * image.width;
planeOffset += image.width)
final pixelColor = plane.bytes[planeOffset + x];
// color: 0x FF FF FF FF
// A B G R
// Calculate pixel color
var newVal =
shift | (pixelColor << 16) | (pixelColor << 8) | pixelColor;
img.data[planeOffset + x] = newVal;
return img;
然后在你的方法中使用它来获取 ui.Image
使用comp.future
获取ui.Image
Completer<ui.Image> comp = Completer();
ui.decodeImageFromList(
await convertImagetoPng(cameraImage),
(result)
comp.complete(result);
);
【讨论】:
以上是关于在 Flutter 中将 CameraImage 转换为 ui.Image的主要内容,如果未能解决你的问题,请参考以下文章
Flutter小记4Android手动设置Camera焦点没效果的解决方案&&CameraImage转YUV或RGBA要注意!
Flutter-如何在flutter的整个应用程序生命周期中将数据保存在内存中?