Decoding Base64 to an Image in ColdFusion - javascript

A while back I posted a question regarding decoding a Base64 string into a image to store in my ColdFusion application. Here's the link.
I was getting the string from a Topaz signature pad that had an NAPI browser plugin that created the Base64 string. I would then take that string and use the following code to decode it:
<cfscript>
binaryValue = binaryDecode( form.SigImgData, "hex" );
FileWrite("c:\Inetpub\wwwroot\signatures\#fullfilename#.bmp", "#binaryValue#");
</cfscript>
I would then store it to disk and display it in the browser using the tag.
Well now that Google Chrome has discontinued support for NAPI plugins, I am now creating the Base64 string using JavaScript supplied from the signature pad manufacturer. I can successfully create the Base64 string using the new JS but when I plug the string into my same CFScript code from above, it creates a non-usable image. Basically a corrupted image file.
Here is an example of my Base64 string:
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
I found a site that allows you to past a string into a box and decode it to the original image and it seems to decode it fine.
As per the suggestions, I have tried the following modification:
<cfset image = imageReadBase64("data:image/bmp;base64,form.SigImgData")>
<cfimage
source="#image#"
destination="c:\Inetpub\wwwroot\signatures\#fullfilename#.bmp"
action="write">
But I receive the following error:
Can not decode string "form.SigImgData".
The input string is not base64-encoded.

As your binary data doesn't have image headers(Contains Mime type e.g. data:image/png;base64 for png image) so you can simply use imageReadBase64 like this:
<cfset image = imageReadBase64(form.SigImgData)>
<cfimage
source="#image#"
destination="c:\Inetpub\wwwroot\signatures\#fullfilename#.bmp"
action="write">
I tried it locally with same code. Is this your image?

With a Base64 string you can use this function to get an image:
ImageReadBase64(yourstring)
Example:
<cfset image = ImageReadBase64(form.SigImgData)>
<cfimage source="#image#" destination="C:\Inetpub\wwwroot\signatures\#fullfilename#.bmp" action="write">

Related

Blob's DataUri vs Base64 string DataUri

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.

Unfamiliar encoding of string (Base64?) - Trying to save and use string contents of .3gp file

I'm attempting to read the contents of a .3gp file as a string to later save that string as a valid .3gp file once again.
When I read the string contents, it seems to be differently encoded than when I look at the string contents of a .3gp file on Windows.
Here is an excerpt from the beginning of the string contents I received:
\u0000\u0000\u0000\u0018ftyp3gp4\u0000\u0000\u0000\u0000isom3gp4\u0000\u0000\t�moov\u0000\u0000\u0000lmvhd\u0000\u0000\u0000\u0000�o�K�o�K\u0000\u0000\u0003�\u0000\u0000 �\u0000\u0001\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\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\u0002\u0000\u0000\u0000�meta\u0000\u0000\u0000!hdlr\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000mdta\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000dkeys\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u001bmdtacom.android.version\u0000\u0000\u0000 mdtacom.android.manufacturer\u0000\u0000\u0000\u0019mdtacom.android.model\u0000\u0000\u0000`ilst\u0000\u0000\u0000\u001d\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0015data\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u00008.1.0\u0000\u0000\u0000\u001e\u0000\u0000\u0000\u0002\u0000\u0000\u0000\u0016data\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0000Google\u0000\u0000\u0000\u001d\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u0015data\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0000Pixel\u0000\u0000\b1trak\u0000\u0000\u0000\tkhd\u0000\u0000\u0000\u0007�o�K�o�K\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000\u0000
A valid .3gp file's contents when opened in Notepad on Windows look like the following excerpt shows:
ftyp3gp4 isomiso23gp4 free -kmdat<§!4ˆÉ‡€èÕ_ÒA#€ vÞm¾ ©°Ï#; €$::=>zá!3³³Ó×ùžŸ8HLììøýÂBg‡‡çî<f¦§QÓ3366sŽ™™‘©£œtÌLÌ#f\bé2ÒÂòçXÉ••–:ÅÌ œ¬¥Ú.däÅ$îñS%$&%w‰š|„ÐѤ&€‚ˆŠÝ#4TVé  £#7ÈÍ ºFˆGУ#7ÈÄ„}¾Fh((ˆò2 ¡ *Šïšy¾AÉùñí*W…ÿŠ£MÛJ…È»4ò\ÇÃú£×©ÎC—‰ñôŸü™Iœž(²z™¦ÿå;õÕ®]ÁB>ªÇŠGma,H(â > tNÊvt~b$ _W¿¢4•¶Ñ9Ñ_â©¥„ñž—÷ ¡æñ¹ ͨéZç£JmdÁ÷•ƒ_sÊvîü¾òµÉÒ̃S±,yðÆ4¼?ü0MU†ÝKÞ £ÏÊÑ#£n1t”ØâX<Oã£ïBAx!—O²×ÈáÄ’àB/¾a¿LÔÐàÝÊ:f†fÆÎqÓ1043s™yq‘‹¤dËJËËc&VRZXë2‚r¢—h©¢£%%7IJŽŽ––}¶J4„ƒé‰²SHIMMm’‰$úJjkd•O¥MMm’šRJjklœÒRSS[dãHG>˜–Ý$ÝÈ-ò¥jýš§;‡’ÎBýT+Un[uÎÁAøn(HÀCñöÈBOǪÆ'#–¨ºAÜØ|qí½"yOÕ]1¨ò¿cm
€<IT%´¡$h I/#ô˜Õ4‘#èõI– BŠtóÊÇʽoAË}PÊ’ž!/.QퟪóÍæjF#ÀzP>#B®—ùUôùbi%VýVüw»ÞÓÎ
àñ^{s$t~/ÕÕj•+ËTU{k“¦ÏNÕ
ËÇíE°2->ú¸\¬w?ù¸:“‰NÏt‰’XÇIP5f‰P^€9TT%LªTŽÆ°ÁXôKþÌÁÖLìé ùÆ>g'§Ž1ó65:9rŽ™¡™¹«œtÌL
#&^\bé2ÂÂâçXÈ“O¦¨(¶IQ8úyõ%6¹J(P>¦¦×'…ê'ÕOµÉõê'ÕOªŸj”ê'ÔOªŸU>×)ÔO¨ŸU>ª}®N5ꪒsPNTSl“šrjš‹d›4ĵì‹:Kjïf–”žœâ•›ÈÕ‚Ÿè^òÀÕU kËâ§Ù|lœ€Á°aÿ|0ÇõPþ7s÷ÕE6zHä'•ÕûiǔŠ£œÒ¿Úó}TªP­²tÅ}|A‹çøª¢‡Â ü¹GUÉSÜ{TH¯|y'Æ’A€
÷à‘».Óp€ÀyßQ&,³#K™• û|ŒÐÑ›äfzv€~á!3£ƒÓ·ù›šœœ9GÌÐÌØÙÎ6f&†n‘³TUWYk“šª²ÒÓT¥•Ï«Ÿ[>¸Õ)Eƒë×Zef²²ººÕ)5••ÕÖ©I¬¬®®µJÑdú¹õÕ¶¹Z+ŸV>¶¶×'Ecê§Ö–Zå,¨}LúÁõ†ÉI©©
I believe the type of string I've received is Base64 based on some searches I did, and I've noticed processing the string in javascript with unescape(encodeURIComponent()) gives me a somewhat similar result to the valid .3gp contents, but it's not exact.
Does anyone know what I need to do to the string to make it look like the valid .3gp file string contents in Windows? Is this even possible at all?
Since you only need to be able to download it, holding it as a string is fine. If you can use a Node Buffer instead, it will be a bit more robust, but javascript string should carry all of your bytes through.
Be careful how you handle the download api to make sure it doesn't get turned into something else.

websocket api - image encoding yields no image type on client side

I have a web socket server on tomcat 8 with the following binary use:
sess.getBasicRemote().sendBinary(bf);
where bf is a simple image to bytes conversion as follows:
BufferedImage img = ImageIO.read(...);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( img, "png", baos );
ByteBuffer bf = ByteBuffer.wrap(baos.toByteArray());
this code ends up in the the client side (javascript) as a blob and eventually rendered as an image in the browser and this seems to work just fine.
the only thing that's strange is the the image is rendered typeless as:
data:;base64,iVBORw0KGgoAAAA......== without the type (image/png).
if I use online encoders for the same image I will get:
data:image/png;base64,iVBORw0KGgoAAAA......== (notice the image/png type)
and so my question is why is that?
is my image to byte conversion wrong? like I said, the image is displayed fine it just is missing the type.
Note that the data send from the java websocket server is not encoded with base 64, its something I do on the client side (via JS's FileReader.readAsDataURL(blob) - very common).
thanks a lot and sorry for the long post
No, your image to byte array conversion is not wrong. Byte array conversion treats the images as a binary stream, it has nothing to do with the MediaType contained in it.
The type that you want to see is a Data URI media type.
Normal java code for converting files to byte array won't give you data URL scheme compliant URL.
From the RFC
data:[<mediatype>][;base64],
The <mediatype> is an Internet media type specification (with
optional parameters.) The appearance of ";base64" means that the data
is encoded as base64. Without ";base64", the data (as a sequence of
octets) is represented using ASCII encoding for octets inside the
range of safe URL characters and using the standard %xx hex encoding
of URLs for octets outside that range. If <mediatype> is omitted, it
defaults to text/plain;charset=US-ASCII. As a shorthand,
"text/plain" can be omitted but the charset parameter supplied.
RFC source
When you're creating the Blob object in Javascript you have an option to pass MediaType to it so that when you read it using FileReader.readAsDataURL it fills the appropriate media type.
Example is below
var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
Source
You probably don't need BufferedImage in your code, simple file read should suffice.
Following is equivalent of your code with Apache FileUtils.
ByteBuffer bf = ByteBuffer.wrap(FileUtils.readFileToByteArray('test.jpg'));

DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript

I'm trying to decode a base64 string for an image back into binary so it can be downloaded and displayed locally by an OS.
The string I have successfully renders when put as the src of an HTML IMG element with the data URI preface (data: img/png;base64, ) but when using the atob function or a goog closure function it fails.
However decoding succeeds when put in here: http://www.base64decode.org/
Any ideas?
EDIT:
I successfully got it to decode with another library other than the built-in JS function. But, it still won't open locally - on a Mac says it's damaged or in an unknown format and can't get opened.
The code is just something like:
imgEl.src = 'data:img/png;base64,' + contentStr; //this displays successfully
decodedStr = window.atob(contentStr); //this throws the invalid char exception but i just
//used a different script to get it decode successfully but still won't display locally
the base64 string itself is too long to display here (limit is 30,000 characters)
I was just banging my head against the wall on this one for awhile.
There are a couple of possible causes to the problem. 1) Utf-8 problems. There's a good write up + a solution for that here.
In my case, I also had to make sure all the whitespace was out of the string before passing it to atob. e.g.
function decodeFromBase64(input) {
input = input.replace(/\s/g, '');
return atob(input);
}
What was really frustrating was that the base64 parsed correctly using the base64 library in python, but not in JS.
I had to remove the data:audio/wav;base64, in front of the b64, as this was given as part of the b64.
var data = b64Data.substring(b64Data.indexOf(',')+1);
var processed = atob(data);

Send ByteArray to JavaScript

How to send a jpg image as ByteArray from as3 to javascript? And how to convert ByteArray to image in javascript?
Take your DisplayObject (Sprite/MovieClip/whatever) and convert it to a BitmapData:
myBitmapData.draw(mySprite);
Convert that to a PNG using adobe's AS3CoreLib
myByteArray = PNGEncoder.encode(myBitmapData);
Convert that to Base64 using Flex's Base64Encoder:
myBase64Encoder.encodeBytes(myByteArray);
Then export actionscript variables to Javascript using ExternalInterface.
The JavaScript and DOM implementations of current web browsers don't really have good mechanisms for doing this sort of thing.
Your best bet is to have your AS3 return a DATA protocol URI with a base64-encoded version of the image. Modern browsers (IE8+, FF2+, etc) will accept a DATA URI as the SRC of an IMG tag and will render the image contained therein.
http://en.wikipedia.org/wiki/Data_URI_scheme
You'll have to have a AS3 expert explain how to turn an byte-array into a base64-encoded string, but it cannot be that hard.
There is a method in this class that does that:
https://github.com/monkeypunch3/flexcapacitor/blob/master/MainLibrary/src/com/flexcapacitor/utils/DisplayObjectUtils.as
calling
var data:String = DisplayObjectUtils.getBase64ImageDataString();
will return this string:
data:image/png;base64,...
You then set the src of an img in html to that value.

Categories