Image to data uri without base64 - javascript

I have image as base64 data URI but want to convert it to Data URI without base64 (in my case image size doesn't matter) - how to do it? This is what I try so far
let imgB64="Qk3KAAAAAAAAAD4AAAAoAAAAHQAAACMAAAABAAEAAAAAAIwAAADDDgAAww4AAAAAAAAAAAAAAAAAAP///wD//f/4//B/+P/tv/j/nc/4/n3z+P39/fjx+Px45uUzuJddz8h3vd/wd73f8He93/BvvN/wX78f8D+f3/BOZz/wdfr/8Hv9//B7+f/we+X/8Hvd//B73f/we93/8GTd/nBfUniQP4+m6L/f3tjP396489/eeP3f2fj+X9f4/5/P+P/Pv/j/8n/4//3/+A";
let imgStr=atob(imgB64); // decode base 64 to str
let bytes=Uint8Array.from(imgStr, c => c.charCodeAt(0)); // string to bytes
picB64.src='data:image;base64,'+imgB64 // this works
pic.src='data:image;text/plain,'+encodeURIComponent(bytes); // this not work :(
<div>This works</div> <img id="picB64">
<div>This not works</div> <img id="pic">
Here is example showing that this is possible (probably partially broken but works)
<img src=data:image;text/plain,BMv%0A%00%00%00%00%00%00x%00%00%00(%00%00%00%40%00%00%00%40%00%00%00%01%00%04%00%00%00%00%00%00%00%00%00%C3%84%0E%00%00%C3%84%0E%00%00%00%00%00%00%00%00%00%00%00%00%00%00%2B%C2%81%C3%BC%00%08%1F%C3%8D%00%08Zr%00%C3%BC%C3%BA%C3%BC%00%5E%5E%5E%00%119%C2%B9%00%08%C2%93%0B%00%C2%AB%C2%AB%C2%AB%00%00%C3%BF%00%00%00%C3%BF%00%00%00%C3%BF%C3%BC%00%C3%BC%C3%BF%C2%AB%00%C2%AB%C3%BF%00%00%00%C3%BF%00%00%00%C3%BF%00%00%00%00%00%02%00%03%01%03%00%01%01%02%03%03%03%02%03%03%02%00%03%01%01%01%03%03%03%02%03%01%02%02%01%02%01%00%00%00%01%03%00%00%02%00%02%01%02%00%02%01%03%03%01%01%02%01%01%02%00%01%02%02%03%00%01%02%03%00%01%01%01%01%03%01%02%01%01%02%03%02%02%03%00%00%00%02%01%01%02%01%02%01%00%03%00%02%02%03%01%03%01%02%02%02%02%00%01%01%02%00%00%03%00%02%01%01%03%03%03%03%01%03%02%01%00%00%01%02%02%01%00%00%01%03%03%00%00%00%03%00%01%01%01%01%01%02%00%02%00%03%03%03%00%02%02%03%01%02%01%02%00%01%01%03%02%01%02%00%00%00%00%00%01%00%01%02%02%01%01%03%03%02%02%02%01%02%03%02%00%00%03%00%03%00%01%03%01%01%02%02%03%02%03%03%03%02%03%03%02%01%03%02%03%01%00%02%03%03%00%02%02%01%02%02%01%02%02%03%03%01%00%01%03%03%03%01%01%01%01%01%00%03%02%00%00%00%02%01%01%02%00%02%02%01%02%03%03%00%03%02%00%02%02%01%00%03%00%00%03%01%03%03%01%02%00%02%03%01%01%01%03%00%00%03%02%03%00%01%02%03%03%02%03%02%02%01%01%01%00%03%03%03%03%01%02%03%02%03%00%00%01%01%01%00%02%00%02%01%03%01%00%02%02%03%02%01%02%01%01%01%01%03%00%01%03%03%00%03%02%01%02%00%01%01%01%00%00%03%01%00%03%01%01%01%01%02%01%02%00%03%03%00%00%01%00%00%03%02%03%02%00%03%02%03%03%01%03%00%01%01%00%01%01%02%00%00%02%02%01%00%00%00%03%02%00%02%02%00%02%03%03%01%02%01%01%00%01%00%03%03%00%01%01%00%03%01%03%01%02%01%00%02%01%01%01%00%02%02%03%02%01%00%00%00%03%02%00%03%00%00%00%02%03%00%00%01%03%02%01%02%02%03%01%00%00%01%01%02%03%03%03%00%01%00%01%00%03%02%02%02%00%00%03%02%02%03%00%00%02%02%01%03%01%02%01%02%03%03%03%01%00%01%02%02%01%02%03%00%03%01%03%01%02%00%01%00%03%03%03%02%01%01%02%03%03%01%01%02%03%01%01%03%02%01%01%01%00%01%00%00%03%01%00%02%02%03%02%00%02%01%03%00%00%02%02%03%03%01%02%00%00%00%03%01%03%02%02%01%02%02%03%03%03%01%01%00%00%03%03%01%00%01%03%03%02%03%03%02%00%02%00%02%00%02%00%02%00%00%01%01%00%02%03%03%03%01%00%01%03%01%01%00%03%02%02%00%02%02%02%01%00%00%02%01%03%02%01%01%00%03%02%01%01%01%02%02%02%02%02%00%01%01%02%00%00%03%02%02%00%02%03%00%01%00%01%03%01%02%03%02%00%03%01%01%00%03%00%03%02%02%03%00%03%01%03%02%01%02%00%01%01%02%00%00%00%02%03%03%01%03%03%02%01%01%01%00%02%01%01%01%01%03%01%02%01%02%03%01%02%02%02%00%02%01%00%00%01%00%02%00%00%02%00%00%01%03%01%02%02%01%03%01%03%02%02%03%00%02%03%03%01%00%03%00%00%01%03%03%03%02%01%02%00%01%03%02%02%02%01%00%02%03%01%01%02%02%01%02%03%03%01%00%01%02%03%00%00%02%02%02%03%01%03%02%03%03%00%00%02%01%02%00%00%01%03%02%00%01%01%01%01%00%01%01%00%00%02%02%02%03%00%02%00%00%01%01%01%01%03%03%01%03%01%03%03%02%03%01%00%03%02%01%01%00%03%03%03%01%00%02%01%02%03%01%02%03%03%01%00%01%03%02%00%00%03%01%03%03%02%03%01%02%02%00%00%03%02%03%00%03%03%02%00%01%03%03%03%00%01%00%00%00%03%02%00%02%01%01%03%01%01%01%01%01%02%02%00%00%00%01%02%00%03%01%03%03%03%03%01%00%01%03%02%00%02%00%00%02%00%02%00%02%01%03%03%01%02%01%02%01%03%00%03%01%00%03%01%03%03%02%03%01%01%01%00%03%03%03%01%03%03%01%01%01%03%01%03%02%00%02%00%01%02%00%03%02%01%00%00%01%02%01%00%02%02%01%00%01%03%01%03%01%03%00%02%02%02%01%00%03%02%01%02%03%02%00%00%02%03%01%01%01%01%00%03%03%02%03%03%02%01%00%01%03%01%01%00%00%03%00%03%03%01%00%02%02%01%00%02%02%02%00%02%00%01%03%02%01%02%01%01%03%01%01%02%01%00%00%00%02%02%03%01%02%01%02%03%01%02%03%01%00%02%02%01%02%03%00%03%01%01%00%01%00%00%03%03%03%00%02%03%01%01%00%03%02%01%02%02%00%00%01%02%02%02%03%02%00%02%00%01%00%03%02%02%03%01%01%01%03%03%03%03%02%02%02%01%01%02%01%02%00%00%00%02%00%01%02%00%00%02%02%02%02%01%02%02%02%02%01%03%03%01%01%01%00%03%03%00%00%00%01%01%02%00%00%00%03%01%00%01%03%03%01%03%02%02%02%01%00%00%03%00%03%00%01%01%02%03%02%03%02%01%01%01%01%00%02%03%03%03%03%03%01%00%01%03%03%01%02%01%01%01%02%02%00%03%00%01%00%00%02%01%02%02%00%00%00%00%02%00%03%01%01%01%00%01%03%02%01%00%03%02%02%00%01%02%03%03%02%03%01%02%00%02%01%01%03%01%00%01%03%01%02%00%02%00%03%03%00%02%03%00%02%02%01%01%00%02%03%01%03%03%03%00%00%00%01%00%00%00%03%03%02%00%01%03%03%00%03%02%03%02%03%02%03%03%03%00%00%01%03%00%01%00%02%00%03%00%00%00%01%03%01%02%00%03%03%00%02%03%00%03%01%02%02%02%03%03%01%01%01%01%01%01%00%00%03%03%01%01%00%01%03%00%02%02%00%00%01%01%01%00%00%02%03%00%01%02%03%00%03%02%02%03%01%02%03%02%01%01%02%01%00%00%01%01%01%00%02%02%00%02%00%00%02%01%00%02%03%00%00%01%01%02%02%02%00%02%03%03%00%02%02%00%03%01%03%03%01%00%01%03%03%03%03%01%01%03%02%03%00%00%01%02%03%01%02%02%02%03%03%03%02%03%02%01%01%02%03%03%03%02%00%03%00%02%00%02%01%02%03%02%00%00%01%02%03%03%02%03%00%01%00%02%03%03%03%02%03%01%00%00%01%00%00%01%03%02%03%00%02%02%00%02%03%00%02%03%01%00%01%03%03%02%02%02%01%03%02%03%00%00%01%03%01%00%03%01%01%03%02%00%01%03%03%01%02%01%03%00%01%01%01%02%02%01%02%00%01%03%03%02%02%02%01%02%02%02%00%03%01%00%03%01%00%03%00%01%03%03%02%02%02%03%02%02%00%03%03%01%03%00%01%02%03%00%03%02%00%02%03%02%02%00%01%01%03%01%00%02%02%03%02%02%00%00%03%01%03%01%03%00%02%00%03%01%03%01%01%00%00%02%01%03%02%03%03%03%03%01%00%01%02%03%00%01%00%00%01%03%02%02%01%01%01%03%02%00%03%03%00%01%02%03%01%00%02%02%01%00%03%01%02%02%02%01%01%01%01%02%01%01%01%03%01%00%03%02%00%03%01%02%01%03%00%00%03%03%01%00%03%00%01%03%00%01%03%01%00%00%01%00%01%01%03%00%00%03%02%00%02%00%00%02%01%01%02%00%02%02%03%03%02%00%02%01%02%02%03%03%01%02%00%00%00%00%01%00%01%03%00%01%03%00%03%02%02%00%00%01%03%02%00%00%02%00%00%02%03%00%02%03%02%01%01%02%01%02%00%02%03%02%01%03%02%01%02%01%01%02%02%01%00%03%03%00%03%01%01%03%02%03%01%03%02%02%02%03%02%00%01%00%02%02%03%03%01%03%00%00%00%02%03%03%00%00%00%00%01%00%03%03%00%00%00%00%02%00%00%01%00%00%01%02%01%00%00%03%00%02%01%03%01%01%00%01%02%01%01%03%00%01%00%00%01%00%00%03%03%00%03%00%01%02%01%01%00%02%02%01%02%01%01%00%00%01%02%00%00%03%03%01%01%02%02%01%03%03%00%00%02%02%01%00%00%01%01%03%01%01%03%02%00%03%03%00%00%00%03%02%01%00%00%02%03%03%00%02%03%03%01%01%03%00%03%01%02%03%01%01%02%00%03%01%00%03%01%00%01%03%01%03%01%03%01%03%01%00%00%02%02%00%02%00%03%02%00%01%02%01%03%02%02%02%01%01%00%03%00%03%03%01%00%03%00%02%01%00%03%03%00%01%03%03%01%00%01%01%03%03%02%03%00%00%01%01%00%00%01%02%03%00%00%01%03%00%02%00%01%01%01%03%01%00%03%01%03%01%03%02%03%00%01%00%02%03%03%01%02%00%00%02%02%02%02%03%01%03%01%00%01%00%02%00%00%03%03%00%00%00%02%01%02%00%02%00%02%03%02%03%00%03%02%01%03%03%01%00%00%01%01%03%00%03%00%00%02%00 >

It's definitely possible to render image without base64 encoding.
Here is it:
//function for convert byte array to hex
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('%')
}
//image in base64
var imgB64="Qk3KAAAAAAAAAD4AAAAoAAAAHQAAACMAAAABAAEAAAAAAIwAAADDDgAAww4AAAAAAAAAAAAAAAAAAP///wD//f/4//B/+P/tv/j/nc/4/n3z+P39/fjx+Px45uUzuJddz8h3vd/wd73f8He93/BvvN/wX78f8D+f3/BOZz/wdfr/8Hv9//B7+f/we+X/8Hvd//B73f/we93/8GTd/nBfUniQP4+m6L/f3tjP396489/eeP3f2fj+X9f4/5/P+P/Pv/j/8n/4//3/+A";
//base64 to string
var imgStr=atob(imgB64);
//make byte array
var bytes=Uint8Array.from(imgStr, c => c.charCodeAt(0));
//transform input array into hex array
var hexBytes = "data:image,%" + toHexString(bytes);
//set image to element
document.getElementById("pic").src = hexBytes;
<html>
<head>
<title>Sample</title>
</head>
<body>
<img id="pic">
</body>
</html>

Unfortunately, the content of a data-uri is either textual or base64 encoded binary data.
From MDN Data URLs
Data URLs are composed of four parts: a prefix (data:), a MIME type indicating the type of data, an optional base64 token if non-textual, and the data itself:
data:[<mediatype>][;base64],<data>
The mediatype is a MIME type string, such as 'image/jpeg' for a JPEG image file. If omitted, defaults to text/plain;charset=US-ASCII
If the data is textual, you can simply embed the text (using the appropriate entities or escapes based on the enclosing document's type). Otherwise, you can specify base64 to embed base64-encoded binary data. You can find more info on MIME types here and here.
To use binary data with a data-uri requires binary data be base64 encoded. Sorry
UPDATE
It seems that you have come across a "work-around", although this allows you to use url encoded text within the data-uri, it is goung to be even larger than the base64 encoding.
Base 64 encodes 3 bytes on binary data in to 4 bytes of ASCII. Resulting in a (approximately) 33% increase in size. URL Encoding a single byte will result in 3 characters resulting in a 200% increase in size.
This increase in size is exactly what you are trying to avoid though.

Related

How can I convert from a Javascript Buffer to a String only containing 0 and 1

So I currently am trying to implement the huffman alg and it works fine for decoding and encoding. However, I store the encoded data as follows.
The result of the encoding function is a list containing many strings made up of 0 and 1 and all are varying length.
If i'd safe them in a normal txt file it would take up more space, if Id store them how they are in a binary file it could be that for example an 'e' which would have the code 101 would be stored in a full 8 bits looking like '00000101' which is wasteful and wont take up less storage then the original txt file. I took all the strings in the list and put them into one string and split it into equal parts of length 8 to store them more effectively.
However if I wanna read the data now, instead of 0 and 1 I get utf-8 chars, even some escape characters.
I'm reading the file with fs.readFileSync("./encoded.bin", "binary"); but javascript then thinks it's a buffer already and converts it to a string and it gets all weird... Any solutions or ideas to convert it back to 0 and 1?
I also tried to switch the "binary" in fs.readFileSync("./encoded.bin", "binary"); to a "utf-8" which helped with not crashing my terminal but still is "#��C��Ʃ��Ԧ�y�Kf�g��<�e�t"
To clarify, my goal in the end is to read out the massive string of binary data which would look like this "00011001000101001010" and actually get this into a string...
You can convert a String of 1s and 0s to the numerical representation of a byte using Number.parseInt(str, 2) and to convert it back, you can use nr.toString(2).
The entire process will look something like this:
const original = '0000010100000111';
// Split the string in 8 char long substrings
const stringBytes = original.match(/.{8}/g);
// Convert the 8 char long strings to numerical byte representations
const numBytes = stringBytes.map((s) => Number.parseInt(s, 2));
// Convert the numbers to an ArrayBuffer
const buffer = Uint8Array.from(numBytes);
// Write to file
// Read from file and reverse the process
const decoded = [...buffer].map((b) => b.toString(2).padStart(8, '0')).join('');
console.log('original', original, 'decoded', decoded, 'same', original === decoded);
var binary = fs.readFileSync("./binary.bin");
binary = [...binary].map((b) => b.toString(2).padStart(8, "0")).join("");
console.log(binary);
//Output will be like 010000111011010

Convert Float32Array to base64 in javascript

There are many Q&A's about converting blobs or Uint8Array to base64. But I have been unable to find how to convert from 32-bit arrays to base64. Here is an attempt.
function p(msg) { console.log(msg) }
let wav1 = [0.1,0.2,0.3]
let wav = new Float32Array(wav1)
p(`Len array to encrypt=${wav.length}`)
let omsg = JSON.stringify({onset: { id: 'abc', cntr: 1234}, wav: atob(wav) })
p(omsg)
The atob gives:
Uncaught InvalidCharacterError: Failed to execute 'atob' on 'Window':
The string to be decoded is not correctly encoded."
What intermediate step is needed to allow proper encoding of the floats to base64 ? Note that I have also tried TweetNacl-util instead of atob this way:
nacl.util.encodeBase64(wav)
This results in the same error.
Update Using JSON.stringify directly converts each float element into its ascii equivalent - which bloats the datasize . For the above that is:
"0.10000000149011612,"1":0.20000000298023224,"2":0.30000001192092896
We are transferring large arrays so this is a suboptimal solution.
Update The crucial element of the solution in the accepted answer is using Float32Array(floats).buffer . I was unaware of the buffer attribute.
The problem with your current code is that nacl.util.encodeBase64() takes in either a string, Array, or Uint8Array. Since your input isn't an Array or Uint8Array, it assumes you want to pass it in as a string.
The solution, of course, is to encode it into a Uint8Array first, then encode the Uint8Array into base64. When you decode, first decode the base64 into a Uint8Array, then convert the Uint8Array back into your Float32Array. This can be done using JavaScript ArrayBuffer.
const floatSize = 4;
function floatArrayToBytes(floats) {
var output = floats.buffer; // Get the ArrayBuffer from the float array
return new Uint8Array(output); // Convert the ArrayBuffer to Uint8s.
}
function bytesToFloatArray(bytes) {
var output = bytes.buffer; // Get the ArrayBuffer from the Uint8Array.
return new Float32Array(output); // Convert the ArrayBuffer to floats.
}
var encoded = nacl.util.encodeBase64(floatArrayToBytes(wav)) // Encode
var decoded = bytesToFloatArray(nacl.util.decodeBase64(encoded)) // Decode
If you don't like functions, here's some one-liners!
var encoded = nacl.util.encodeBase64(new Uint8Array(wav.buffer)) // Encode
var decoded = new Float32Array(nacl.util.decodeBase64(encoded).buffer) // Decode

Decoding payload from Byte 6 onwards

I am sending text data from a device. This text is contained in the array from Byte 6. Could anyone help me work out how to decode the array from byte 6 please?
the Base64 is:
AwYABgABMTIzNEtn
The code i use at the moment is:
function Decode(fport, bytes) {
// Decode plain text; for testing only
return {
receivedString: String.fromCharCode.apply(null, bytes)
};
}
This obviously returns the full byte string in text form as below:
Picture of full byte string as text
I am not interested in returning the data from the first 5 bytes as these are stop characters etc. I am only interested in extracting the '1234Kg'
Any ideas welcome!
Thanks,
Lee

Conversion from buffer of bytes to string then back to bytes in NodeJS / Javascript

Like the title states, I am just trying to encode some bytes in a string, then decode them back to bytes. The conversion of a Uint8 array of bytes to string then back to array does not happen perfectly. I am just wondering what encoding I should use in the conversion to make it happen correctly.
I try this as a dummy example:
var bytes = serializeToBinary(); // giving me bytes
console.log('bytes type:'+ Object.prototype.toString.call(bytes));
console.log('bytes length:'+ bytes.length);
var bytesStr = bytes.toString('base64'); // gives me a string that looks like '45,80,114,98,97,68,111'
console.log('bytesStr length:'+ bytesStr.length);
console.log('bytesStr type:'+ Object.prototype.toString.call(bytesStr));
var decodedbytesStr = Buffer.from(bytesStr, 'base64');
console.log('decodedbytesStr type:'+ Object.prototype.toString.call(decodedbytesStr));
console.log('decodedbytesStr length:'+ decoded.length);
Output:
bytes type:[object Uint8Array]
bytes length:4235
bytesStr type:[object String]
bytesStr length:14161
decodedbytesStr type:[object Uint8Array]
decodedbytesStr length:7445
Shouldn't decodedbytesStr length and bytes length be the same?
TypedArray does not support .toString('base64'). The base64 argument is ignored, and you simply get a string representation of the array's values, separated by commas. This is not a base64 string, so Buffer.from(bytesStr, 'base64') is not processing it correctly.
You want to call .toString('base64') on a Buffer instead. When creating bytesStr, simply build a Buffer from your Uint8Array first:
var bytesStr = Buffer.from(bytes).toString('base64');

Image file size from data URI in JavaScript

I am not sure it's even possible but - can I get the image file size from data URI?
For example, let's say there is an IMG element where src goes:
src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...
Based on the src, can I get the image file size by using plain JavaScript? (without server request)
If you want file size, simply decode your base64 string and check the length.
var src ="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP/// yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
var base64str = src.substr(22);
var decoded = atob(base64str);
console.log("FileSize: " + decoded.length);
If you're okay with a (very good) estimate, the file size is 75% of the size of the base64 string. The true size is no larger than this estimate, and, at most, two bytes smaller.
If you want to write one line and be done with it, use atob() and check the length, as in the other answers.
If you want an exact answer with maximum performance (in the case of gigantic files or millions of files or both), use the estimate but account for the padding to get the exact size:
let base64Length = src.length - (src.indexOf(',') + 1);
let padding = (src.charAt(src.length - 2) === '=') ? 2 : ((src.charAt(src.length - 1) === '=') ? 1 : 0);
let fileSize = base64Length * 0.75 - padding;
This avoids parsing the entire string, and is entirely overkill unless you're hunting for microoptimizations or are short on memory.
Your best option is to calculate the length of the base64 string itself.
What is a base64 length in bytes?
You have to convert the base64 string to a normal string using atob() and then check it length, it will return a value that you can say is close to the actual size of the image. Also you don't need the data:image/jpeg;base64, part from the data URI to check the size.
This is a universal solution for all types of base64 strings based on Daniel Trans's code.
var src ="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP/// yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
var base64str = src.split('base64,')[1];
var decoded = atob(base64str);
console.log("FileSize: " + decoded.length);
The other solutions make use of atob, which has now been deprecated. Here is an up-to-date example, using Buffer instead.
const src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...";
const base64str = src.split('base64,')[1]; //remove the image type metadata.
const imageFile = Buffer.from(base64str, 'base64'); //encode image into bytes
console.log('FileSize: ' + imageFile.length);

Categories

Resources