My purpose is stream to a websocket.
Firstly i need the camera data. I used startImageStream func for that. This func return image as yuv format. I found something about yuv to image widget but i couldnt convert it to base 64.
The question is how can i convert this yuv image data to base64 ? Or this is bad way to make a stream with flutter.
controller.startImageStream((image) {
// convert image here
// assuming it's converted
final imageBytes = <int>[];
final encodedImage = base64.encode(imageBytes);
});
as for yuv->rgb conversion, you can do something like this (code copied from https://gist.github.com/Alby-o/fe87e35bc21d534c8220aed7df028e03):
// imgLib -> Image package from https://pub.dartlang.org/packages/image
import 'package:image/image.dart' as imglib;
import 'package:camera/camera.dart';
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
imglib.Image _convertBGRA8888(CameraImage image) {
return imglib.Image.fromBytes(
image.width,
image.height,
image.planes[0].bytes,
format: imglib.Format.bgra,
);
}
// CameraImage YUV420_888 -> PNG -> Image (compresion:0, filter: none)
// Black
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;
}
Some background:
In the latter you can find a comment that links to what appears to be more efficient implementation, it's in YUV_2_RGB project: https://github.com/alexcohn/YUV_2_RGB/blob/master/lib/service/image_result_processor_service.dart