H5图片压缩代码
来源:互联网 发布:910九玩诛仙手游端口 编辑:程序博客网 时间:2024/06/09 19:46
mobileFix.mini.js
function JPEGEncoder(l) { var o = this; var s = Math.round; var k = Math.floor; var O = new Array(64); var K = new Array(64); var d = new Array(64); var Z = new Array(64); var u; var h; var G; var T; var n = new Array(65535); var m = new Array(65535); var P = new Array(64); var S = new Array(64); var j = []; var t = 0; var a = 7; var A = new Array(64); var f = new Array(64); var U = new Array(64); var e = new Array(256); var C = new Array(2048); var x; var i = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63]; var g = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]; var c = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; var w = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125]; var E = [1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97, 7, 34, 113, 20, 50, 129, 145, 161, 8, 35, 66, 177, 193, 21, 82, 209, 240, 36, 51, 98, 114, 130, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40, 41, 42, 52, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250]; var v = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]; var Y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; var J = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119]; var B = [0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97, 113, 19, 34, 50, 129, 8, 20, 66, 145, 161, 177, 193, 9, 35, 51, 82, 240, 21, 98, 114, 209, 10, 22, 36, 52, 225, 37, 241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 130, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242, 243, 244, 245, 246, 247, 248, 249, 250]; function M(ag) { var af = [16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99]; for (var ae = 0; ae < 64; ae++) { var aj = k((af[ae] * ag + 50) / 100); if (aj < 1) { aj = 1 } else { if (aj > 255) { aj = 255 } } O[i[ae]] = aj } var ah = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99]; for (var ad = 0; ad < 64; ad++) { var ai = k((ah[ad] * ag + 50) / 100); if (ai < 1) { ai = 1 } else { if (ai > 255) { ai = 255 } } K[i[ad]] = ai } var ac = [1, 1.387039845, 1.306562965, 1.175875602, 1, 0.785694958, 0.5411961, 0.275899379]; var ab = 0; for (var ak = 0; ak < 8; ak++) { for (var aa = 0; aa < 8; aa++) { d[ab] = (1 / (O[i[ab]] * ac[ak] * ac[aa] * 8)); Z[ab] = (1 / (K[i[ab]] * ac[ak] * ac[aa] * 8)); ab++ } } } function q(ae, aa) { var ad = 0; var ag = 0; var af = new Array(); for (var ab = 1; ab <= 16; ab++) { for (var ac = 1; ac <= ae[ab]; ac++) { af[aa[ag]] = []; af[aa[ag]][0] = ad; af[aa[ag]][1] = ab; ag++; ad++ } ad *= 2 } return af } function W() { u = q(g, c); h = q(v, Y); G = q(w, E); T = q(J, B) } function z() { var ac = 1; var ab = 2; for (var aa = 1; aa <= 15; aa++) { for (var ad = ac; ad < ab; ad++) { m[32767 + ad] = aa; n[32767 + ad] = []; n[32767 + ad][1] = aa; n[32767 + ad][0] = ad } for (var ae = -(ab - 1); ae <= -ac; ae++) { m[32767 + ae] = aa; n[32767 + ae] = []; n[32767 + ae][1] = aa; n[32767 + ae][0] = ab - 1 + ae } ac <<= 1; ab <<= 1 } } function V() { for (var aa = 0; aa < 256; aa++) { C[aa] = 19595 * aa; C[(aa + 256) >> 0] = 38470 * aa; C[(aa + 512) >> 0] = 7471 * aa + 32768; C[(aa + 768) >> 0] = -11059 * aa; C[(aa + 1024) >> 0] = -21709 * aa; C[(aa + 1280) >> 0] = 32768 * aa + 8421375; C[(aa + 1536) >> 0] = -27439 * aa; C[(aa + 1792) >> 0] = -5329 * aa } } function X(aa) { var ac = aa[0]; var ab = aa[1] - 1; while (ab >= 0) { if (ac & (1 << ab)) { t |= (1 << a) } ab--; a--; if (a < 0) { if (t == 255) { F(255); F(0) } else { F(t) } a = 7; t = 0 } } } function F(aa) { j.push(e[aa]) } function p(aa) { F((aa >> 8) & 255); F((aa) & 255) } function N(aZ, ap) { var aL, aK, aJ, aI, aH, aD, aC, aB; var aN = 0; var aR; const aq = 8; const ai = 64; for (aR = 0; aR < aq; ++aR) { aL = aZ[aN]; aK = aZ[aN + 1]; aJ = aZ[aN + 2]; aI = aZ[aN + 3]; aH = aZ[aN + 4]; aD = aZ[aN + 5]; aC = aZ[aN + 6]; aB = aZ[aN + 7]; var aY = aL + aB; var aO = aL - aB; var aX = aK + aC; var aP = aK - aC; var aU = aJ + aD; var aQ = aJ - aD; var aT = aI + aH; var aS = aI - aH; var an = aY + aT; var ak = aY - aT; var am = aX + aU; var al = aX - aU; aZ[aN] = an + am; aZ[aN + 4] = an - am; var ax = (al + ak) * 0.707106781; aZ[aN + 2] = ak + ax; aZ[aN + 6] = ak - ax; an = aS + aQ; am = aQ + aP; al = aP + aO; var at = (an - al) * 0.382683433; var aw = 0.5411961 * an + at; var au = 1.306562965 * al + at; var av = am * 0.707106781; var ah = aO + av; var ag = aO - av; aZ[aN + 5] = ag + aw; aZ[aN + 3] = ag - aw; aZ[aN + 1] = ah + au; aZ[aN + 7] = ah - au; aN += 8 } aN = 0; for (aR = 0; aR < aq; ++aR) { aL = aZ[aN]; aK = aZ[aN + 8]; aJ = aZ[aN + 16]; aI = aZ[aN + 24]; aH = aZ[aN + 32]; aD = aZ[aN + 40]; aC = aZ[aN + 48]; aB = aZ[aN + 56]; var ar = aL + aB; var aj = aL - aB; var az = aK + aC; var ae = aK - aC; var aG = aJ + aD; var ac = aJ - aD; var aW = aI + aH; var aa = aI - aH; var ao = ar + aW; var aV = ar - aW; var ay = az + aG; var aF = az - aG; aZ[aN] = ao + ay; aZ[aN + 32] = ao - ay; var af = (aF + aV) * 0.707106781; aZ[aN + 16] = aV + af; aZ[aN + 48] = aV - af; ao = aa + ac; ay = ac + ae; aF = ae + aj; var aM = (ao - aF) * 0.382683433; var ad = 0.5411961 * ao + aM; var a1 = 1.306562965 * aF + aM; var ab = ay * 0.707106781; var a0 = aj + ab; var aA = aj - ab; aZ[aN + 40] = aA + ad; aZ[aN + 24] = aA - ad; aZ[aN + 8] = a0 + a1; aZ[aN + 56] = a0 - a1; aN++ } var aE; for (aR = 0; aR < ai; ++aR) { aE = aZ[aR] * ap[aR]; P[aR] = (aE > 0) ? ((aE + 0.5) | 0) : ((aE - 0.5) | 0) } return P } function b() { p(65504); p(16); F(74); F(70); F(73); F(70); F(0); F(1); F(1); F(0); p(1); p(1); F(0); F(0) } function r(aa, ab) { p(65472); p(17); F(8); p(ab); p(aa); F(3); F(1); F(17); F(0); F(2); F(17); F(1); F(3); F(17); F(1) } function D() { p(65499); p(132); F(0); for (var ab = 0; ab < 64; ab++) { F(O[ab]) } F(1); for (var aa = 0; aa < 64; aa++) { F(K[aa]) } } function H() { p(65476); p(418); F(0); for (var ae = 0; ae < 16; ae++) { F(g[ae + 1]) } for (var ad = 0; ad <= 11; ad++) { F(c[ad]) } F(16); for (var ac = 0; ac < 16; ac++) { F(w[ac + 1]) } for (var ab = 0; ab <= 161; ab++) { F(E[ab]) } F(1); for (var aa = 0; aa < 16; aa++) { F(v[aa + 1]) } for (var ah = 0; ah <= 11; ah++) { F(Y[ah]) } F(17); for (var ag = 0; ag < 16; ag++) { F(J[ag + 1]) } for (var af = 0; af <= 161; af++) { F(B[af]) } } function I() { p(65498); p(12); F(3); F(1); F(0); F(2); F(17); F(3); F(17); F(0); F(63); F(0) } function L(ad, aa, al, at, ap) { var ag = ap[0]; var ab = ap[240]; var ac; const ar = 16; const ai = 63; const ah = 64; var aq = N(ad, aa); for (var am = 0; am < ah; ++am) { S[i[am]] = aq[am] } var an = S[0] - al; al = S[0]; if (an == 0) { X(at[0]) } else { ac = 32767 + an; X(at[m[ac]]); X(n[ac]) } var ae = 63; for (; (ae > 0) && (S[ae] == 0); ae--) {} if (ae == 0) { X(ag); return al } var ao = 1; var au; while (ao <= ae) { var ak = ao; for (; (S[ao] == 0) && (ao <= ae); ++ao) {} var aj = ao - ak; if (aj >= ar) { au = aj >> 4; for (var af = 1; af <= au; ++af) { X(ab) } aj = aj & 15 } ac = 32767 + S[ao]; X(ap[(aj << 4) + m[ac]]); X(n[ac]); ao++ } if (ae != ai) { X(ag) } return al } function y() { var ab = String.fromCharCode; for (var aa = 0; aa < 256; aa++) { e[aa] = ab(aa) } } this.encode = function(an, aj, aB) { var aa = new Date().getTime(); if (aj) { R(aj) } j = new Array(); t = 0; a = 7; p(65496); b(); D(); r(an.width, an.height); H(); I(); var al = 0; var aq = 0; var ao = 0; t = 0; a = 7; this.encode.displayName = "_encode_"; var at = an.data; var ar = an.width; var aA = an.height; var ay = ar * 4; var ai = ar * 3; var ah, ag = 0; var am, ax, az; var ab, ap, ac, af, ae; while (ag < aA) { ah = 0; while (ah < ay) { ab = ay * ag + ah; ap = ab; ac = -1; af = 0; for (ae = 0; ae < 64; ae++) { af = ae >> 3; ac = (ae & 7) * 4; ap = ab + (af * ay) + ac; if (ag + af >= aA) { ap -= (ay * (ag + 1 + af - aA)) } if (ah + ac >= ay) { ap -= ((ah + ac) - ay + 4) } am = at[ap++]; ax = at[ap++]; az = at[ap++]; A[ae] = ((C[am] + C[(ax + 256) >> 0] + C[(az + 512) >> 0]) >> 16) - 128; f[ae] = ((C[(am + 768) >> 0] + C[(ax + 1024) >> 0] + C[(az + 1280) >> 0]) >> 16) - 128; U[ae] = ((C[(am + 1280) >> 0] + C[(ax + 1536) >> 0] + C[(az + 1792) >> 0]) >> 16) - 128 } al = L(A, d, al, u, G); aq = L(f, Z, aq, h, T); ao = L(U, Z, ao, h, T); ah += 32 } ag += 8 } if (a >= 0) { var aw = []; aw[1] = a + 1; aw[0] = (1 << (a + 1)) - 1; X(aw) } p(65497); if (aB) { var av = j.length; var aC = new Uint8Array(av); for (var au = 0; au < av; au++) { aC[au] = j[au].charCodeAt() } j = []; var ak = new Date().getTime() - aa; console.log("Encoding time: " + ak + "ms"); return aC } var ad = "data:image/jpeg;base64," + btoa(j.join("")); j = []; var ak = new Date().getTime() - aa; console.log("Encoding time: " + ak + "ms"); return ad }; function R(ab) { if (ab <= 0) { ab = 1 } if (ab > 100) { ab = 100 } if (x == ab) { return } var aa = 0; if (ab < 50) { aa = Math.floor(5000 / ab) } else { aa = Math.floor(200 - ab * 2) } M(aa); x = ab; console.log("Quality set to: " + ab + "%") } function Q() { var aa = new Date().getTime(); if (!l) { l = 50 } y(); W(); z(); V(); R(l); var ab = new Date().getTime() - aa; console.log("Initialization " + ab + "ms") } Q()};
lrz.js
/** * lrz3 * https://github.com/think2011/localResizeIMG3 * @author think2011 */;(function () { window.URL = window.URL || window.webkitURL; var userAgent = navigator.userAgent; /** * 客户端压缩图片 * @param file * @param [options] * @param callback * @constructor */ function Lrz(file, options, callback) { this.file = file; this.callback = callback; this.defaults = {quality: 7}; // 适应传入的参数 if (callback) { for (var p in options) { this.defaults[p] = options[p]; } if (this.defaults.quality > 10) this.defaults.quality = 10; } else { this.callback = options; } this.results = { blob: null, origin: null, base64: null }; this.init(); } Lrz.prototype = { constructor: Lrz, /** * 初始化 */ init: function () { var that = this; that.create(that.file, that.callback); }, /** * 生成base64 * @param file * @param callback */ create: function (file, callback) { var that = this, img = new Image(), results = that.results, blob = URL.createObjectURL(file); img.onload = function () { // 获得图片缩放尺寸 var resize = that.resize(this); // 初始化canva var canvas = document.createElement('canvas'), ctx; canvas.width = resize.w; canvas.height = resize.h; ctx = canvas.getContext('2d'); // 调整正确的拍摄方向 var mpImg = new MegaPixImage(img); EXIF.getData(img, function () { mpImg.render(canvas, { width: canvas.width, height: canvas.height, orientation: EXIF.getTag(this, "Orientation") }); // 设置白色背景 ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 生成结果 results.blob = blob; results.origin = file; ctx.drawImage(img,0, 0, resize.w, resize.h); // 兼容 Android if (/Android/i.test(userAgent)) { try { var encoder = new JPEGEncoder(); results.base64 = encoder.encode(ctx.getImageData(0, 0, canvas.width, canvas.height), that.defaults.quality * 100); } catch (_error) { alert('未引用mobile补丁,无法生成图片。'); } } // 其他情况&IOS else { results.base64 = canvas.toDataURL('image/jpeg', that.defaults.quality); } // 执行回调 callback(results); }); }; img.src = blob; }, /** * 获得图片的缩放尺寸 * @param img * @returns {{w: (Number), h: (Number)}} */ resize: function (img) { var w = this.defaults.width, h = this.defaults.height, scale = img.width / img.height, ret = {w: img.width, h: img.height}; if (w & h) { ret.w = w; ret.h = h; } else if (w) { ret.w = w; ret.h = Math.ceil(w / scale); } else if (h) { ret.w = Math.ceil(h * scale); ret.h = h; } return ret; } }; // 暴露接口 window.lrz = function (file, options, callback) { return new Lrz(file, options, callback); };})()
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));/** * Mega pixel image rendering library for iOS6 Safari * * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), * which causes unexpected subsampling when drawing it in canvas. * By using this library, you can safely render the image with proper stretching. * * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com> * Released under the MIT license */(function() { /** * Detect subsampling in loaded image. * In iOS, larger images than 2M pixels may be subsampled in rendering. */ function detectSubsampling(img) { var iw = img.naturalWidth, ih = img.naturalHeight; if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image var canvas = document.createElement('canvas'); canvas.width = canvas.height = 1; var ctx = canvas.getContext('2d'); ctx.drawImage(img, -iw + 1, 0); // subsampled image becomes half smaller in rendering size. // check alpha channel value to confirm image is covering edge pixel or not. // if alpha value is 0 image is not covering, hence subsampled. return ctx.getImageData(0, 0, 1, 1).data[3] === 0; } else { return false; } } /** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into canvas for some images. */ function detectVerticalSquash(img, iw, ih) { var canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var data = ctx.getImageData(0, 0, 1, ih).data; // search image edge pixel position in case it is squashed vertically. var sy = 0; var ey = ih; var py = ih; while (py > sy) { var alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } var ratio = (py / ih); return (ratio===0)?1:ratio; } /** * Rendering image element (with resizing) and get its data URL */ function renderImageToDataURL(img, options, doSquash) { var canvas = document.createElement('canvas'); renderImageToCanvas(img, canvas, options, doSquash); return canvas.toDataURL("image/jpeg", options.quality || 0.8); } /** * Rendering image element (with resizing) into the canvas element */ function renderImageToCanvas(img, canvas, options, doSquash) { var iw = img.naturalWidth, ih = img.naturalHeight; if (!(iw+ih)) return; var width = options.width, height = options.height; var ctx = canvas.getContext('2d'); ctx.save(); transformCoordinate(canvas, ctx, width, height, options.orientation); var subsampled = detectSubsampling(img); if (subsampled) { iw /= 2; ih /= 2; } var d = 1024; // size of tiling canvas var tmpCanvas = document.createElement('canvas'); tmpCanvas.width = tmpCanvas.height = d; var tmpCtx = tmpCanvas.getContext('2d'); var vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1; var dw = Math.ceil(d * width / iw); var dh = Math.ceil(d * height / ih / vertSquashRatio); var sy = 0; var dy = 0; while (sy < ih) { var sx = 0; var dx = 0; while (sx < iw) { tmpCtx.clearRect(0, 0, d, d); tmpCtx.drawImage(img, -sx, -sy); ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh); sx += d; dx += dw; } sy += d; dy += dh; } ctx.restore(); tmpCanvas = tmpCtx = null; } /** * Transform canvas coordination according to specified frame size and orientation * Orientation value is from EXIF tag */ function transformCoordinate(canvas, ctx, width, height, orientation) { switch (orientation) { case 5: case 6: case 7: case 8: canvas.width = height; canvas.height = width; break; default: canvas.width = width; canvas.height = height; } switch (orientation) { case 2: // horizontal flip ctx.translate(width, 0); ctx.scale(-1, 1); break; case 3: // 180 rotate left ctx.translate(width, height); ctx.rotate(Math.PI); break; case 4: // vertical flip ctx.translate(0, height); ctx.scale(1, -1); break; case 5: // vertical flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.scale(1, -1); break; case 6: // 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(0, -height); break; case 7: // horizontal flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(width, -height); ctx.scale(-1, 1); break; case 8: // 90 rotate left ctx.rotate(-0.5 * Math.PI); ctx.translate(-width, 0); break; default: break; } } var URL = window.URL && window.URL.createObjectURL ? window.URL : window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null; /** * MegaPixImage class */ function MegaPixImage(srcImage) { if (window.Blob && srcImage instanceof Blob) { if (!URL) { throw Error("No createObjectURL function found to create blob url"); } var img = new Image(); img.src = URL.createObjectURL(srcImage); this.blob = srcImage; srcImage = img; } if (!srcImage.naturalWidth && !srcImage.naturalHeight) { var _this = this; srcImage.onload = srcImage.onerror = function() { var listeners = _this.imageLoadListeners; if (listeners) { _this.imageLoadListeners = null; for (var i=0, len=listeners.length; i<len; i++) { listeners[i](); } } }; this.imageLoadListeners = []; } this.srcImage = srcImage; } /** * Rendering megapix image into specified target element */ MegaPixImage.prototype.render = function(target, options, callback) { if (this.imageLoadListeners) { var _this = this; this.imageLoadListeners.push(function() { _this.render(target, options, callback); }); return; } options = options || {}; var imgWidth = this.srcImage.naturalWidth, imgHeight = this.srcImage.naturalHeight, width = options.width, height = options.height, maxWidth = options.maxWidth, maxHeight = options.maxHeight, doSquash = !this.blob || this.blob.type === 'image/jpeg'; if (width && !height) { height = (imgHeight * width / imgWidth) << 0; } else if (height && !width) { width = (imgWidth * height / imgHeight) << 0; } else { width = imgWidth; height = imgHeight; } if (maxWidth && width > maxWidth) { width = maxWidth; height = (imgHeight * width / imgWidth) << 0; } if (maxHeight && height > maxHeight) { height = maxHeight; width = (imgWidth * height / imgHeight) << 0; } var opt = { width : width, height : height }; for (var k in options) opt[k] = options[k]; var tagName = target.tagName.toLowerCase(); if (tagName === 'img') { target.src = renderImageToDataURL(this.srcImage, opt, doSquash); } else if (tagName === 'canvas') { renderImageToCanvas(this.srcImage, target, opt, doSquash); } if (typeof this.onrender === 'function') { this.onrender(target); } if (callback) { callback(); } if (this.blob) { this.blob = null; URL.revokeObjectURL(this.srcImage.src); } }; /** * Export class to global */ if (typeof define === 'function' && define.amd) { define([], function() { return MegaPixImage; }); // for AMD loader } else { this.MegaPixImage = MegaPixImage; }})();
index.js
(function () { var input = document.querySelector('input'); input.onchange = function () { lrz(this.files[0], {width: 400}, function (results) { // 你需要的数据都在这里,可以以字符串的形式传送base64给服务端转存为图片。 console.log(results); // 以下为演示用内容 var tip = document.querySelector('#tip'), report = document.querySelector('#report'), footer = document.querySelector('footer'); report.innerHTML = footer.innerHTML = ''; tip.innerHTML = '<p>正在生成和上传..</p> <small class="text-muted">演示使用了大量内存,可能会造成几秒内卡顿,不代表真实表现,请亲测。</small>'; demo_report('原始图片', results.blob, results.origin.size); setTimeout(function () { demo_report('客户端预压的图片', results.base64, results.base64.length * 0.8); // 发送到后端 var xhr = new XMLHttpRequest(); var data = { base64: results.base64, size: results.base64.length // 校验用,防止未完整接收 }; xhr.open('POST', '/'); xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var result = JSON.parse(xhr.response); result.error ? alert('服务端错误,未能保存图片') : demo_report('服务端实存的图片', result.src, result.size); tip.innerHTML = '<p>生成和上传完毕</p> <small class="text-muted">演示使用了大量内存,可能会造成几秒内卡顿,不代表真实表现,请亲测。</small>'; } }; xhr.send(JSON.stringify(data)); // 发送base64 }, 100); }); }; /** * 演示报告 * @param title * @param src * @param size */ function demo_report(title, src, size) { var img = new Image(), li = document.createElement('li'), size = (size / 1024).toFixed(2) + 'KB'; img.onload = function () { var content = '<ul>' + '<li>' + title + '(' + img.width + ' X ' + img.height + ')</li>' + '<li class="text-cyan">' + size + '</li>' + '</ul>'; li.className = 'item'; li.innerHTML = content; li.appendChild(img); document.querySelector('#report').appendChild(li); }; img.src = src; } // 演示用服务器太慢,做个延缓加载 window.onload = function () { input.style.display = 'block'; }})();
html
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>lrz3 demo</title></head><style> ul, li { margin: 0; padding: 0; list-style: none; } .text-cyan { color: cyan; } .text-muted { color: #999; } .item { position: relative; margin: 8px 0; } .item ul { font-size: 15px; position: absolute; top: 0; left: 0; color: #fff; text-shadow: 1px 1px 5px #000; border:1px dotted rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3); } .item ul li { margin: 10px 15px; } .item img { max-width: 100%; box-shadow: 1px 1px 5px #ccc; } footer { width: 100%; font-size: 12px; text-align: center; position: absolute; left: 0; bottom: 0; margin: 20px 0; } footer a { color: #777; } input { display: none; }</style><body><input type="file" capture="camera" /><!--<input type="file" accept="image/*" capture="camera" /> 部分手机无法正确限制图片格式 --><hr/><div id="tip"><!-- 演示提示 --></div><ul id="report"><!-- 演示报告 --></ul><footer> <p style=""><a href="https://github.com/think2011/localResizeIMG3">localResizeIMG3 by think2011</a></p></footer><script src="js/mobileFix.mini.js?v=ad62f13"></script><script src="js/exif.js?v=dd609b9"></script><script src="js/lrz.js?v=3d33fcf"></script><script src="js/index.js?v=c970150"></script></body></html>
阅读全文
0 0
- H5图片压缩代码
- js 压缩图片 H5
- js 压缩图片 H5
- H5+ 图片压缩上传
- H5 图片压缩上传
- js图片压缩-H5
- h5图片压缩
- H5图片压缩与上传
- H5 图片压缩上传解决方案
- H5图片压缩与上传
- h5图片上传和压缩
- H5压缩图片 AJAX上传图片
- H5压缩图片 AJAX上传图片
- H5 canvas实现客户端压缩图片上传
- H5多图片压缩加水印上传
- H5多图片压缩加水印上传
- 图片压缩代码
- 图片压缩代码
- vxWorks内核解读一--实时内核概述
- 理解HTTP幂等性
- 基于 EntityFramework 的数据库主从读写分离服务插件
- 5个Android开发中比较常见的内存泄漏问题及解决办法
- springoot 数据库
- H5图片压缩代码
- go语言在Windows系统下的安装并运行Hello World程序
- Oracle自动增长序列
- Java最大的优势真的在于跨平台吗?
- Spring Boot集成swagger
- 【VS应用】 VS.net中快捷键收缩和展开代码段
- TestNG入门相关网站
- 排序算法之希尔排序的C++实现
- 位置和传感器:运动传感器