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

本文实例为大家分享了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));

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容