How to retrieve an image in flutter from flask api
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.
Christian Rápalo
Updated on December 04, 2022Comments
-
Christian Rápalo 11 months
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
-
Philip Tzou about 3 years@Carb2750 I made some edits to the server-side code since I didn't test the code. However it seems you have already figured it out.