* Parses image metadata and calls the callback with an object argument * with the following property: * - imageHead: The complete image head as ArrayBuffer * The options argument accepts an object and supports the following * properties: * - maxMetaDataSize: Defines the maximum number
(file, callback, options, data)
| 73 | * @returns {Promise<object>|undefined} Returns Promise if no callback given. |
| 74 | */ |
| 75 | function parseMetaData(file, callback, options, data) { |
| 76 | var that = this |
| 77 | /** |
| 78 | * Promise executor |
| 79 | * |
| 80 | * @param {Function} resolve Resolution function |
| 81 | * @param {Function} reject Rejection function |
| 82 | * @returns {undefined} Undefined |
| 83 | */ |
| 84 | function executor(resolve, reject) { |
| 85 | if ( |
| 86 | !( |
| 87 | global.DataView && |
| 88 | blobSlice && |
| 89 | file && |
| 90 | file.size >= 12 && |
| 91 | file.type === 'image/jpeg' |
| 92 | ) |
| 93 | ) { |
| 94 | // Nothing to parse |
| 95 | return resolve(data) |
| 96 | } |
| 97 | // 256 KiB should contain all EXIF/ICC/IPTC segments: |
| 98 | var maxMetaDataSize = options.maxMetaDataSize || 262144 |
| 99 | if ( |
| 100 | !loadImage.readFile( |
| 101 | blobSlice.call(file, 0, maxMetaDataSize), |
| 102 | function (buffer) { |
| 103 | // Note on endianness: |
| 104 | // Since the marker and length bytes in JPEG files are always |
| 105 | // stored in big endian order, we can leave the endian parameter |
| 106 | // of the DataView methods undefined, defaulting to big endian. |
| 107 | var dataView = new DataView(buffer) |
| 108 | // Check for the JPEG marker (0xffd8): |
| 109 | if (dataView.getUint16(0) !== 0xffd8) { |
| 110 | return reject( |
| 111 | new Error('Invalid JPEG file: Missing JPEG marker.') |
| 112 | ) |
| 113 | } |
| 114 | var offset = 2 |
| 115 | var maxOffset = dataView.byteLength - 4 |
| 116 | var headLength = offset |
| 117 | var markerBytes |
| 118 | var markerLength |
| 119 | var parsers |
| 120 | var i |
| 121 | while (offset < maxOffset) { |
| 122 | markerBytes = dataView.getUint16(offset) |
| 123 | // Search for APPn (0xffeN) and COM (0xfffe) markers, |
| 124 | // which contain application-specific metadata like |
| 125 | // Exif, ICC and IPTC data and text comments: |
| 126 | if ( |
| 127 | (markerBytes >= 0xffe0 && markerBytes <= 0xffef) || |
| 128 | markerBytes === 0xfffe |
| 129 | ) { |
| 130 | // The marker bytes (2) are always followed by |
| 131 | // the length bytes (2), indicating the length of the |
| 132 | // marker segment, which includes the length bytes, |
no test coverage detected