3

Struggling to convert a base64 image captured using a webcam into a jpeg for upload.

The following capture / display photo works (note that I am using webcam.min.js (which returns base64) and not webcam.js (which returns jpeg but relies on Flash) -

function take_snapshot() {
Webcam.snap( function(data_uri) {
// display results in page
document.getElementById('upload_results').innerHTML = 
'<img id="imageprev" src="'+data_uri+'"/>';
} );
}

I have tried the following, which may or may not be converting the base 64image to a blob -

function saveSnap(){
var base64image = document.getElementById("imageprev").src;
alert(base64image)
                                
                                                               
    // convert base64 to raw binary data held in a string
    var byteString = atob(base64image.split(',')[1]);
    // separate out the mime component
    var mimeString = base64image.split(',')[0].split(':')[1].split(';')[0];
    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);
    var dw = new DataView(ab);
    for(var i = 0; i < byteString.length; i++) {
    dw.setUint8(i, byteString.charCodeAt(i));
                                                                    alert("arrived here");
                                                                    
    // write the ArrayBuffer to a blob, and you're done
    return new Blob([ab], {type: mimeString});
    }

And this doesn't do anything, except halt the jsp

let image = new Image();
image.src = base64image;
document.body.appendChild(image);

How do I get / see / extract the actual jpeg file so I can then upload it (it must be something like number.jpeg)

JDK6 / Javascript (no php please)

Any thoughts appreciated.

Regards Ralph

Ralph
  • 115
  • 1
  • 13
  • 1
    Does this answer your question? [How to convert dataURL to file object in javascript?](https://stackoverflow.com/questions/6850276/how-to-convert-dataurl-to-file-object-in-javascript) – Njuguna Mureithi Nov 18 '20 at 10:55
  • Neither do, webcam.js returns a data URL (this is what I was using but webcam.js reverts to using Flash), had to switch to webcam.min.js which returns a base64 string – Ralph Nov 18 '20 at 10:57
  • After much fiddling with some of the examples I may be turning the base64 into a blob but I have no idea how to convert a blob into a jpeg, or even if I should (I need a jpeg uploaded to the server) – Ralph Nov 18 '20 at 11:57
  • @Ralph If you convert the base64 encoded image to a "blob" the blob contains/is the binary jpeg image. – Marc Nov 18 '20 at 12:02
  • Thanks Marc, How do I get / see the jpeg (filename extension etc) from the blob ? I need the actual jpeg which I can then upload. – Ralph Nov 18 '20 at 12:06
  • Please post all the code – Njuguna Mureithi Nov 18 '20 at 12:07
  • I have edited the original post, feedback appreciated. – Ralph Nov 18 '20 at 12:16
  • @Ralph: the base64 data encodes the *content* of a file. it does *not* encode a file name (and thus also no extension). If you need something, you can make something up (for example always call it "webcam.jpg" or something like that). – Joachim Sauer Nov 18 '20 at 12:18
  • I know, but webcam.min.js returns base64 and I need to convert that to a proper / real jpeg file so I can upload it to a server. Hence my attempt. Examples seem to suggest I have to convert the base64 to a blob first but that is quite useless if I cant then get a real jpeg file by running something on the blob. – Ralph Nov 18 '20 at 12:31

3 Answers3

2

Create an image object and put the base64 as its source.

let image = new Image();
image.src = 'data:image/png;base64,iVBORw0K...';
document.body.appendChild(image);

var aFilePartss = [image];
var oMyBlob = new Blob(aFileParts, {type : 'image/png'});
// window.open(URL.createObjectURL(oMyBlob));

var fd = new FormData();
fd.append('data', oMyBlob);
$.ajax({
    type: 'POST',
    url: '/upload.php',
    data: fd,
}).done(function(data) {
    console.log(data);
});
Mohiuddin Khan
  • 513
  • 1
  • 5
  • 13
  • Thanks Mohiuddin, if my base64image name is 'base64image' please expplian exactly where and how in your example code I need to reference it and what the output will be – Ralph Nov 18 '20 at 12:35
  • image.src = base64image and you'll get the raw image in "image" variable. It will create a raw img tag on you html page. Do you need make a compressed png file and download it?? – Mohiuddin Khan Nov 18 '20 at 12:46
  • I need a jpeg so I can upload a real photo to the server part – Ralph Nov 18 '20 at 12:50
  • Thanks again, the window opens with the photo shown. How do I reference that in my code so my server can then upload it (i.e. a physical jpeg file). Do I just reference oMyBlob ? – Ralph Nov 18 '20 at 13:09
  • you can upload the blob file with ajax request, updated the answer again – Mohiuddin Khan Nov 18 '20 at 13:13
  • Thanks, but I dont want to use php, I have another function in an 'update asset' jsp which uploads jpegs. I seem to be heading nowhere which ia rather sad. – Ralph Nov 18 '20 at 13:16
1

Here is the basics you need to convert to blob and upload.

const MOCK_DATA_URL = `data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEVBMTczNDg3QzA5MTFFNjk3ODM5NjQyRjE2RjA3QTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEVBMTczNDk3QzA5MTFFNjk3ODM5NjQyRjE2RjA3QTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRUExNzM0NjdDMDkxMUU2OTc4Mzk2NDJGMTZGMDdBOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRUExNzM0NzdDMDkxMUU2OTc4Mzk2NDJGMTZGMDdBOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjjUmssAAAGASURBVHjatJaxTsMwEIbpIzDA6FaMMPYJkDKzVYU+QFeEGPIKfYU8AETkCYI6wANkZQwIKRNDB1hA0Jrf0rk6WXZ8BvWkb4kv99vn89kDrfVexBSYgVNwDA7AN+jAK3gEd+AlGMGIBFDgFvzouK3JV/lihQTOwLtOtw9wIRG5pJn91Tbgqk9kSk7GViADrTD4HCyZ0NQnomi51sb0fUyCMQEbp2WpU67IjfNjwcYyoUDhjJVcZBjYBy40j4wXgaobWoe8Z6Y80CJBwFpunepIzt2AUgFjtXXshNXjVmMh+K+zzp/CMs0CqeuzrxSRpbOKfdCkiMTS1VBQ41uxMyQR2qbrXiiwYN3ACh1FDmsdK2Eu4J6Tlo31dYVtCY88h5ELZIJJ+IRMzBHfyJINrigNkt5VsRiub9nXICdsYyVd2NcVvA3ScE5t2rb5JuEeyZnAhmLt9NK63vX1O5Pe8XaPSuGq1uTrfUgMEp9EJ+CQvr+BJ/AAKvAcCiAR+bf9CjAAluzmdX4AEIIAAAAASUVORK5CYII=`

function takeSnapshotThenUpload() {
  //get datauri
  let blob = convertToBlob(MOCK_DATA_URL)
  return uploadFile(blob)

}



function convertToBlob(base64image) {
  // convert base64 to raw binary data held in a string
  var byteString = atob(base64image.split(',')[1]);
  // separate out the mime component
  var mimeString = base64image.split(',')[0].split(':')[1].split(';')[0];
  // write the bytes of the string to an ArrayBuffer
  var ab = new ArrayBuffer(byteString.length);
  var dw = new DataView(ab);
  for (var i = 0; i < byteString.length; i++) {
    dw.setUint8(i, byteString.charCodeAt(i));
    alert("arrived here");

    // write the ArrayBuffer to a blob, and you're done
    return new Blob([ab], {
      type: mimeString
    });
  }
}

function uploadFile(blob) {
  const formData = new FormData()
  formData.append('cancel.jpeg', blob)

  fetch('/saveImage', {
      method: 'POST',
      body: formData
    })
    .then(response => response.json())
    .then(data => {
      console.log(data)
    })
    .catch(error => {
      console.error(error)
    })
}
<button onclick="takeSnapshotThenUpload()">Take screenshot then upload</button>
Remember to fix your takeSnapshotThenUpload to something like:
<script src="webcam.js"></script>

<div id="my_camera" style="width:320px; height:240px;"></div>
<div id="my_result"></div>

<script language="JavaScript">
    Webcam.attach( '#my_camera' );
    
    function take_snapshot() {
        Webcam.snap( function(data_uri) {
            takeSnapshotThenUpload(data_uri)
        } );
    }
</script>

<a href="javascript:void(take_snapshot())">Take Snapshot</a>
Njuguna Mureithi
  • 3,506
  • 1
  • 21
  • 41
  • Thanks once again, I will spend some time fixing my code and analysing yours. This has saved some of my hair-tearing which has occured over many weeks of trying to fix this. Life was so much simpler when Flash was around, – Ralph Nov 18 '20 at 13:22
  • As an aside do you know whether you can use image_url (in webcam.js) and somehow force it not to use Flash as ths would avoid webcam.min.js and all of its pitfalls? – Ralph Nov 18 '20 at 14:27
  • I am not that versed with webcam.js. Have you tried HTML5 over Flash? Seems like you dont need Flash https://caniuse.com/?search=webcam – Njuguna Mureithi Nov 19 '20 at 11:35
  • webcam.js is HTML5, but uses Flash irrespective of whether the site is https or not. Anything else (where you use a datauri, then have to convert base64 to a blob and then fiddle with php and by some other magic you get a jpeg), seems ludicrous to me. I dont believe capturing an image and then outputting a jpeg can be that complicated. It is only 5 lines of code when using webcam.js. – Ralph Nov 21 '20 at 07:55
1

Example code for converting base64 to file (image/jpeg):

async base64ToFile(base64) {
  const res = await fetch(base64)
  const buf = await res.arrayBuffer()
  const file = new File([buf], "capture_camera.jpeg", {
    type: 'image/jpeg',
  })
  return file;
};
Oleg Barabanov
  • 2,468
  • 2
  • 8
  • 17
Skevin
  • 11
  • 2