19

How can I strip the EXIF data from an uploaded image through javascript? I am currently able to access the EXIF data using this exif-js plugin, like this:

EXIF.getData(oimg, function() {
    var orientation = EXIF.getTag(this, "Orientation");
});

However, I have not found any way to actually remove the Exif data, only to retrieve it.

More specifically, I am trying to do this to get rid of the orientation Exif data which rotates my image on certain browsers.

Praxis Ashelin
  • 5,137
  • 2
  • 20
  • 46
  • @alex It currently does not seem possible for me to use PHP for this task. Even if there is no native Javascript function that allows this, a plugin would be acceptable. How can I edit my question to be less broad? – Praxis Ashelin Dec 24 '14 at 14:35
  • @alex, also with nodejs, it's not that extreme that you would want to handle this with JS. Even if this question is not about that. – fejese Dec 24 '14 at 14:44

1 Answers1

27

Here is a little demo of it, select an image with orientation data to see how it looks with and with out it(modern browsers only).

http://jsfiddle.net/mowglisanu/frhwm2xe/3/

var input = document.querySelector('#erd');
input.addEventListener('change', load);
function load(){
    var fr = new FileReader();
    fr.onload = process;
    fr.readAsArrayBuffer(this.files[0]);
    document.querySelector('#orig').src = URL.createObjectURL(this.files[0]);
}
function process(){
    var dv = new DataView(this.result);
    var offset = 0, recess = 0;
    var pieces = [];
    var i = 0;
    if (dv.getUint16(offset) == 0xffd8){
        offset += 2;
        var app1 = dv.getUint16(offset);
        offset += 2;
        while (offset < dv.byteLength){
            //console.log(offset, '0x'+app1.toString(16), recess);
            if (app1 == 0xffe1){

                pieces[i] = {recess:recess,offset:offset-2};
                recess = offset + dv.getUint16(offset);
                i++;
            }
            else if (app1 == 0xffda){
                break;
            }
            offset += dv.getUint16(offset);
            var app1 = dv.getUint16(offset);
            offset += 2;
        }
        if (pieces.length > 0){
            var newPieces = [];
            pieces.forEach(function(v){
                newPieces.push(this.result.slice(v.recess, v.offset));
            }, this);
            newPieces.push(this.result.slice(recess));
            var br = new Blob(newPieces, {type: 'image/jpeg'});
            document.querySelector('#mod').src = URL.createObjectURL(br);
        }
    }       
}
img{
    max-width:200px;
}
<input id="erd" type="file"/><br>
<img id="orig" title="Original">
<img id="mod" title="Modified">
Musa
  • 96,336
  • 17
  • 118
  • 137
  • 3
    Is there a way to replace the orientation with 1 rather than removing all the exif data? @Musa – danial Jan 19 '16 at 22:37
  • 1
    @danial sure, you just have to know where the orientation data is and set the value in the data view, something like `dataview.setUint16(orientationOffset, newValue)` – Musa Jan 19 '16 at 22:45
  • How do I know where the orientation data is? – danial Jan 20 '16 at 05:15
  • 1
    look up the file format and [**exif format**](http://www.media.mit.edu/pia/Research/deepview/exif.html) – Musa Jan 20 '16 at 12:24
  • Hello, I tried to adapt your code for a different thing. Do you care explaining those codes (0xffd8 and 0xffda) what these are for, because my Jpeg is sure a different code..? – Silom Jan 21 '16 at 15:36
  • That is the first two bytes of the jpeg file 0xff then 0xd8 http://i.stack.imgur.com/X1OVR.png – Musa Jan 21 '16 at 16:05
  • On the second pass of the file, this turns up empty: process(process(file)) .. Here is a trace of what is happening: ```dv.getUint16(offset) == 0xffd8 true, offset < dv.byteLength true, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffe1 false, app1 == 0xffda true, pieces.length > 0 false``` – jcalfee314 Jan 03 '17 at 17:46
  • `process` doesn't return anything, also it doesn't take any parameters – Musa Jan 03 '17 at 18:18
  • I see .. the jsfiddle works fine, I can process the image several times. I am running the code on nodejs and I'm getting the exact same filtered image as the jsfiddle, however, the second pass through your code in nodejs turns out an empty image.. What happens if onload receives an `undefined`? I think it is gracefully skipping the filter on the second pass so the bug is not as obvious. – jcalfee314 Jan 05 '17 at 16:07
  • 1
    I just made a question out of it. Here is a possible bug: http://stackoverflow.com/questions/41490122/strip-exif-data-from-image-node-js-addressing-a-possible-bug-in-the-original-v – jcalfee314 Jan 05 '17 at 16:38
  • @musa in my case I can not touch the stored images on the DB and I need to remove the EXIF data on the front end. How can your code be modified this so the EXIF data is stripped from a image coming from the server? Thanks – davidhartman00 Jul 02 '19 at 00:49
  • If you're using ajax to get the image data you can use the same process function with the response of your ajax(as an array buffer) to create the data view. – Musa Jul 02 '19 at 02:08
  • this is not working – stackoverflow Aug 15 '22 at 13:19