In my JS script I’m receiving string with encoded image.jpeg. The image is created with OpenCV in C++:
cv::imencode(".jpeg", rgb_img, jpeg_data);
std::string jpeg_string(jpeg_data.begin(), jpeg_data.end());
Then the string is passed through websocket.
In JS I have to decode that string and use as src of img tag. I tried (ChatGPT):
// Create a Uint8Array from the binary data
var arrayBuffer = new ArrayBuffer(jpeg_string.length);
var uint8Array = new Uint8Array(arrayBuffer);
for (var i = 0; i < jpeg_string.length; i++) {
uint8Array[i] = jpeg_string.charCodeAt(i);
}
// Create a Blob object from the ArrayBuffer
var blob = new Blob([arrayBuffer], { type: 'image/jpeg' });
// Create an Object URL for the Blob
var imageDataUri = URL.createObjectURL(blob);
img.src = imageDataUri;
and (Stack Overflow):
const imageDataUri = `data:image/jpeg;base64,${jpeg_string}`;
img.src = imageDataUri;
None of this works. In the first example:
src = blob:http://0.0.0.0:7000/<random numbers, lowercase letters and dashes>
in the other one:
src = data:image/jpeg;base64,<uppercase letters and numbers>
How to display that image?
I’m working with Robot Operating System, Ubuntu 22.4 (shouldn’t make a difference).
4
Answers
Solution: I used marked solution. To make it work I stole some code from other topic:
I think this code below looks like it’s almost right:
The problem appears to be that the server is not base64 encoding.
This seems to be the correct way to encode your image:
Then, you can show your image using this:
If you want to send a stream of images to a browser, a common and simple solution is to to declare
multipart/x-mixed-replace
MIME type in the HTTP response, then keep sending pictures from the server in the same HTTP response.This will require complex logic on the HTTP server side if you expect more than one client to read that video feed.
If you’re already working with websockets, perhaps stick to that. It’s cleaner. The server side can deal with websockets in smarter ways.
There is good reason to send the original binary instead of the base64 encoding because base64 blows the data up by a factor of 8/6, i.e. adding 33%. You could hope for any transparent gzip compression to catch that.
There is no reason to base64-encode the binary data on the server. HTTP is happy to carry binary data. Clientside Javascript can turn the binary file into a base64-encoded
data:
URI.With the right APIs (
createObjectURL
fromBlob
orFile
?), the base64 encoding may not even be needed. The browser might just wrap the binary data in an "Object URL" that does not contain base64 at any point, yet is well digested by the HTML rendering. Base64 would be an implementation detail you need not think about.