aboutsummaryrefslogtreecommitdiffstats
path: root/web/js/src/exif.js
blob: f27be8ecbb9b88824ca2643805b537f59b2618d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* Cut down version of https://github.com/exif-js/exif-js
 * only looking for orientation EXIF data. MIT. */

(function() {
    var EXIF = {};
    window.EXIF = EXIF;

    function readEXIFData(file, start) {
        var str = "";
        for (var n = start; n < start+4; n++) {
            str += String.fromCharCode(file.getUint8(n));
        }
        if (str != "Exif") {
            return false;
        }

        var bigEnd,
            tiffOffset = start + 6;

        // test for TIFF validity and endianness
        if (file.getUint16(tiffOffset) == 0x4949) {
            bigEnd = false;
        } else if (file.getUint16(tiffOffset) == 0x4D4D) {
            bigEnd = true;
        } else {
            return false;
        }

        if (file.getUint16(tiffOffset+2, !bigEnd) != 0x002A) {
            return false;
        }

        var firstIFDOffset = file.getUint32(tiffOffset+4, !bigEnd);
        if (firstIFDOffset < 0x00000008) {
            return false;
        }

        var dirStart = tiffOffset + firstIFDOffset,
            entries = file.getUint16(dirStart, !bigEnd),
            tags = {},
            entryOffset,
            i;

        for (i=0;i<entries;i++) {
            entryOffset = dirStart + i*12 + 2;
            if (file.getUint16(entryOffset, !bigEnd) == 0x0112) {
                return parseInt(file.getUint16(entryOffset + 8, !bigEnd), 10);
            }
        }
        return false;
    }

    EXIF.getData = function(img) {
        if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) {
            return false;
        }

        var data = img.src;
        if (data.match(/^http/)) {
            // We're loading this image from the server, presumably after a
            // submission, so we have its URL, not yet its data.
            var canvas = document.createElement("canvas"),
                ctx = canvas.getContext("2d");
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img, 0, 0);
            data = canvas.toDataURL("image/jpeg");
        }

        var base64 = data.replace(/^data\:([^\;]+)\;base64,/gmi, '');
        var binary = atob(base64);
        var len = binary.length;
        var file = new ArrayBuffer(len);
        var view = new Uint8Array(file);
        for (var i = 0; i < len; i++) {
            view[i] = binary.charCodeAt(i);
        }

        var dataView = new DataView(file);
        if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
            return false; // not a valid jpeg
        }

        var offset = 2,
            length = file.byteLength,
            marker;

        while (offset < length) {
            if (dataView.getUint8(offset) != 0xFF) {
                return false; // not a valid marker, something is wrong
            }

            marker = dataView.getUint8(offset + 1);

            // we could implement handling for other markers here,
            // but we're only looking for 0xFFE1 for EXIF data
            if (marker == 225) {
                return readEXIFData(dataView, offset + 4);
                // offset += 2 + file.getShortAt(offset+2, true);
            } else {
                offset += 2 + dataView.getUint16(offset+2);
            }
        }
    };

})();