欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue2.0实现调用摄像头进行拍照功能 exif.js实现图片上传功能

程序员文章站 2023-08-20 16:42:41
本文实例为大家分享了vue2.0实现调用摄像头进行拍照功能的具体代码,以及图片上传功能引用exif.js,供大家参考,具体内容如下 可以在github 上下载demo链接...

本文实例为大家分享了vue2.0实现调用摄像头进行拍照功能的具体代码,以及图片上传功能引用exif.js,供大家参考,具体内容如下

可以在github 上下载demo链接

vue组件代码

<template>
 <div>
  <div style="padding:20px;">
   <div class="show">
    <div class="picture" :style="'backgroundimage:url('+headerimage+')'"></div>
   </div>
   <div style="margin-top:20px;">
    <input type="file" id="upload" accept="image/jpg" @change="upload">
    <label for="upload"></label>
   </div>
  </div>
 </div>
</template>

<script>
import {exif} from './exif.js'

export default {
 data () {
  return {
   headerimage:'',picvalue:''
  }
 },
 mounted () {
 },
 methods: {
  upload (e) {
   let files = e.target.files || e.datatransfer.files;
   if (!files.length) return;
   this.picvalue = files[0];
   this.imgpreview(this.picvalue);
   console.log(this.picvalue)
  },
  imgpreview (file) {
   let self = this;
   let orientation;
   //去获取拍照时的信息,解决拍出来的照片旋转问题
    exif.getdata(file, function(){
      orientation = exif.gettag(this, 'orientation');
    });
   // 看支持不支持filereader 
   if (!file || !window.filereader) return;

   if (/^image/.test(file.type)) {
     // 创建一个reader
     let reader = new filereader();
     // 将图片2将转成 base64 格式
     reader.readasdataurl(file);
     // 读取成功后的回调
     reader.onloadend = function () {
      let result = this.result;
      let img = new image();
      img.src = result;
      //判断图片是否大于100k,是就直接上传,反之压缩图片
      if (this.result.length <= (100 * 1024)) {
       self.headerimage = this.result;
       self.postimg();
      }else {
       img.onload = function () {
        let data = self.compress(img,orientation);
        self.headerimage = data;
        self.postimg();
       }
      }
     }
    }
   },
   postimg () {
    //这里写接口
   },
   rotateimg (img, direction,canvas) {
    //最小与最大旋转方向,图片旋转4次后回到原方向
    const min_step = 0;
    const max_step = 3;
    if (img == null)return;
    //img的高度和宽度不能在img元素隐藏后获取,否则会出错
    let height = img.height;
    let width = img.width;
    let step = 2;
    if (step == null) {
      step = min_step;
    }
    if (direction == 'right') {
      step++;
      //旋转到原位置,即超过最大值
      step > max_step && (step = min_step);
    } else {
      step--;
      step < min_step && (step = max_step);
    }
    //旋转角度以弧度值为参数
    let degree = step * 90 * math.pi / 180;
    let ctx = canvas.getcontext('2d');
    switch (step) {
     case 0:
       canvas.width = width;
       canvas.height = height;
       ctx.drawimage(img, 0, 0);
       break;
     case 1:
       canvas.width = height;
       canvas.height = width;
       ctx.rotate(degree);
       ctx.drawimage(img, 0, -height);
       break;
     case 2:
       canvas.width = width;
       canvas.height = height;
       ctx.rotate(degree);
       ctx.drawimage(img, -width, -height);
       break;
     case 3:
       canvas.width = height;
       canvas.height = width;
       ctx.rotate(degree);
       ctx.drawimage(img, -width, 0);
       break;
    }
  },
  compress(img,orientation) {
   let canvas = document.createelement("canvas");
   let ctx = canvas.getcontext('2d');
    //瓦片canvas
   let tcanvas = document.createelement("canvas");
   let tctx = tcanvas.getcontext("2d");
   let initsize = img.src.length;
   let width = img.width;
   let height = img.height;
   //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
   let ratio;
   if ((ratio = width * height / 4000000) > 1) {
    console.log("大于400万像素")
    ratio = math.sqrt(ratio);
    width /= ratio;
    height /= ratio;
   } else {
    ratio = 1;
   }
   canvas.width = width;
   canvas.height = height;
 //    铺底色
   ctx.fillstyle = "#fff";
   ctx.fillrect(0, 0, canvas.width, canvas.height);
   //如果图片像素大于100万则使用瓦片绘制
   let count;
   if ((count = width * height / 1000000) > 1) {
    console.log("超过100w像素");
    count = ~~(math.sqrt(count) + 1); //计算要分成多少块瓦片
 //      计算每块瓦片的宽和高
    let nw = ~~(width / count);
    let nh = ~~(height / count);
    tcanvas.width = nw;
    tcanvas.height = nh;
    for (let i = 0; i < count; i++) {
     for (let j = 0; j < count; j++) {
      tctx.drawimage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
      ctx.drawimage(tcanvas, i * nw, j * nh, nw, nh);
     }
    }
   } else {
    ctx.drawimage(img, 0, 0, width, height);
   }
   //修复ios上传图片的时候 被旋转的问题
   if(orientation != "" && orientation != 1){
    switch(orientation){
     case 6://需要顺时针(向左)90度旋转
       this.rotateimg(img,'left',canvas);
       break;
     case 8://需要逆时针(向右)90度旋转
       this.rotateimg(img,'right',canvas);
       break;
     case 3://需要180度旋转
       this.rotateimg(img,'right',canvas);//转两次
       this.rotateimg(img,'right',canvas);
       break;
    }
   }
   //进行最小压缩
   let ndata = canvas.todataurl('image/jpeg', 0.1);
   console.log('压缩前:' + initsize);
   console.log('压缩后:' + ndata.length);
   console.log('压缩率:' + ~~(100 * (initsize - ndata.length) / initsize) + "%");
   tcanvas.width = tcanvas.height = canvas.width = canvas.height = 0;
   return ndata;
  },
 }
}
</script>

<style>
*{
 margin: 0;
 padding: 0;
}
.show {
 width: 100px;
 height: 100px;
 overflow: hidden;
 position: relative;
 border-radius: 50%;
 border: 1px solid #d5d5d5;
}
.picture {
 width: 100%;
 height: 100%;
 overflow: hidden;
 background-position: center center;
 background-repeat: no-repeat;
 background-size: cover;
}
</style>

引用的exif.js代码

(function() {

  var debug = false;

  var root = this;

  var exif = function(obj) {
    if (obj instanceof exif) return obj;
    if (!(this instanceof exif)) return new exif(obj);
    this.exifwrapped = obj;
  };

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = exif;
    }
    exports.exif = exif;
  } else {
    root.exif = exif;
  }

  var exiftags = exif.tags = {

    // version tags
    0x9000 : "exifversion",       // exif version
    0xa000 : "flashpixversion",     // flashpix format version

    // colorspace tags
    0xa001 : "colorspace",       // color space information tag

    // image configuration
    0xa002 : "pixelxdimension",     // valid width of meaningful image
    0xa003 : "pixelydimension",     // valid height of meaningful image
    0x9101 : "componentsconfiguration", // information about channels
    0x9102 : "compressedbitsperpixel", // compressed bits per pixel

    // user information
    0x927c : "makernote",        // any desired information written by the manufacturer
    0x9286 : "usercomment",       // comments by user

    // related file
    0xa004 : "relatedsoundfile",    // name of related sound file

    // date and time
    0x9003 : "datetimeoriginal",    // date and time when the original image was generated
    0x9004 : "datetimedigitized",    // date and time when the image was stored digitally
    0x9290 : "subsectime",       // fractions of seconds for datetime
    0x9291 : "subsectimeoriginal",   // fractions of seconds for datetimeoriginal
    0x9292 : "subsectimedigitized",   // fractions of seconds for datetimedigitized

    // picture-taking conditions
    0x829a : "exposuretime",      // exposure time (in seconds)
    0x829d : "fnumber",         // f number
    0x8822 : "exposureprogram",     // exposure program
    0x8824 : "spectralsensitivity",   // spectral sensitivity
    0x8827 : "isospeedratings",     // iso speed rating
    0x8828 : "oecf",          // optoelectric conversion factor
    0x9201 : "shutterspeedvalue",    // shutter speed
    0x9202 : "aperturevalue",      // lens aperture
    0x9203 : "brightnessvalue",     // value of brightness
    0x9204 : "exposurebias",      // exposure bias
    0x9205 : "maxaperturevalue",    // smallest f number of lens
    0x9206 : "subjectdistance",     // distance to subject in meters
    0x9207 : "meteringmode",      // metering mode
    0x9208 : "lightsource",       // kind of light source
    0x9209 : "flash",          // flash status
    0x9214 : "subjectarea",       // location and area of main subject
    0x920a : "focallength",       // focal length of the lens in mm
    0xa20b : "flashenergy",       // strobe energy in bcps
    0xa20c : "spatialfrequencyresponse",  //
    0xa20e : "focalplanexresolution",  // number of pixels in width direction per focalplaneresolutionunit
    0xa20f : "focalplaneyresolution",  // number of pixels in height direction per focalplaneresolutionunit
    0xa210 : "focalplaneresolutionunit",  // unit for measuring focalplanexresolution and focalplaneyresolution
    0xa214 : "subjectlocation",     // location of subject in image
    0xa215 : "exposureindex",      // exposure index selected on camera
    0xa217 : "sensingmethod",      // image sensor type
    0xa300 : "filesource",       // image source (3 == dsc)
    0xa301 : "scenetype",        // scene type (1 == directly photographed)
    0xa302 : "cfapattern",       // color filter array geometric pattern
    0xa401 : "customrendered",     // special processing
    0xa402 : "exposuremode",      // exposure mode
    0xa403 : "whitebalance",      // 1 = auto white balance, 2 = manual
    0xa404 : "digitalzoomration",    // digital zoom ratio
    0xa405 : "focallengthin35mmfilm",  // equivalent foacl length assuming 35mm film camera (in mm)
    0xa406 : "scenecapturetype",    // type of scene
    0xa407 : "gaincontrol",       // degree of overall image gain adjustment
    0xa408 : "contrast",        // direction of contrast processing applied by camera
    0xa409 : "saturation",       // direction of saturation processing applied by camera
    0xa40a : "sharpness",        // direction of sharpness processing applied by camera
    0xa40b : "devicesettingdescription",  //
    0xa40c : "subjectdistancerange",  // distance to subject

    // other tags
    0xa005 : "interoperabilityifdpointer",
    0xa420 : "imageuniqueid"      // identifier assigned uniquely to each image
  };

  var tifftags = exif.tifftags = {
    0x0100 : "imagewidth",
    0x0101 : "imageheight",
    0x8769 : "exififdpointer",
    0x8825 : "gpsinfoifdpointer",
    0xa005 : "interoperabilityifdpointer",
    0x0102 : "bitspersample",
    0x0103 : "compression",
    0x0106 : "photometricinterpretation",
    0x0112 : "orientation",
    0x0115 : "samplesperpixel",
    0x011c : "planarconfiguration",
    0x0212 : "ycbcrsubsampling",
    0x0213 : "ycbcrpositioning",
    0x011a : "xresolution",
    0x011b : "yresolution",
    0x0128 : "resolutionunit",
    0x0111 : "stripoffsets",
    0x0116 : "rowsperstrip",
    0x0117 : "stripbytecounts",
    0x0201 : "jpeginterchangeformat",
    0x0202 : "jpeginterchangeformatlength",
    0x012d : "transferfunction",
    0x013e : "whitepoint",
    0x013f : "primarychromaticities",
    0x0211 : "ycbcrcoefficients",
    0x0214 : "referenceblackwhite",
    0x0132 : "datetime",
    0x010e : "imagedescription",
    0x010f : "make",
    0x0110 : "model",
    0x0131 : "software",
    0x013b : "artist",
    0x8298 : "copyright"
  };

  var gpstags = exif.gpstags = {
    0x0000 : "gpsversionid",
    0x0001 : "gpslatituderef",
    0x0002 : "gpslatitude",
    0x0003 : "gpslongituderef",
    0x0004 : "gpslongitude",
    0x0005 : "gpsaltituderef",
    0x0006 : "gpsaltitude",
    0x0007 : "gpstimestamp",
    0x0008 : "gpssatellites",
    0x0009 : "gpsstatus",
    0x000a : "gpsmeasuremode",
    0x000b : "gpsdop",
    0x000c : "gpsspeedref",
    0x000d : "gpsspeed",
    0x000e : "gpstrackref",
    0x000f : "gpstrack",
    0x0010 : "gpsimgdirectionref",
    0x0011 : "gpsimgdirection",
    0x0012 : "gpsmapdatum",
    0x0013 : "gpsdestlatituderef",
    0x0014 : "gpsdestlatitude",
    0x0015 : "gpsdestlongituderef",
    0x0016 : "gpsdestlongitude",
    0x0017 : "gpsdestbearingref",
    0x0018 : "gpsdestbearing",
    0x0019 : "gpsdestdistanceref",
    0x001a : "gpsdestdistance",
    0x001b : "gpsprocessingmethod",
    0x001c : "gpsareainformation",
    0x001d : "gpsdatestamp",
    0x001e : "gpsdifferential"
  };

  var stringvalues = exif.stringvalues = {
    exposureprogram : {
      0 : "not defined",
      1 : "manual",
      2 : "normal program",
      3 : "aperture priority",
      4 : "shutter priority",
      5 : "creative program",
      6 : "action program",
      7 : "portrait mode",
      8 : "landscape mode"
    },
    meteringmode : {
      0 : "unknown",
      1 : "average",
      2 : "centerweightedaverage",
      3 : "spot",
      4 : "multispot",
      5 : "pattern",
      6 : "partial",
      255 : "other"
    },
    lightsource : {
      0 : "unknown",
      1 : "daylight",
      2 : "fluorescent",
      3 : "tungsten (incandescent light)",
      4 : "flash",
      9 : "fine weather",
      10 : "cloudy weather",
      11 : "shade",
      12 : "daylight fluorescent (d 5700 - 7100k)",
      13 : "day white fluorescent (n 4600 - 5400k)",
      14 : "cool white fluorescent (w 3900 - 4500k)",
      15 : "white fluorescent (ww 3200 - 3700k)",
      17 : "standard light a",
      18 : "standard light b",
      19 : "standard light c",
      20 : "d55",
      21 : "d65",
      22 : "d75",
      23 : "d50",
      24 : "iso studio tungsten",
      255 : "other"
    },
    flash : {
      0x0000 : "flash did not fire",
      0x0001 : "flash fired",
      0x0005 : "strobe return light not detected",
      0x0007 : "strobe return light detected",
      0x0009 : "flash fired, compulsory flash mode",
      0x000d : "flash fired, compulsory flash mode, return light not detected",
      0x000f : "flash fired, compulsory flash mode, return light detected",
      0x0010 : "flash did not fire, compulsory flash mode",
      0x0018 : "flash did not fire, auto mode",
      0x0019 : "flash fired, auto mode",
      0x001d : "flash fired, auto mode, return light not detected",
      0x001f : "flash fired, auto mode, return light detected",
      0x0020 : "no flash function",
      0x0041 : "flash fired, red-eye reduction mode",
      0x0045 : "flash fired, red-eye reduction mode, return light not detected",
      0x0047 : "flash fired, red-eye reduction mode, return light detected",
      0x0049 : "flash fired, compulsory flash mode, red-eye reduction mode",
      0x004d : "flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
      0x004f : "flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
      0x0059 : "flash fired, auto mode, red-eye reduction mode",
      0x005d : "flash fired, auto mode, return light not detected, red-eye reduction mode",
      0x005f : "flash fired, auto mode, return light detected, red-eye reduction mode"
    },
    sensingmethod : {
      1 : "not defined",
      2 : "one-chip color area sensor",
      3 : "two-chip color area sensor",
      4 : "three-chip color area sensor",
      5 : "color sequential area sensor",
      7 : "trilinear sensor",
      8 : "color sequential linear sensor"
    },
    scenecapturetype : {
      0 : "standard",
      1 : "landscape",
      2 : "portrait",
      3 : "night scene"
    },
    scenetype : {
      1 : "directly photographed"
    },
    customrendered : {
      0 : "normal process",
      1 : "custom process"
    },
    whitebalance : {
      0 : "auto white balance",
      1 : "manual white balance"
    },
    gaincontrol : {
      0 : "none",
      1 : "low gain up",
      2 : "high gain up",
      3 : "low gain down",
      4 : "high gain down"
    },
    contrast : {
      0 : "normal",
      1 : "soft",
      2 : "hard"
    },
    saturation : {
      0 : "normal",
      1 : "low saturation",
      2 : "high saturation"
    },
    sharpness : {
      0 : "normal",
      1 : "soft",
      2 : "hard"
    },
    subjectdistancerange : {
      0 : "unknown",
      1 : "macro",
      2 : "close view",
      3 : "distant view"
    },
    filesource : {
      3 : "dsc"
    },

    components : {
      0 : "",
      1 : "y",
      2 : "cb",
      3 : "cr",
      4 : "r",
      5 : "g",
      6 : "b"
    }
  };

  function addevent(element, event, handler) {
    if (element.addeventlistener) {
      element.addeventlistener(event, handler, false);
    } else if (element.attachevent) {
      element.attachevent("on" + event, handler);
    }
  }

  function imagehasdata(img) {
    return !!(img.exifdata);
  }


  function base64toarraybuffer(base64, contenttype) {
    contenttype = contenttype || base64.match(/^data\:([^\;]+)\;base64,/mi)[1] || ''; // e.g. 'data:image/jpeg;base64,...' => 'image/jpeg'
    base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
    var binary = atob(base64);
    var len = binary.length;
    var buffer = new arraybuffer(len);
    var view = new uint8array(buffer);
    for (var i = 0; i < len; i++) {
      view[i] = binary.charcodeat(i);
    }
    return buffer;
  }

  function objecturltoblob(url, callback) {
    var http = new xmlhttprequest();
    http.open("get", url, true);
    http.responsetype = "blob";
    http.onload = function(e) {
      if (this.status == 200 || this.status === 0) {
        callback(this.response);
      }
    };
    http.send();
  }

  function getimagedata(img, callback) {
    function handlebinaryfile(binfile) {
      var data = findexifinjpeg(binfile);
      var iptcdata = findiptcinjpeg(binfile);
      img.exifdata = data || {};
      img.iptcdata = iptcdata || {};
      if (callback) {
        callback.call(img);
      }
    }

    if (img.src) {
      if (/^data\:/i.test(img.src)) { // data uri
        var arraybuffer = base64toarraybuffer(img.src);
        handlebinaryfile(arraybuffer);

      } else if (/^blob\:/i.test(img.src)) { // object url
        var filereader = new filereader();
        filereader.onload = function(e) {
          handlebinaryfile(e.target.result);
        };
        objecturltoblob(img.src, function (blob) {
          filereader.readasarraybuffer(blob);
        });
      } else {
        var http = new xmlhttprequest();
        http.onload = function() {
          if (this.status == 200 || this.status === 0) {
            handlebinaryfile(http.response);
          } else {
            throw "could not load image";
          }
          http = null;
        };
        http.open("get", img.src, true);
        http.responsetype = "arraybuffer";
        http.send(null);
      }
    } else if (window.filereader && (img instanceof window.blob || img instanceof window.file)) {
      var filereader = new filereader();
      filereader.onload = function(e) {
        if (debug) console.log("got file of length " + e.target.result.bytelength);
        handlebinaryfile(e.target.result);
      };

      filereader.readasarraybuffer(img);
    }
  }

  function findexifinjpeg(file) {
    var dataview = new dataview(file);

    if (debug) console.log("got file of length " + file.bytelength);
    if ((dataview.getuint8(0) != 0xff) || (dataview.getuint8(1) != 0xd8)) {
      if (debug) console.log("not a valid jpeg");
      return false; // not a valid jpeg
    }

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

    while (offset < length) {
      if (dataview.getuint8(offset) != 0xff) {
        if (debug) console.log("not a valid marker at offset " + offset + ", found: " + dataview.getuint8(offset));
        return false; // not a valid marker, something is wrong
      }

      marker = dataview.getuint8(offset + 1);
      if (debug) console.log(marker);

      // we could implement handling for other markers here,
      // but we're only looking for 0xffe1 for exif data

      if (marker == 225) {
        if (debug) console.log("found 0xffe1 marker");

        return readexifdata(dataview, offset + 4, dataview.getuint16(offset + 2) - 2);

        // offset += 2 + file.getshortat(offset+2, true);

      } else {
        offset += 2 + dataview.getuint16(offset+2);
      }

    }

  }

  function findiptcinjpeg(file) {
    var dataview = new dataview(file);

    if (debug) console.log("got file of length " + file.bytelength);
    if ((dataview.getuint8(0) != 0xff) || (dataview.getuint8(1) != 0xd8)) {
      if (debug) console.log("not a valid jpeg");
      return false; // not a valid jpeg
    }

    var offset = 2,
      length = file.bytelength;


    var isfieldsegmentstart = function(dataview, offset){
      return (
        dataview.getuint8(offset) === 0x38 &&
        dataview.getuint8(offset+1) === 0x42 &&
        dataview.getuint8(offset+2) === 0x49 &&
        dataview.getuint8(offset+3) === 0x4d &&
        dataview.getuint8(offset+4) === 0x04 &&
        dataview.getuint8(offset+5) === 0x04
      );
    };

    while (offset < length) {

      if ( isfieldsegmentstart(dataview, offset )){

        // get the length of the name header (which is padded to an even number of bytes)
        var nameheaderlength = dataview.getuint8(offset+7);
        if(nameheaderlength % 2 !== 0) nameheaderlength += 1;
        // check for pre photoshop 6 format
        if(nameheaderlength === 0) {
          // always 4
          nameheaderlength = 4;
        }

        var startoffset = offset + 8 + nameheaderlength;
        var sectionlength = dataview.getuint16(offset + 6 + nameheaderlength);

        return readiptcdata(file, startoffset, sectionlength);

        break;

      }


      // not the marker, continue searching
      offset++;

    }

  }
  var iptcfieldmap = {
    0x78 : 'caption',
    0x6e : 'credit',
    0x19 : 'keywords',
    0x37 : 'datecreated',
    0x50 : 'byline',
    0x55 : 'bylinetitle',
    0x7a : 'captionwriter',
    0x69 : 'headline',
    0x74 : 'copyright',
    0x0f : 'category'
  };
  function readiptcdata(file, startoffset, sectionlength){
    var dataview = new dataview(file);
    var data = {};
    var fieldvalue, fieldname, datasize, segmenttype, segmentsize;
    var segmentstartpos = startoffset;
    while(segmentstartpos < startoffset+sectionlength) {
      if(dataview.getuint8(segmentstartpos) === 0x1c && dataview.getuint8(segmentstartpos+1) === 0x02){
        segmenttype = dataview.getuint8(segmentstartpos+2);
        if(segmenttype in iptcfieldmap) {
          datasize = dataview.getint16(segmentstartpos+3);
          segmentsize = datasize + 5;
          fieldname = iptcfieldmap[segmenttype];
          fieldvalue = getstringfromdb(dataview, segmentstartpos+5, datasize);
          // check if we already stored a value with this name
          if(data.hasownproperty(fieldname)) {
            // value already stored with this name, create multivalue field
            if(data[fieldname] instanceof array) {
              data[fieldname].push(fieldvalue);
            }
            else {
              data[fieldname] = [data[fieldname], fieldvalue];
            }
          }
          else {
            data[fieldname] = fieldvalue;
          }
        }

      }
      segmentstartpos++;
    }
    return data;
  }



  function readtags(file, tiffstart, dirstart, strings, bigend) {
    var entries = file.getuint16(dirstart, !bigend),
      tags = {},
      entryoffset, tag,
      i;

    for (i=0;i<entries;i++) {
      entryoffset = dirstart + i*12 + 2;
      tag = strings[file.getuint16(entryoffset, !bigend)];
      if (!tag && debug) console.log("unknown tag: " + file.getuint16(entryoffset, !bigend));
      tags[tag] = readtagvalue(file, entryoffset, tiffstart, dirstart, bigend);
    }
    return tags;
  }


  function readtagvalue(file, entryoffset, tiffstart, dirstart, bigend) {
    var type = file.getuint16(entryoffset+2, !bigend),
      numvalues = file.getuint32(entryoffset+4, !bigend),
      valueoffset = file.getuint32(entryoffset+8, !bigend) + tiffstart,
      offset,
      vals, val, n,
      numerator, denominator;

    switch (type) {
      case 1: // byte, 8-bit unsigned int
      case 7: // undefined, 8-bit byte, value depending on field
        if (numvalues == 1) {
          return file.getuint8(entryoffset + 8, !bigend);
        } else {
          offset = numvalues > 4 ? valueoffset : (entryoffset + 8);
          vals = [];
          for (n=0;n<numvalues;n++) {
            vals[n] = file.getuint8(offset + n);
          }
          return vals;
        }

      case 2: // ascii, 8-bit byte
        offset = numvalues > 4 ? valueoffset : (entryoffset + 8);
        return getstringfromdb(file, offset, numvalues-1);

      case 3: // short, 16 bit int
        if (numvalues == 1) {
          return file.getuint16(entryoffset + 8, !bigend);
        } else {
          offset = numvalues > 2 ? valueoffset : (entryoffset + 8);
          vals = [];
          for (n=0;n<numvalues;n++) {
            vals[n] = file.getuint16(offset + 2*n, !bigend);
          }
          return vals;
        }

      case 4: // long, 32 bit int
        if (numvalues == 1) {
          return file.getuint32(entryoffset + 8, !bigend);
        } else {
          vals = [];
          for (n=0;n<numvalues;n++) {
            vals[n] = file.getuint32(valueoffset + 4*n, !bigend);
          }
          return vals;
        }

      case 5:  // rational = two long values, first is numerator, second is denominator
        if (numvalues == 1) {
          numerator = file.getuint32(valueoffset, !bigend);
          denominator = file.getuint32(valueoffset+4, !bigend);
          val = new number(numerator / denominator);
          val.numerator = numerator;
          val.denominator = denominator;
          return val;
        } else {
          vals = [];
          for (n=0;n<numvalues;n++) {
            numerator = file.getuint32(valueoffset + 8*n, !bigend);
            denominator = file.getuint32(valueoffset+4 + 8*n, !bigend);
            vals[n] = new number(numerator / denominator);
            vals[n].numerator = numerator;
            vals[n].denominator = denominator;
          }
          return vals;
        }

      case 9: // slong, 32 bit signed int
        if (numvalues == 1) {
          return file.getint32(entryoffset + 8, !bigend);
        } else {
          vals = [];
          for (n=0;n<numvalues;n++) {
            vals[n] = file.getint32(valueoffset + 4*n, !bigend);
          }
          return vals;
        }

      case 10: // signed rational, two slongs, first is numerator, second is denominator
        if (numvalues == 1) {
          return file.getint32(valueoffset, !bigend) / file.getint32(valueoffset+4, !bigend);
        } else {
          vals = [];
          for (n=0;n<numvalues;n++) {
            vals[n] = file.getint32(valueoffset + 8*n, !bigend) / file.getint32(valueoffset+4 + 8*n, !bigend);
          }
          return vals;
        }
    }
  }

  function getstringfromdb(buffer, start, length) {
    var outstr = "";
    for (n = start; n < start+length; n++) {
      outstr += string.fromcharcode(buffer.getuint8(n));
    }
    return outstr;
  }

  function readexifdata(file, start) {
    if (getstringfromdb(file, start, 4) != "exif") {
      if (debug) console.log("not valid exif data! " + getstringfromdb(file, start, 4));
      return false;
    }

    var bigend,
      tags, tag,
      exifdata, gpsdata,
      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 {
      if (debug) console.log("not valid tiff data! (no 0x4949 or 0x4d4d)");
      return false;
    }

    if (file.getuint16(tiffoffset+2, !bigend) != 0x002a) {
      if (debug) console.log("not valid tiff data! (no 0x002a)");
      return false;
    }

    var firstifdoffset = file.getuint32(tiffoffset+4, !bigend);

    if (firstifdoffset < 0x00000008) {
      if (debug) console.log("not valid tiff data! (first offset less than 8)", file.getuint32(tiffoffset+4, !bigend));
      return false;
    }

    tags = readtags(file, tiffoffset, tiffoffset + firstifdoffset, tifftags, bigend);

    if (tags.exififdpointer) {
      exifdata = readtags(file, tiffoffset, tiffoffset + tags.exififdpointer, exiftags, bigend);
      for (tag in exifdata) {
        switch (tag) {
          case "lightsource" :
          case "flash" :
          case "meteringmode" :
          case "exposureprogram" :
          case "sensingmethod" :
          case "scenecapturetype" :
          case "scenetype" :
          case "customrendered" :
          case "whitebalance" :
          case "gaincontrol" :
          case "contrast" :
          case "saturation" :
          case "sharpness" :
          case "subjectdistancerange" :
          case "filesource" :
            exifdata[tag] = stringvalues[tag][exifdata[tag]];
            break;

          case "exifversion" :
          case "flashpixversion" :
            exifdata[tag] = string.fromcharcode(exifdata[tag][0], exifdata[tag][1], exifdata[tag][2], exifdata[tag][3]);
            break;

          case "componentsconfiguration" :
            exifdata[tag] =
              stringvalues.components[exifdata[tag][0]] +
              stringvalues.components[exifdata[tag][1]] +
              stringvalues.components[exifdata[tag][2]] +
              stringvalues.components[exifdata[tag][3]];
            break;
        }
        tags[tag] = exifdata[tag];
      }
    }

    if (tags.gpsinfoifdpointer) {
      gpsdata = readtags(file, tiffoffset, tiffoffset + tags.gpsinfoifdpointer, gpstags, bigend);
      for (tag in gpsdata) {
        switch (tag) {
          case "gpsversionid" :
            gpsdata[tag] = gpsdata[tag][0] +
              "." + gpsdata[tag][1] +
              "." + gpsdata[tag][2] +
              "." + gpsdata[tag][3];
            break;
        }
        tags[tag] = gpsdata[tag];
      }
    }

    return tags;
  }

  exif.getdata = function(img, callback) {
    if ((img instanceof image || img instanceof htmlimageelement) && !img.complete) return false;

    if (!imagehasdata(img)) {
      getimagedata(img, callback);
    } else {
      if (callback) {
        callback.call(img);
      }
    }
    return true;
  }

  exif.gettag = function(img, tag) {
    if (!imagehasdata(img)) return;
    return img.exifdata[tag];
  }

  exif.getalltags = function(img) {
    if (!imagehasdata(img)) return {};
    var a,
      data = img.exifdata,
      tags = {};
    for (a in data) {
      if (data.hasownproperty(a)) {
        tags[a] = data[a];
      }
    }
    return tags;
  }

  exif.pretty = function(img) {
    if (!imagehasdata(img)) return "";
    var a,
      data = img.exifdata,
      strpretty = "";
    for (a in data) {
      if (data.hasownproperty(a)) {
        if (typeof data[a] == "object") {
          if (data[a] instanceof number) {
            strpretty += a + " : " + data[a] + " [" + data[a].numerator + "/" + data[a].denominator + "]\r\n";
          } else {
            strpretty += a + " : [" + data[a].length + " values]\r\n";
          }
        } else {
          strpretty += a + " : " + data[a] + "\r\n";
        }
      }
    }
    return strpretty;
  }

  exif.readfrombinaryfile = function(file) {
    return findexifinjpeg(file);
  }

  if (typeof define === 'function' && define.amd) {
    define('exif-js', [], function() {
      return exif;
    });
  }
}.call(this));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。