本文实例为大家分享了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
暂无评论内容