Search code examples
androidflutterdartbitmaprgba

Flutter ui.ImageByteFormat.rawRgba has terrible Image Quality


In my project, I need to capture the frame of a flutter animation and save that frame as an image (probably in .png) to Device Storage.

I am using RepaintBoundary to capture the frame, but I can't use the ui.ImageByteFormat.png method because it takes a lot of process time to capture the frame as a .png, and since I need to take a lot of frames it will not be a viable solution. Instead, I am using ui.ImageByteFormat.rawRgba which is super fast but when I save it to Storage the image quality is terrible. It hardly looks like it's the same image I captured.

I am using FFMPEG to convert .raw or .bmp format to png and save it to storage.

In both cases, using raw or using BitMap the output image is like this:

enter image description here

But, the Quality of the Image should be like this enter image description here

Now, I need help to either get this raw capture saved with quality by using whatever file format doesn't matter or please share if you have any other viable method to capture frames of a flutter animation.


Solution

  • IMHO, that's not about quality (e.g. a "blur" image is of bad quality). that's because there are some problems on the format - someone must wrongly understand the format when encoding/decoding it.

    After looking at your code, it is likely that, your Bitmap.fromHeadless(300,100,bytes) has problem. The image is not 300x100! Please correct the size.

    Let me explain a bit about the "raw" or "bmp" format. Basically, the format just put pixels one after one onto a big list of bytes. For example, the array looks like: ["red at (0,0)", "green at (0,0)", "blue at (0,0)", "alpha at (0,0)", "red at (0,1)", "green at (0,1)", "blue at (0,1)", "alpha at (0,1)", ...]. Notice it is row major order. In other words, the order is like "pixel0,0", "pixel0,1", ... "pixel0,k", "pixel1,0", ...

    Thus, if you specify the wrong size, then it will be interpreted wrongly - That's why you see that strange-looking image!

    About how to get size: After your line of ui.Image image = await boundary.toImage(pixelRatio: 3);, you can simply do image.width and image.height to get the correct size.

    Please reply if you do not understand something and I am willing to explain ;)