<template> <p> <p style="padding:20px;"> <p class="show"> <p class="picture" :style="'backgroundimage:url('+headerimage+')'"></p> </p> <p style="margin-top:20px;"> <input type="file" id="upload" accept="image/jpg" @change="upload"> <label for="upload"></label> </p> </p> </p> </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
推荐阅读:
如何使用vue.extend实现alert模态框弹窗组件
如何使用vue组件实现弹出框点击显示隐藏
以上就是如何使用vue2.0调用摄像头进行拍照的详细内容。
