How to retrieve an image in flutter from flask api

Viewed 1140

I have a post request in Flask that accepts an image file, and I want to return another image to retrieve it in Flutter and put it on screen.

In Flutter, I can send the image through the post request, but I don't know how to retrieve an image and put it on screen.

I know I can save the image in the static folder at Flask, and retrieve the URL from Flutter, and it works, but I think this is too inefficient for what I'm doing. So I want to send the image directly without saving it.

This was my last attempt but didn't work.

@app.route("/send-image", methods=['POST'])
def send_image():
    if request.method == 'POST':

        user_image = request.files["image"]
        image = cv2.imdecode(np.frombuffer(
            user_image.read(), np.uint8), cv2.IMREAD_COLOR)

        #data is a NumPy array returned by the predict function. This numpy array it's an image
        data = predict(image)

        data_object = {}
        data = data.reshape(data.shape[0], data.shape[1], 1)
        data2 = array_to_img(data)

        b = BytesIO()
        data2.save(b, format="jpeg")
        b.seek(0)

        data_object["img"] = str(b.read())
        return json.dumps(data_object)

Here I returned a Uint8List because I read from the internet that I can put that into an Image.memory() to put the image on the screen.

Future<Uint8List> makePrediction(File photo) async {
    const url = "http://192.168.0.11:5000/send-image";
    try {
      FormData data = new FormData.fromMap({
        "image": await MultipartFile.fromFile(photo.path),
      });
      final response = await dio.post(url, data: data);

      String jsonResponse = json.decode(response.data)["img"].toString();
      List<int> bytes =
          utf8.encode(jsonResponse.substring(2, jsonResponse.length - 1));

      Uint8List dataResponse = Uint8List.fromList(bytes);

      return dataResponse;
    } catch (error) {
      print("ERRORRR: " + error.toString());
    } 
  }

Sorry if what I did here doesn't make sense, but after trying a lot of things I wasn't thinking properly. I really need your help

1 Answers

You can convert the image to base64 and display it with Flutter.

On server:

import base64
...
data_object["img"] = base64.b64encode(b.read()).decode('ascii')
...

On client:

...
String imageStr = json.decode(response.data)["img"].toString();
Image.memory(base64Decode(imageStr));
...

The problem with your server-side code is it tries to coerce a bytes to str object by using function str().

However, in Python 3, bytes.__repr__ is called by str() since bytes.__str__ is not defined. This results in something like this:

str(b'\xf9\xf3') == "b'\\xf9\\xf3'"

It makes the JSON response looks like:

{"img": "b'\\xf9\\xf3'"}

Without writing a dedicated parser, you can not read this format of image data in Flutter. However, base64 is a well known format of encoding binary data and we do have a parser base64Decode in Flutter.

Related