123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /*
- * JavaScript Load Image Meta
- * https://github.com/blueimp/JavaScript-Load-Image
- *
- * Copyright 2013, Sebastian Tschan
- * https://blueimp.net
- *
- * Image meta data handling implementation
- * based on the help and contribution of
- * Achim Stöhr.
- *
- * Licensed under the MIT license:
- * https://opensource.org/licenses/MIT
- */
- /* global define, module, require, DataView, Uint8Array */
- ;(function(factory) {
- 'use strict'
- if (typeof define === 'function' && define.amd) {
- // Register as an anonymous AMD module:
- define(['./load-image'], factory)
- } else if (typeof module === 'object' && module.exports) {
- factory(require('./load-image'))
- } else {
- // Browser globals:
- factory(window.loadImage)
- }
- })(function(loadImage) {
- 'use strict'
- var hasblobSlice =
- typeof Blob !== 'undefined' &&
- (Blob.prototype.slice ||
- Blob.prototype.webkitSlice ||
- Blob.prototype.mozSlice)
- loadImage.blobSlice =
- hasblobSlice &&
- function() {
- var slice = this.slice || this.webkitSlice || this.mozSlice
- return slice.apply(this, arguments)
- }
- loadImage.metaDataParsers = {
- jpeg: {
- 0xffe1: [], // APP1 marker
- 0xffed: [] // APP13 marker
- }
- }
- // Parses image meta data and calls the callback with an object argument
- // with the following properties:
- // * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10)
- // The options argument accepts an object and supports the following
- // properties:
- // * maxMetaDataSize: Defines the maximum number of bytes to parse.
- // * disableImageHead: Disables creating the imageHead property.
- loadImage.parseMetaData = function(file, callback, options, data) {
- // eslint-disable-next-line no-param-reassign
- options = options || {}
- // eslint-disable-next-line no-param-reassign
- data = data || {}
- var that = this
- // 256 KiB should contain all EXIF/ICC/IPTC segments:
- var maxMetaDataSize = options.maxMetaDataSize || 262144
- var noMetaData = !(
- typeof DataView !== 'undefined' &&
- file &&
- file.size >= 12 &&
- file.type === 'image/jpeg' &&
- loadImage.blobSlice
- )
- if (
- noMetaData ||
- !loadImage.readFile(
- loadImage.blobSlice.call(file, 0, maxMetaDataSize),
- function(e) {
- if (e.target.error) {
- // FileReader error
- // eslint-disable-next-line no-console
- console.log(e.target.error)
- callback(data)
- return
- }
- // Note on endianness:
- // Since the marker and length bytes in JPEG files are always
- // stored in big endian order, we can leave the endian parameter
- // of the DataView methods undefined, defaulting to big endian.
- var buffer = e.target.result
- var dataView = new DataView(buffer)
- var offset = 2
- var maxOffset = dataView.byteLength - 4
- var headLength = offset
- var markerBytes
- var markerLength
- var parsers
- var i
- // Check for the JPEG marker (0xffd8):
- if (dataView.getUint16(0) === 0xffd8) {
- while (offset < maxOffset) {
- markerBytes = dataView.getUint16(offset)
- // Search for APPn (0xffeN) and COM (0xfffe) markers,
- // which contain application-specific meta-data like
- // Exif, ICC and IPTC data and text comments:
- if (
- (markerBytes >= 0xffe0 && markerBytes <= 0xffef) ||
- markerBytes === 0xfffe
- ) {
- // The marker bytes (2) are always followed by
- // the length bytes (2), indicating the length of the
- // marker segment, which includes the length bytes,
- // but not the marker bytes, so we add 2:
- markerLength = dataView.getUint16(offset + 2) + 2
- if (offset + markerLength > dataView.byteLength) {
- // eslint-disable-next-line no-console
- console.log('Invalid meta data: Invalid segment size.')
- break
- }
- parsers = loadImage.metaDataParsers.jpeg[markerBytes]
- if (parsers) {
- for (i = 0; i < parsers.length; i += 1) {
- parsers[i].call(
- that,
- dataView,
- offset,
- markerLength,
- data,
- options
- )
- }
- }
- offset += markerLength
- headLength = offset
- } else {
- // Not an APPn or COM marker, probably safe to
- // assume that this is the end of the meta data
- break
- }
- }
- // Meta length must be longer than JPEG marker (2)
- // plus APPn marker (2), followed by length bytes (2):
- if (!options.disableImageHead && headLength > 6) {
- if (buffer.slice) {
- data.imageHead = buffer.slice(0, headLength)
- } else {
- // Workaround for IE10, which does not yet
- // support ArrayBuffer.slice:
- data.imageHead = new Uint8Array(buffer).subarray(0, headLength)
- }
- }
- } else {
- // eslint-disable-next-line no-console
- console.log('Invalid JPEG file: Missing JPEG marker.')
- }
- callback(data)
- },
- 'readAsArrayBuffer'
- )
- ) {
- callback(data)
- }
- }
- // Determines if meta data should be loaded automatically:
- loadImage.hasMetaOption = function(options) {
- return options && options.meta
- }
- var originalTransform = loadImage.transform
- loadImage.transform = function(img, options, callback, file, data) {
- if (loadImage.hasMetaOption(options)) {
- loadImage.parseMetaData(
- file,
- function(data) {
- originalTransform.call(loadImage, img, options, callback, file, data)
- },
- options,
- data
- )
- } else {
- originalTransform.apply(loadImage, arguments)
- }
- }
- })
|