2

I'm looking for a way to convert a hex image (for example a jpg in hex form) back to base64 in order to display the image in a web page.

I have been using the code below for smaller images but it fails for larger images with a max call stack exceeded error.

src below is the source of the image in hex format.

test.img = new Image();
test.img.src = "data:image/jpg; base64," + hexToBase64(src);

function hexToBase64(str) {
    return btoa(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
}
Dan
  • 2,304
  • 6
  • 42
  • 69
  • [related](https://stackoverflow.com/questions/246801/how-can-you-encode-a-string-to-base64-in-javascript) – John Wu Oct 02 '18 at 23:28
  • 1
    Is there a reason it is in a hex string format? Just seems weird when you can most of the time get away with just using a Blob, File, or ArrayBuffer (TypedArray) object. But a "max call stack exceeded" message tends to be from a runaway recursive function which I am not seeing here. – Patrick Evans Oct 02 '18 at 23:32
  • This is just what I've been handed. The format of src is a header with various character markers and then the data. For example the first 4 characters of the header are 3238, which translates to 28. 28 is the number of characters to process next, which contain the file name, in this case 66696e6973686c6f6f702e706e67. If there is a better way to process this I would be grateful to learn it. The format is just what I've been given – Dan Oct 03 '18 at 00:09

1 Answers1

4

The max call stack exceeded error is being generated by converting the hex string into an array and supplying it to String.fromCharCode() as an arguments array using the apply method from Function.prototype.

There are practical limits on how many arguments can be passed in JavaScript function calls so the method can work for small files and fail for larger ones.

Refactoring the code will be necessary. As an untested basic solution

function hexToBase64(str) {
    var bString = "";
    for( var i = 0; i < str.length; i +=2) {
         bString += String.fromCharCode( parseInt( str.substr( i, 2), 16));
    }
    return btoa(bString);
}

may provide some ideas.

traktor
  • 17,588
  • 4
  • 32
  • 53