How to convert camera image to image? - flutter

I want to convert camera image from function startImageStream of camera plugin in Flutter to Image to crop that image but I only find the way to convert to FirebaseVisionImage.

Edit For Color Image
if I understand you clear. You are trying to covnert YUV420 format. The following is code snippet from: https://github.com/flutter/flutter/issues/26348
const shift = (0xFF << 24);
Future<Image> convertYUV420toImageColor(CameraImage image) async {
try {
final int width = image.width;
final int height = image.height;
final int uvRowStride = image.planes[1].bytesPerRow;
final int uvPixelStride = image.planes[1].bytesPerPixel;
print("uvRowStride: " + uvRowStride.toString());
print("uvPixelStride: " + uvPixelStride.toString());
// imgLib -> Image package from https://pub.dartlang.org/packages/image
var img = imglib.Image(width, height); // Create Image buffer
// Fill image buffer with plane[0] from YUV420_888
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int uvIndex = uvPixelStride * (x / 2).floor() + uvRowStride * (y / 2).floor();
final int index = y * width + x;
final yp = image.planes[0].bytes[index];
final up = image.planes[1].bytes[uvIndex];
final vp = image.planes[2].bytes[uvIndex];
// Calculate pixel color
int r = (yp + vp * 1436 / 1024 - 179).round().clamp(0, 255);
int g = (yp - up * 46549 / 131072 + 44 - vp * 93604 / 131072 + 91).round().clamp(0, 255);
int b = (yp + up * 1814 / 1024 - 227).round().clamp(0, 255);
// color: 0x FF FF FF FF
// A B G R
img.data[index] = shift | (b << 16) | (g << 8) | r;
}
}
imglib.PngEncoder pngEncoder = new imglib.PngEncoder(level: 0, filter: 0);
List<int> png = pngEncoder.encodeImage(img);
muteYUVProcessing = false;
return Image.memory(png);
} catch (e) {
print(">>>>>>>>>>>> ERROR:" + e.toString());
}
return null;
}

I found, sometimes planes[0] bytes per row is not same as width. In that case, you should do something like the code below.
static image_lib.Image convertYUV420ToImage(CameraImage cameraImage) {
final width = cameraImage.width;
final height = cameraImage.height;
final yRowStride = cameraImage.planes[0].bytesPerRow;
final uvRowStride = cameraImage.planes[1].bytesPerRow;
final uvPixelStride = cameraImage.planes[1].bytesPerPixel!;
final image = image_lib.Image(width, height);
for (var w = 0; w < width; w++) {
for (var h = 0; h < height; h++) {
final uvIndex =
uvPixelStride * (w / 2).floor() + uvRowStride * (h / 2).floor();
final index = h * width + w;
final yIndex = h * yRowStride + w;
final y = cameraImage.planes[0].bytes[yIndex];
final u = cameraImage.planes[1].bytes[uvIndex];
final v = cameraImage.planes[2].bytes[uvIndex];
image.data[index] = yuv2rgb(y, u, v);
}
}
return image;
}
static int yuv2rgb(int y, int u, int v) {
// Convert yuv pixel to rgb
var r = (y + v * 1436 / 1024 - 179).round();
var g = (y - u * 46549 / 131072 + 44 - v * 93604 / 131072 + 91).round();
var b = (y + u * 1814 / 1024 - 227).round();
// Clipping RGB values to be inside boundaries [ 0 , 255 ]
r = r.clamp(0, 255);
g = g.clamp(0, 255);
b = b.clamp(0, 255);
return 0xff000000 |
((b << 16) & 0xff0000) |
((g << 8) & 0xff00) |
(r & 0xff);
}

Related

How to convert HSV to RGB in flutter

I'm using this code to convert RGB to HSV.
now i have to revert back to RGB.
is that any way to convert this in flutter??
I just recently started working in flutter, please help me out, I'm stuck here.
Thank you so much in advance.
rgbToHsv(int r1, int g1, int b1) {
// R, G, B values are divided by 255
// to change the range from 0..255 to 0..1:
double r = r1 / 255.0;
double g = g1 / 255.0;
double b = b1 / 255.0;
// h, s, v = hue, saturation, value
var cmax = [r, g, b].reduce(max); // maximum of r, g, b
var cmin = [r, g, b].reduce(min); // minimum of r, g, b
var diff = cmax - cmin; // diff of cmax and cmin.
var h;
var s;
var v;
//Get value of h
if (cmax == cmin) {
h = 0;
} else if (cmax == r) {
h = (60 * ((g - b) / diff) + 360) % 360;
} else if (cmax == g) {
h = (60 * ((b - r) / diff) + 120) % 360;
} else if (cmax == b) {
h = (60 * ((r - g) / diff) + 240) % 360;
}
//Get value of s
if (cmax == 0) {
s = 0;
} else {
s = (diff / cmax) * 100;
}
//Get value of v
v = cmax * 100;
//Convert HSV [360, 100, 100] to HSV [256, 256, 256]
double h_256 = (h / 360) * 255;
double s_256 = (s / 100) * 255;
double v_256 = (v / 100) * 255;
int h_256_int = h_256.toInt();
int s_256_int = s_256.toInt();
int v_256_int = v_256.toInt();
//Convert to HSV HEX
var hex_h = h_256_int.toRadixString(16);
var hex_s = s_256_int.toRadixString(16);
var hex_v = v_256_int.toRadixString(16);
//MERGE HSV HEX
var finalColor = hex_h + hex_s + hex_v;
print("HSV HEX:" + finalColor.toUpperCase());
/////RGB TRANS>>>>>>>>>>>>>>>>>
////////RGB TRANS>>>>>>>>>>>>>>>>>
////////RGB TRANS>>>>>>>>>>>>>>>>>
////////RGB TRANS>>>>>>>>>>>>>>>>>
var _h = hextToint(hex_h);
var _s = hextToint(hex_s);
var _v = hextToint(hex_v);
print(_h);
print(_s);
print(_v);
print(hsvToRgb(_h.toDouble(), _s.toDouble(), _v.toDouble()));
//return rgb;
}
this might help. I have used this in one of my projects.
String hsvToRgb(double H, double S, double V) {
int R, G, B;
H /= 360;
S /= 100;
V /= 100;
if (S == 0) {
R = (V * 255).toInt();
G = (V * 255).toInt();
B = (V * 255).toInt();
} else {
double var_h = H * 6;
if (var_h == 6) var_h = 0; // H must be < 1
int var_i = var_h.floor(); // Or ... var_i =
// floor( var_h )
double var_1 = V * (1 - S);
double var_2 = V (1 - S (var_h - var_i));
double var_3 = V (1 - S (1 - (var_h - var_i)));
double var_r;
double var_g;
double var_b;
if (var_i == 0) {
var_r = V;
var_g = var_3;
var_b = var_1;
} else if (var_i == 1) {
var_r = var_2;
var_g = V;
var_b = var_1;
} else if (var_i == 2) {
var_r = var_1;
var_g = V;
var_b = var_3;
} else if (var_i == 3) {
var_r = var_1;
var_g = var_2;
var_b = V;
} else if (var_i == 4) {
var_r = var_3;
var_g = var_1;
var_b = V;
} else {
var_r = V;
var_g = var_1;
var_b = var_2;
}
R = (var_r * 255).toInt(); // RGB results from 0 to 255
G = (var_g * 255).toInt();
B = (var_b * 255).toInt();
}
String rs = R.toRadixString(16);
String gs = G.toRadixString(16);
String bs = B.toRadixString(16);
if (rs.length == 1) rs = "0" + rs;
if (gs.length == 1) gs = "0" + gs;
if (bs.length == 1) bs = "0" + bs;
return "#" + rs + gs + bs;
}
RGB to HSV
HSVColor rgbToHSV(int r, int g, int b, {double opacity = 1}) {
return HSVColor.fromColor(Color.fromRGBO(r, g, b, opacity));
}
HSV to RGB
List<int> hsvToRGB(HSVColor color) {
//convert to color
final c = color.toColor();
return [c.red, c.blue, c.green];
}
To use HSVColor use myHSVcolor.toColor().
More about HSV Color.
Expanding on Yeasin Sheikh answer
Flutter
RGB to HSV
HSVColor rgbToHSV(int r, int g, int b, {double opacity = 1}) {
return HSVColor.fromColor(Color.fromRGBO(r, g, b, opacity));
}
HSV to RGB
List<int> hsvToRGB(HSVColor color) {
//convert to color
final c = color.toColor();
return [c.red, c.blue, c.green];
}
To use HSVColor use myHSVcolor.toColor().
More about HSV Color.
Native Dart
Import color package
RGB to HSV
final RgbColor rgbColor = RgbColor(red, green, blue);
final HsvColor hsvColor = rgbColor.toHsvColor();
HSV to RGB
final HsvColor hsvColor = HsvColor(hueValue, saturationValue, valueValue)
final RgbColor rgbColor = hsvColor.toRgbColor();
HSVColor class is not supported in native dart so we are using a package for that with similar classes.

Convert YUV420 to RGB flutter

const shift = (0xFF << 24);
Future<Image> convertYUV420toImageColor(CameraImage image) async {
try {
final int width = image.width;
final int height = image.height;
final int uvRowStride = image.planes[1].bytesPerRow;
final int uvPixelStride = image.planes[1].bytesPerPixel;
print("uvRowStride: " + uvRowStride.toString());
print("uvPixelStride: " + uvPixelStride.toString());
// imgLib -> Image package from https://pub.dartlang.org/packages/image
var img = imglib.Image(width, height); // Create Image buffer
// Fill image buffer with plane[0] from YUV420_888
for(int x=0; x < width; x++) {
for(int y=0; y < height; y++) {
final int uvIndex = uvPixelStride * (x/2).floor() + uvRowStride*(y/2).floor();
final int index = y * width + x;
final yp = image.planes[0].bytes[index];
final up = image.planes[1].bytes[uvIndex];
final vp = image.planes[2].bytes[uvIndex];
// Calculate pixel color
int r = (yp + vp * 1436 / 1024 - 179).round().clamp(0, 255);
int g = (yp - up * 46549 / 131072 + 44 -vp * 93604 / 131072 + 91).round().clamp(0, 255);
int b = (yp + up * 1814 / 1024 - 227).round().clamp(0, 255);
// color: 0x FF FF FF FF
// A B G R
img.data[index] = shift | (b << 16) | (g << 8) | r;
}
}
imglib.PngEncoder pngEncoder = new imglib.PngEncoder(level: 0, filter: 0);
List<int> png = pngEncoder.encodeImage(img);
muteYUVProcessing = false;
return Image.memory(png);
} catch (e) {
print(">>>>>>>>>>>> ERROR:" + e.toString());
}
return null;
}
I have been following this code snippet from How to convert Camera Image to Image in Flutter? to convert YUV to RGB to send the images via WebSockets for ML prediction.
Although it works to convert, the resulting image is rotated 90 degrees and the performance is a little bit slow. How I can rotate it?
replace img.data[index] = shift | (b << 16) | (g << 8) | r;
with
if (img.boundsSafe(height-y, x)){
img.setPixelRgba(height-y, x, r , g ,b ,shift);
}
and replace var img = imglib.Image(width, height);
with
var img = imglib.Image(height, width);
For IOS version, the CameraImage is returned as biplanar which has only two planes.
Quote from image_format_group.dart:
/// Multi-plane YUV 420 format.
/// This format is a generic YCbCr format, capable of describing any 4:2:0
/// chroma-subsampled planar or semiplanar buffer (but not fully interleaved),
/// with 8 bits per color sample.
/// On Android, this is `android.graphics.ImageFormat.YUV_420_888`. See
/// https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888
/// On iOS, this is `kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange`. See
/// https://developer.apple.com/documentation/corevideo/1563591-pixel_format_identifiers/kcvpixelformattype_420ypcbcr8biplanarvideorange?language=objc
yuv420
For my approach, I use dart:ffi and link to c++ for Android CameraImage following the tutorial from here. The conversion between YUV420p and YUV420sp can be found here. There is no complete code for the conversion yet, but neither any solution for IOS around the forum.

How to optimize flutter CameraImage to TensorImage?

That function is too slow. So Flutter CameraImage efficiency convert to TensorImage in dart?
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;
}```
Seems your for loop is inefficient. The data for whole row (with same placeOffset, different x) will be cached at once, so would be faster to switch ordering of the two loops.
for (int y = 0; y < image.height; y++) {
for (int x = 0; x < image.width; x++) {
final pixelColor = plane.bytes[y * image.width + x];
// ...
}
}
However, your code does not seems to be reading from the actual camera stream. please refer this thread for converting CameraImage to Image.
How to convert Camera Image to Image in Flutter?

How to get Sprite pixel alpha information in cocos2d js/c++

I am working on a scratch and win game, I used clipper node for this.
But I want to know the event when whole sprite is clippe?
Is there any other way to know it, plz help me
I solved this issue by using following method:-
I create one rendure texture and add an sprite on it.
I found answer here:- http://discuss.cocos2d-x.org/t/render-texture-get-percentage-of-transparent/21123
here is the code:-
var WINDOW_WIDTH = cc.director.getWinSize().width;
var WINDOW_HEIGHT = cc.director.getWinSize().height;
rt = new cc.RenderTexture(WINDOW_WIDTH, WINDOW_HEIGHT,
sprite.getTexture().getPixelFormat());
rt.setPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
this.addChild(rt, 5);
getPercentageTransparent: function () {
//
var s = rt.getSprite().getContentSize();
var tx = s.width;
var ty = s.height;
var bitsPerPixel = 4 * 8;
var bytesPerPixel = bitsPerPixel / 8;
var bytesPerRow = bytesPerPixel * tx;
var myDataLength = bytesPerRow * ty;
var numberOfPixels = tx * ty;
var numberOfTransparent = 0;
var rawImagePixels = new Uint8Array(myDataLength);
rt.begin();
gl.readPixels(0, 0, tx, ty, gl.RGBA, gl.UNSIGNED_BYTE, rawImagePixels);
rt.end();
var x, y;
for (y = 0; y < ty; y++) {
// just want the last byte (alpha) for each pixel
for (x = 0; x < tx; x++) {
var alpha = rawImagePixels[(y * 4 * tx + ((x * 4) + 3))];
if (alpha < 1) {
numberOfTransparent++;
}
}
}
cc.log("Number of pixels" + numberOfPixels);
cc.log("Number of Trasparent" + numberOfTransparent);
cc.log("percentage " + (numberOfTransparent / numberOfPixels) * 100);
return (numberOfTransparent / numberOfPixels) * 100;
},

Direct read data from a file png

is required to read data from a binary file without loading them in Bitmap because it is too much, more than 20000x20000 pixels, I need to open a file, one line at a time to read a file for processing. found an example for reading BMP, can not understand how in the same way to get data from PNG.
byte[] B = File.ReadAllBytes(filename);
GCHandle GCH = GCHandle.Alloc(B, GCHandleType.Pinned);
IntPtr Scan0 = (IntPtr)((int)(GCH.AddrOfPinnedObject()) + 54);
int W = Marshal.ReadInt32(Scan0, -36);
int H = Marshal.ReadInt32(Scan0, -32);
Bitmap Bmp = new Bitmap(W, H, 4 * W, PixelFormat.Format32bppArgb, Scan0);
GCH.Free();
return Bmp;
Language C#
I found a library (PNGChunkParser) with parsing blocks APG has received all the blocks that are in the file, I found a 21 unit Idate, but trying to paint them 50 lines, to be not the right picture:
byte[] B = File.ReadAllBytes(filename);
List<byte> tmpb = new List<byte>();
using (MemoryStream stream = new MemoryStream(B))
{
PNGChunk[] chunks = PNGChunkParser.ChunksFromStream(stream).ToArray();
foreach (PNGChunk item in chunks)
{
if (item.TypeString == "IDAT")
{
PNGChunk idatChunk = item;
foreach (byte s in idatChunk.Data)
{
tmpb.Add(s);
}
}
}
}
var size_png = ImageHelper.GetDimensions(filename);
GetConturPic(tmpb.ToArray(), size_png.Width, 50,PixelFormat.Format32bppArgb);
private void GetConturPic(byte[] data, int w, int h, PixelFormat pixel_format)
{
int index;
int stride = GetStride(w, pixel_format);
Bitmap bm = new Bitmap(w, h);
Color fm = new Color();
try
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
index = y * stride + 4 * x;
fm = GetPixelColor(data, w, h, x, y,
System.Drawing.Bitmap.GetPixelFormatSize(pixel_format));
bm.SetPixel(x, y, fm);
}
pictureBox1.Image = bm;
pictureBox1.Refresh();
}
}
catch (Exception ex)
{
listBox1.Items.Add(ex.Message);
}
}
public Color GetPixelColor(byte[] Pixels, int w, int h, int x, int y, int depth)
{
Color clr = Color.Empty;
// Get color components count
int cCount = depth / 8;
// Get start index of the specified pixel
int i = ((y * w) + x) * cCount;
if (i > Pixels.Length - cCount)
throw new IndexOutOfRangeException();
byte b, g, a, r, c;
switch (depth)
{
case 32:
b = Pixels[i];
g = Pixels[i + 1];
r = Pixels[i + 2];
a = Pixels[i + 3]; // a
clr = Color.FromArgb(a, b, g, r);
break;
case 24:
b = Pixels[i];
g = Pixels[i + 1];
r = Pixels[i + 2];
clr = Color.FromArgb(b, g, r);
break;
case 8:
c = Pixels[i];
clr = Color.FromArgb(c, c, c);
break;
}
return clr;
}
help what need to do to get 50 lines of image ?