Unraveling an image saved in .jpeg format from a

My JavaScript script is dealing with a string containing an encoded image.jpeg that was created using OpenCV in C++:

cv::imencode(".jpeg", rgb_img, jpeg_data);
std::string jpeg_string(jpeg_data.begin(), jpeg_data.end());

The next step involves passing this string through a websocket. In my JS code, I need to decode the string and use it as the src attribute for an img tag. I attempted two methods, one from ChatGPT and another from Stack Overflow:

// Approach 1
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);
}

var blob = new Blob([arrayBuffer], { type: 'image/jpeg' });
var imageDataUri = URL.createObjectURL(blob);
img.src = imageDataUri;
// Approach 2
const imageDataUri = `data:image/jpeg;base64,${jpeg_string}`;
img.src = imageDataUri;

However, both approaches are not yielding the desired result. The first method results in a src value like

blob:http://0.0.0.0:7000/<random numbers, lowercase letters and dashes>
, and the second method produces
data:image/jpeg;base64,<uppercase letters and numbers>
. How can I successfully display the image?
I am using Robot Operating System on Ubuntu 22.4 (though this information should not affect the solution).

Answer №1

To properly encode your image, follow these steps:

cv::imencode(".jpeg", rgb_img, jpeg_data);
auto *enc_msg = reinterpret_cast<unsigned char*>(jpeg_data.data());
std::string encoded = base64_encode(enc_msg, jpeg_data.size());

After encoding, display your image by using this code:

const imageDataUri = `data:image/jpeg;base64,${jpeg_string}`;
img.src = imageDataUri;

Answer №2

Upon review, it seems that this snippet of code is on the right track:

const imgDataURI = `data:image/jpeg;base64,${jpegString}`;
image.src = imgDataURI;

It appears that the issue lies in the server not properly encoding to base64.

Answer №3

Solution: I utilized a marked solution and to make it functional, I incorporated some code borrowed from another source:

static const std::string base64_chars =
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789+/";


static inline bool is_base64(unsigned char c) {
  return (isalnum(c) || (c == '+') || (c == '/'));
}

std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
  std::string ret;
  int i = 0;
  int j = 0;
  unsigned char char_array_3[3];
  unsigned char char_array_4[4];

  while (in_len--) {
    char_array_3[i++] = *(bytes_to_encode++);
    if (i == 3) {
      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
      char_array_4[3] = char_array_3[2] & 0x3f;

      for(i = 0; (i <4) ; i++)
        ret += base64_chars[char_array_4[i]];
      i = 0;
    }
  }

  if (i)
  {
    for(j = i; j < 3; j++)
      char_array_3[j] = '\0';

    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
    char_array_4[3] = char_array_3[2] & 0x3f;

    for (j = 0; (j < i + 1); j++)
      ret += base64_chars[char_array_4[j]];

    while((i++ < 3))
      ret += '=';

  }

  return ret;

}

Answer №4

When it comes to delivering a continuous stream of images to a browser, one efficient approach is to set the MIME type to multipart/x-mixed-replace in the HTTP response and then send images consecutively from the server within the same response.

However, managing this process for multiple clients reading the video feed can be quite intricate on the server side.

If you are already familiar with websockets, it might be more advantageous to stick with that method as it tends to offer a cleaner solution. Websockets allow for smarter handling on the server side.


Opting to transmit the original binary data instead of using base64 encoding has its merits since base64 inflates the data size by about 33%. Plus, relying on transparent gzip compression may help mitigate this increase.

There's really no necessity to encode binary data in base64 on the server end. HTTP is fully capable of transmitting binary data, leaving it up to clientside Javascript to convert the binary file into a base64-encoded data: URI.

By leveraging appropriate APIs such as createObjectURL from Blob or File, you may find that bypassing base64 encoding altogether is feasible. The browser could potentially encapsulate the binary data in an "Object URL" devoid of any base64 content but still compatible with HTML rendering. This means that base64 encoding becomes an implementation detail that does not require your direct attention.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What properties can be set for a dll using a .rc file in C++ and which attributes are displayed on Windows 7?

After creating a dll and setting various attributes in the rc file by following a helpful tutorial, I scanned the dll with exiftool and saw all of my attributes intact. However, upon right-clicking on the dll in Windows 7, selecting "Properties," and navig ...

Navigate through a JSON data structure containing nested arrays

Does anyone know an effective way to loop through a JSON object that contains two or more nested arrays? The goal is to extract the values from each array without including key-value pairs in the output. {"Obj": ["array 0", ["nested array 1"], ...

Vue event manager, accessible for all components

I have created a new Vue instance and assigned it to the window object, thinking that it would be accessible throughout all components. I expected this setup to allow me access to events emitted anywhere within my application. However, it seems like this ...

How can I efficiently transfer information between AngularJS modules?

Angular offers the flexibility of creating independent Modules that can be reused in various parts of your application. Imagine having a module dedicated to managing lists, which you want to use across your entire application and populate in different ways ...

Enhancing Octahedron Geometry in Three.js: Incorporating Materials Array

Is it possible to apply different materials to each face of a THREE.OctahedronGeometry? I have successfully done this with box objects, but when I try with THREE.OctahedronGeometry, I only see the first material on all faces. How can I achieve this with ...

Using PHP's GD library to annotate images

I wrote a script that generates random pattern images. The code creates an image with specified width and height, filling it with small 40x40 pixel rectangles. Here's the code snippet: <?php $width = 1000; $height = 600; $image_p = imagecreate ...

Determine all sequences within an array using JavaScript

Given an array (with a fixed length) of objects in the following structures: {type: 'A', value: 1} or {type: 'B', text: 'b'} What is the most efficient method to identify all sequences of objects with type 'A' an ...

Something is overriding the style created by makestyle material UI that I had implemented

How can I increase the importance of my makeStyles classes over default Material UI styles? Here is my code: import { createTheme, ThemeProvider } from '@mui/material/styles'; import { makeStyles, createStyles } from '@mui/styles'; co ...

How to Stop Form from Automatically Submitting in Laravel 5.5 and vue-typeahead's onHit method

I have integrated the vue-typeahead component into my Laravel project using vue-typeahead. However, I am facing an issue where when I select an entry from the result list by pressing the "enter" key, the form automatically submits. Is there a way to preve ...

displaying and concealing elements with jquery

Is there a way to hide a div if the screen size exceeds 700px, and only show it when the screen size is less than 700px? Below is the jQuery code I'm attempting to use: jQuery(document).ready(function() { if ((screen.width>701)) { $(" ...

Animating the reordering of slides in Angular using ng-repeat

I implemented a carousel slider in Angular utilizing ng-repeat with orderBy:'id'. However, I encountered an issue where the id changes when clicking the next slide button. Check out my JSFiddle here Within a div, I have ng-repeat: <div clas ...

What is the process for defining a global variable within a module in Typescript?

I've already included a global value in my global JavaScript context: const fs = require('fs') For a specific reason, I need to include it in the global scope. Now, I want to create a .d.ts file to declare the global variable with a stron ...

I am currently developing a project using vue-cli, and I have noticed that it takes a significant amount of time to build every time it refreshes. I am looking for a solution to prevent this delay

Working with the vue-cli2.9+ version of my project, I found that every time I started the project or made changes to the code, it would take a considerable amount of time for the modules to build before running the project again. I was looking for ways t ...

Attempting to pass a string array through C++ methods

I need assistance with a C++ program that reads names and ages from the user until they input "stop", then displays all the values. I am new to C++ programming so any help would be appreciated. // Pass.cpp // Reading names and ages from user and outputt ...

Latest news on KnockoutJS enhancements

Is there a way to create an HTML markup with a GIF progress bar that appears when the page is loading? I want to use Ajax to fetch data, populate the markup, and then hide the GIF. How can I achieve this functionality using KnockoutJS? var Item = functi ...

Instructions on how to eliminate the minutes button from Material UI datetime picker

I'm currently working on customizing a datetimepicker from materialUI in ReactJS. My goal is to prevent the user from seeing or selecting minutes in the picker interface. Despite setting the views prop to include only year, month, date, and hours, use ...

What is the best way to display my 'React Loading Spinner' component at the center of my view?

Whenever I use the Loading as my parent component for the Layout component, it always shows up in the center of the page instead of within my view. How can I adjust its positioning? ...

Send an array collected from a form to the server using ReactJs

I have a task at hand where I need to work on a basic form that sends data to the server. Within this form, there is a specific field where I need to add multiple inputs and store them in an array called "users". To clarify, what I intend to do is have che ...

What is the reason for my file being blank?

Can anyone help me figure out why my file 'database2' is ending up empty and no files are being renamed? I've noticed that after the section where the issue is addressed in comments, the file 'database2' ends up being 0 bytes. More ...

What could be causing the repeated calls to a computed function in vuejs?

In my Vuejs application, I start by fetching initial data and setting it in the store: const app = new Vue({ router, store, mounted: function() { var that = this; $.get("/initial_data/", {}, function(data) { that.$s ...