Blob's DataUri vs Base64 string DataUri - javascript

As you know & stated in w3 it is possible to create a url for a Blob object in javascript by using Blob's createObjectUrl. On the other hand, if we have a data as a Base64 encoded string we can present it as a Url with the format "data[MIMEType];base64,[data>]".
Let's suppose that I have a base64 encoded string that was generated from an image that is very popular on these days :) "The red dot" image in wikipedia.
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
I'm 100% sure that if I create a URL conforming the Data URI Scheme as stated above, then, I'll be able to put a link element and download it from the browser: please see the code example below:
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
var reddotLink = document.createElement("a");
reddotLink.target = "_blank";
reddotLink.href = "data:image/png;base64," + reddotB64;
document.body.appendChild(reddotLink);
reddotLink.click();
document.body.removeChild(reddotLink);
This works prettywell and displays the image in a new tab. On the other hand I'll try to create the link by using Blob as follow:
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
var reddotBlob = new Blob([atob(reddotB64)], { type: 'image/png' });
var reddotLink = document.createElement("a");
reddotLink.target = "_blank";
reddotLink.href = URL.createObjectURL(reddotBlob);
document.body.appendChild(reddotLink);
reddotLink.click();
document.body.removeChild(reddotLink);
This code is decoding base64 encoded string variable reddotB64 via atob function. And then, creating a Blob object and continues with URL.createObjectURL function. In that case, since I've decoded reddotB64 from base64 to binary and created a Blob of type image/png and then create object url from that I expect it to work but it's not working.
Do you have a clue why it's not working? Or am I missing anything on the standards? Or doing something wrong in Javascript?

Here is the answer. Looks like it is an encoding issue. In order to convert/decode Base64 string to binary(UInt8Array/byte) using atob is not enough. After using atob it is required to use UTF-16 character code: and we achieve this by using charCodeAt function for every character in the decoded string. As a result we get UTF-16 encoded binary string which is definately working. Just create a Blob and then call URL.createObjectURL.

Related

What to use instead of Buffer(bitmap)

I'm using the following method to convert files into base64 encoding and it's been working fine for a long time, but I see now that Buffer is depricated.
// function to encode file data to base64 encoded string
function base64_encode(file) {
var bitmap = fs.readFileSync(file);
// convert binary data to base64 encoded string
return new Buffer(bitmap).toString("base64");
}
let base64String = base64_encode("Document.png");
Can someone please help me modify this to work with the new suggested method as I'm not sure how to modify it myself?
Thank you so much in advance.
It is not Buffer that is deprecated but its constructor, so instead of new Buffer() you use e.g. Buffer.from.
However fs.readFileSync already returns a Buffer if no encoding is specified, so there is not really a need to pass that to another buffer. Instead you can do return fs.readFileSync(file).toString("base64")
Using the Sync part of the API is most of the time something would like to avoid and if possible switch over to the promise-based API.

Base64 Decode embedded PDF in Typescript

Within an XML file we have a base64 encoded String representing a PDF file, that contains some table representations, i.e. similar to this example. When decoding the base64 string of that PDF document (i.e. such as this), we end up with a PDF document of 66 kB in size, which can be opened in any PDF viewer correctly.
On trying to decode that same base64 encoded string with Buffer in TypeScript (within a VSCode extension), i.e. with the functions below:
function decodeBase64(base64String: string): string {
const buf: Buffer = Buffer.from(base64String, "base64");
return buf.toString();
}
// the base64 encoded string is usually extracted from an XML file directly
// for testing purposes we load that base64 encoded string from a local file
const base64Enc: string = fs.readFileSync(".../base64Enc.txt", "ascii");
const base64Decoded: string = decodeBase64(base64Enc);
fs.writeFileSync(".../table.pdf", base64Decoded);
we end up with a PDF of 109 kB in size and a document that can't be opened using PDF viewers.
For a simple PDF, such as this one, with a base64 encoded string representation like this, the code above works and the PDF can be read in any PDF viewer.
I've also tried to directly read in the locally stored base64 encoded representation of the PDF file using
const buffer: string | Buffer = fs.readFileSync(".../base64Enc.txt", "base64");
though isn't producing something useful either.
Even with a slight adaptation of this suggestion, due to atob(...) not being present (with suggestions to replace atob with Buffer), which ended up in a code like this:
const buffer: string = fs.readFileSync(".../base64Enc.txt", "ascii");
// atob(...) is not present, other answers suggest to use Buffer for conversion
const binary: string = Buffer.from(buffer, 'base64').toString();
const arrayBuffer: ArrayBuffer = new ArrayBuffer(binary.length);
const uintArray: Uint8Array = new Uint8Array(arrayBuffer);
for (let i: number = 0; i < binary.length; i++) {
uintArray[i] = binary.charCodeAt(i);
}
const decoded: string = Buffer.from(uintArray.buffer).toString();
fs.writeFileSync(".../table.pdf", decoded);
I'm not ending up with a readable PDF. The "decoded" table.pdf sample ends up with 109 kB in size.
What am I doing wrong here? How can I decode a PDF such as the table.pdf sample to obtain a readable PDF document, similar to the functionality provided by Notepad++?
Borrowing heavily from answers to How to get an array from ArrayBuffer?, if you get a Uint8Array right from the Buffer using the Uint8Array constructor:
const buffer: string = fs.readFileSync(".../base64Enc.txt", "ascii");
const uintArray: Uint8Array = new Uint8Array(Buffer.from(buffer, 'base64'));
fs.writeFileSync(".../table.pdf", uintArray);
Writing the Uint8Array directly to the file guarantees there's no corruption due to encoding changes from moving to and from strings.
Just a note: the Uint8Array points to the same internal array of bytes as the Buffer. Not that it matters in this case, since this code doesn't reference the Buffer outside of the constructor, but in case someone decides to create a new variable for the output of Buffer.from(buffer, 'base64').

How to parse a DICOM in JavaScript using cornerstone?

I'm trying to parse a dicom file in javascript. I download the dicom with axios, the data I get is a string that looks like this:
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000DICM\u0002\u0000\u0000\u0000UL\u0004\u0000�\u0000\u0000\u0000\u0002\u0000\u0001\u0000OB\u0000\u0000\u0002\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0002\u0000UI\u001a\u00001.2.840.10008.5.1.4.1.1.1\u0000\u0002\u0000\u0003\u0000UI0\u00001.3.12.2.1104.5.3.33.1388.11.201703201514180234\u0000\u0002\u0000\u0010\u0000UI\u0014\u00001.2.840.10008.1.2.1\u0000\u0002\u0000\u0012\u0000UI\u0014\u00001.3.12.2.1107.5.3.4\u0000\u0002\u0000\u0013\u0000SH\u000e\u0000Siemens_FLC_60\u0008\u0000\u0005\u0000CS\n\u0000ISO_IR 100\u0008\u0000\u0008\u0000CS\u0016\u0000ORIGINAL\\PRIMARY\\\\RAD \u0008\u0000\u0016\u0000UI\u001a\u00001.2.840.11008.5.1.4.1.1.1\u0000\u0008\u0000\u0018\u0000UI0\u00001.3.12.2.1417.5.3.33.1398.11.201703201514180234\u0000\u0008\u0000 \u0000DA\u0008\u000020170320\u0008\u0000!\u0000DA\u0008\u000020170320\u0008\u0000\"\u0000DA\u0008\u000020170320\u0008\u0000#\u0000DA\u0008\u000020170320\u0008\u00000\u0000TM\u0006\u0000151324\u0008\u00001\u0000TM\u000c\u0000151418.0234 \u0008\u00002\u0000TM\u000c\u0000151418.0234 \u0008\u00003\u0000TM\u000c\u0000151418.0234 \u0008\u0000P\u0000SH\u0000\u0000\u0008\u0000`\u0000CS\u0002\u0000CR\u0008\u0000p\u0000LO\u0008\u0000SIEMENS \u0008\u0000�\u0000LO\u0018\u0000CH Foo Bar - PARIS\u0008\u0000�\u0000PN\u0000\u0000\u0008\u0000\u0010\u0010SH\u0010\u0000AX10094200-1398 \u0008\u00000\u0010LO\n\u0000LDQK001 RC\u0008\u00002\u0010SQ\u0000\u00000\u0000\u0000\u0000��\u0000�(\u0000\u0000\u0000\u0008\u0000\u0000\u0001SH\u0002\u0000RC\u0008\u0000\u0002\u0001SH\u0004\u0000QDOC\u0008\u0000\u0004\u0001LO\n\u0000LDQK001 RC\u0008\u0000>\u0010LO\u001a\u0000RAD_Rachis Cerv. F 3/4 AP \u0008\u0000#\u0010LO\u0002\u000077\u0008\u0000�\u0010LO\u0000\u0000\u0008\u0000�\u0010LO\u0016\u0000Fluorospot Compact FD \u0008\u0000\u0010\u0011SQ\u0000\u0000V\u0000\u0000\u0000��\u0000�N\u0000\u0000\u0000\u0008\u0000P\u0011UI\u0018\u00001.2.840.10008.3.1.2.3.1\u0000\u0008\u0000U\u0011UI&\u00001.3.51.0.1.1.10.2.1.94.2417819.2393805\u0008\u0000\u0011\u0011SQ\u0000\u0000Z\u0000\u0000\u0000��\u0000�R\u0000\u0000\u0000\u0008\u0000P\u0011UI\u0018\u00001.2.840.10008.…"
I need to decode this to a json format (or a readable format like dcmdump does for example) in a js script.
I have tried to use the cornerstone dicom parser (https://github.com/cornerstonejs/dicomParser) like this:
import * as dicomParser from 'dicom-parser';
let enc = new TextEncoder("utf-8")
let arr8 = enc.encode(dicom_data).map(Number)
console.log(dicomParser.parseDicom(arr8))
But I get the following error:
"uncaught exception: dicomParser.parseDicom: missing required meta header attribute 0002,0010".
Does anyone know a simple way to do this?
I am not familiar with JavaScript. However, the attribute (0002,0010 = Transfer Syntax UID) is present in the header.
But the way you handle the data does not appear right to me.
The data is not in DICOM format.
Instead, it seems to be encoded as a string in which non-printable characters have been converted to \u. By this, one byte in the header has been expanded to a two-byte hex number. You should try to obtain the file in its original binary representation
Transcoding to UTF-8 does not appear appropriate to me. Some DICOM attributes contain a value in binary representation. Plus the attributes "addresses" (group, element) and their length are encoded in binary format. Transcoding to UTF-8 will destroy this.
So I think it should work once you pass the original binary DICOM file to the dicomParser without applying any modifications before the parsing.
Well, I never used the toolkit you mentioned in question. I did a simple google search and found github with the documentation.
Documentation also provides a sample to dicom dump. You can view the source of this page in your browser which will provide you complete code to print dump.
Following is snippet:
var reader = new FileReader();
reader.onload = function(file) {
var arrayBuffer = reader.result;
// Here we have the file data as an ArrayBuffer. dicomParser requires as input a
// Uint8Array so we create that here
var byteArray = new Uint8Array(arrayBuffer);
var kb = byteArray.length / 1024;
var mb = kb / 1024;
var byteStr = mb > 1 ? mb.toFixed(3) + " MB" : kb.toFixed(0) + " KB";

Angular: Convert base64 string to Byte Array in IE

I am trying to convert a base64 string to byte array and open it as a pdf file in IE. The only problem is atob is not supported in IE, so trying to use Buffer like this:
let b64Data = myBase64Url.split(',', 2)[1];
var byteArray = new Buffer(b64Data ,'base64').toString('binary');
var blob = new Blob([byteArray], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(blob);
I am getting a popup successfully to open the file
But the file is corrupted
What am i doing wrong ? Is there a better way to convert base64 to byte array in IE ?
In order for the base64 to be properly decoded, it must be only the base64 data, i.e. no mimetype information preceding it.
You will also need to remove .toString('binary') so that you're passing a buffer instead of a string.

How to send base64 encoded image string into JSON object in javascript?

I wanted to convert a image file into JSON object in javascript.
So I have converted image into a string using base64 encoding.
How to convert this string to JSON object?
Simple, set value to an keyObj.
var base64String = 'data:image/png;base64....'
var imgObj = {
url: base64String
}
<img src=''+ imgObj.url +''/>
I would create a new Image() and set the src to the image. Then onload of the image, draw it to a canvas (which can be in memory, doesn't need to be in the DOM), and from there use toDataURL(). See this page for more details: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL

Categories