How to get "raw" image data using JavaScript? - javascript

I have a base64 encoding of a PNG image (the string starts with data:image/png;base64,). My understanding is that this a base64 representation of the image encoded in PNG. Is there a way to get the "raw" pixel by pixel binary of the image using Node.js?

Try this. First remove "data:image/png;base64," from the string. i.e
const img = base64Data.replace(/^data:image\/png;base64,/, "");
Then convert the image from base64.
const imgBuf = Buffer.from(img, 'base64');
At this point we have the image in binary. We can then get the pixels. Try with this module https://github.com/scijs/get-pixels.
const getPixels = require("get-pixels");
getPixels(imgBuf, "image/png", function(err, pixels) {
if (err) {
console.log("Bad image path")
return
}
console.log("got pixels")
});

I think you can acheive that by doing so:
var b64str;
var buf = new Buffer(b64str, 'base64');
As Buffer objects are used to represent a fixed-length sequence of bytes

Related

How to show binary photo inside <img> tag

I am wondering if there is a way to use binary photo that i get from a server.
So for example I have this kind of url mybackend.com/get_image?id=1 and as a response I get a photo.
This is the response that I console.log:
�PNG
IHDR
ռ��IDATx�� ���
U��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“�HL}/�MwIEND�B`�
This value that i logged is binary i guess.
When I set <img src="mybackend.com/get_image?id=1" /> it works because browser first makes GET network call and makes this binary show probably under the hood.
I found bunch of answers regarding this and it usually says that I need to convert this into base64 and than insert it into src attribute. But they don't bring me near to showing photo.
Thanks
const base64Image = btoa(binaryImage);
const imageTag = `<img src="data:image/png,${base64Image}" />`
btoa has a caveat - the binary must have a specific string representation. The MDN article explains how to work around this:
// convert a Unicode string to a string in which
// each 16-bit unit occupies only one byte
function toBinary(string) {
const codeUnits = new Uint16Array(string.length);
for (let i = 0; i < codeUnits.length; i++) {
codeUnits[i] = string.charCodeAt(i);
}
return String.fromCharCode(...new Uint8Array(codeUnits.buffer));
}
// a string that contains characters occupying > 1 byte
const myString = "☸☹☺☻☼☾☿";
const converted = toBinary(myString);
const encoded = btoa(converted);
console.log(encoded); // OCY5JjomOyY8Jj4mPyY=
Though it may be easier to simply use a library which can do this out of the box, such as js-base64
<script src="https://cdn.jsdelivr.net/npm/js-base64#3.6.0/base64.min.js"></script>
Base64.fromUint8Array(binaryImage);

NodeJS converting Base64 String To jpeg image - NodeJS or mysql

I have stored jpeg image in mysql database in format longblob...now i read that longblob and would like to retrieve jpeg image to see how it looks..i get only base64 string so how to convert it in mysql or node js?
Here is my base64 string that is read from database:
https:// jsfiddle.net/ ej4c9pk3/
How to decode it to jpeg image so that i can see how it looks and then i can display it on web page.
Image base64 text is on the link...so you could see it and try it to decode to jpeg.
I write function that convert Base64 String to Base64 Hex String and now it is correct converted to display as BLOB png image...but problem is when i open field in DB Browser for SQLite it writes this converted value as Text, and must be written as binary (so that the image will be recognized and displayed when i choose Image in DB Browser for SQLIte...so the question is how can i insert Base64 Hex String to SQLite3 Database as binary?
Here is my code for insert:
/* GET - channels_logo */
for (var i in rows) {
/* WRITE - table channels_logo */
db.prepare('INSERT INTO channels_logo (logo_id, logo_channel, logo_png) VALUES
("'+rows[i].id+'", "'+rows[i].channel+'", "'+(base64toHex(new Buffer(rows[i].logo).toString()))+'")').run();
};
function base64toHex(base64) {
/* DEFINE - variables */
var raw = atob(base64);
var HEX = '';
for (i = 0; i < raw.length; i++) {
var _hex = raw.charCodeAt(i).toString(16)
HEX += (_hex.length==2?_hex:'0'+_hex);
};
return HEX.toUpperCase();
};
[![Using this insert code is inserted as Text:][1]][1]
https://i.stack.imgur.com/iZ2A1.jpg
[![And needs to be binary inserted and now it looks ok (i just erase text and copy text inserted into binary and now it works)][1]][1]
https://i.stack.imgur.com/ZzGTU.jpg
So i see that SQLite3 displays inserted Base64 Hex As Text not binary...what i need to write in insert statement to insert it as binary?

Valid base64 string for a jpeg

Is this a valid base64 string of jpeg?
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD
That characters in question are the '/9j/' after the 'base64,'
I'm guessing it could be to do with compression as it's JPEG.
As when compared to a base64 string of a png, the pattern is different, i.e. the character pattern is different from above.
data:image/png;base64,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
The origin of my problem is that i'm base64 encoding an array of canvases into .jpeg's and .png's - the .png's output fine whereas the .jpeg's always output as black boxes.
I'm capturing the images using html2canvas (javascript), they are 'images' of html nodes, I have played around with transparency issues, like setting the background of the dom nodes to white.
All of the jpeg images I am encoding have this '/9j/' pattern, i'm generating them in a loop so it may well be a common property all the images have.
I can't seem to find a decent tool online to validate base64 strings either.
Let's check:
$ echo -n '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID' | base64 --decode | file -
/dev/stdin: JPEG image data, JFIF standard 1.01
So it's recognized as a valid JPEG header (this doesn't necessarily mean that the entire JPEG data is valid, though, but at least it looks like a JPEG).
The difference between the JPEG data and the PNG data is because the file formats are different. Also, / is a valid character in Base64.
You can do a js check. Not sure how efficient it will be.
function checkImage( str ) {
var _img = document.createElement( 'img' );
_img.onerror = function() {
reportError(str);
}
_img.src = str;
}
function reportError(str) {
alert('Invalid image :' + str)
}
Hope it helps.
The file type can be identified by magic number. With a JPEG the magic number is “ff d8 ff” at offset 0. If you encode this to Base64, you'll always get “/9j/”
First we have to specify what is valid:
An totally legit image with no errors when gets rendered to image.
As long as it can show something visually, ignore the errors.(may have resolution or size issues but we don't care.)
In the first case, we can use onerror to bind events.The function checks if the base64 string can be converted to a <img> without any error. It will not only catch all the broken images but also the ones can be displayed but have errors.
let checkImage = (str) => {
let img = new Image();
img.src = str;
img.onerror = () => { //do something }
}
Or if we just want something can be rendered as image no matter what errors it gives us, we can ignore the errors and directly check if the size of the image is available.
let checkImage = (str) => {
let img = new Image();
img.src = str;
img.onload= () => {
if(img.width==0 || img.height==0){ //do something}
}
}

Javascript - what files type choose to save pixels data?

How to save (with the lowest file size) pixels data in javascript?
For now I'm using JSON and it is looking like this:
{"SIZE":[120,120],
"FRAME":["SHINE",""],
"LEDS":[
{"X":0,"Y":0,"R":16,"G":30,"B":58},
{"X":1,"Y":0,"R":13,"G":23,"B":43},
{"X":2,"Y":0,"R":14,"G":26,"B":50},
etc...
So for little pictures like 16x16, 90x32 the file size is ok but now I need do pictures 120x120 and file size is around 500kb. Is there any better solution for that?
You have few options to send your pixels data in minimal size. The easiest way is to pack all this pixel information in one binary data.
MIME type
You can send image data with http request using i.e. image/bmp MIME type. You can view https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data to check how to read that kind of data
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
// do something with each byte in the array
}
}
};
oReq.send(null);
Convert to binary and send it as BASE64
You can convert your pixels data to binary format (similar to pure BMP) and then use BASE64 algorithm to represent it with letters. Then you can send it with regular JSON
This is very good explanation about packing complex structures to binary: http://danthedev.com/2015/07/25/binary-in-javascript/

How do I store a javascript string in byte format and for later retrieval in string form?

I want to generate a file containing strings alongside Float32Arrays in my web app. I can write this data into a blob and then a file like this:
var myFirstFloat32Array = new Float32Array([42, 1, 2, 3]);
var myString = 'This is my string. It is a beautiful string.';
var blob = new Blob([
new Uint8Array([myFloat32Array.length]), // Store the size.
myFloat32Array,
new Uint8Array([myString.length]), // Store the size.
myString);
var downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(blob);
downloadLink.download = 'generatedFile';
downloadLink.innerHTML = 'Click to download generated file.';
So ... that successfully writes the file, but how do I read the string following the float 32 array?
I can read the first float32 array easily by reading the number from the first 4 bytes (which gives me the size of the array) and then constructing a Float32Array of that length.
However, how do I read the string? The string could contain characters outside of the ASCII range, so I can't just btoa the string, convert to a Uint8Array, and then write it.
Maybe I could convert the string to a blob first, get its size from the blob, and then somehow decode it later while reading (but how do I know the character encoding used later)?
What's the standard way to store string data alongside byte data in javascript for later decoding?

Categories