手机网页版JS压缩上传图片--base64位 兼容IOS和安卓

原创 2016年05月31日 13:34:07

首先,我用到了一款插件,是纯JS压缩上传插件,第一次用CSDN,不太会用,我把插件所有代码拷贝在文章末尾。
加载JS插件<script src="__JS__/dist/lrz.mobile.min.js"></script>


页面上传图片:

    <div class="fileupload-buttonbar">
        <a type="button" class="am-btn am-btn-sm am-fl " style="  line-height: 0.2;"><img
                src="__IMG__/image.png"></a>

        <div class="fileinput-button" style="width: 100%">
            <input type="file" name="files" class="btn" id="choose"
                   style="left: 35px;position:absolute;z-index: 1;width: 35px;height:40px;opacity: 0;cursor: pointer;"
                   data-url="{:U('Core/File/uploadPictureBase64')}" multiple/></div>

        <style>
            .img-list li {
                float: left;
                position: relative;
                display: inline-block;
                width: 100px;
                height: 100px;
                margin: 5px 5px 20px 5px;
                border: 1px solid rgb(100, 149, 198);
                background: #fff no-repeat center;
                background-size: cover;
                border-radius: 5px;
            }
        </style>
    </div>
    <!--插入图片表情结束-->
    <!--发布按钮-->
    <p class="submitweibo" url="{:U('Mob/Weibo/doSend')}">
        <button style="float: right" type="submit" class="am-btn am-btn-primary am-btn-block">发布</button>
    </p>
    <!--发布按钮END-->
</div>
<ul class="img-list am-fl" style="padding-left:0px;">
    <!--图片显示区域-->
</ul>

图片id存放,隐藏input,放在页面的form表单内即可。

<input type="hidden" id="img_ids" name="attach_ids" value="">



js代码

//新上传图片
function add_img() {
    var filechooser = document.getElementById("choose");
    $("#upload").on("click", function () {
        filechooser.click();
    })
    filechooser.onchange = function () {
        if (!this.files.length) return;
        var files = Array.prototype.slice.call(this.files);
        if (files.length > 9) {
            alert("最多同时只可上传9张图片");
            return;
        }
        files.forEach(function (files, i) {
            if (!/\/(?:jpeg|png|gif)/i.test(files.type)){
                toast.error('上传图片格式不符!');
            }
            var div = ' <li class="waitbox loadingBox">\
            <img src= ' + _LOADING_ + '  style="width:90px,hight:90px"> \
        </li> ';
            $('.img-list').append(div);
            lrz(files, {
                width: 1200,
                height: 900,
                before: function () {
                    console.log('压缩开始');
                },
                fail: function (err) {
                    console.error(err);
                },
                always: function () {
                    console.log('压缩结束');
                },
                done: function (results) {
                    // 你需要的数据都在这里,可以以字符串的形式传送base64给服务端转存为图片。
                    var data=results.base64;
                    upload(data);
                }
            });
        })
    }
}

function removeLi(li,file_id) {
console.log(li)
    upAttachVal('remove', file_id, $('#img_ids'))
    $(li).parent('.waitbox').remove();


}
//图片上传,返回id ,地址
function upload(data) {
    console.log(data);
    var dataUrl = U('Core/File/uploadPictureBase64');
    $.post(dataUrl, {data: data}, function (msg) {
        if (msg.status == 1) {
            var ids = $('#img_ids').val();
            upAttachVal('add', msg.id, $('#img_ids'));
            //上传成功显示图片
            var div = ' <li class="waitbox">\
                <a class="del-btn am-icon-close"  onclick="removeLi(this, '+msg.id+')" style="position:absolute;right: 5px;top: -5px;color: red"></a>\
            <img src= ' + msg.path + '  style="width:99px;height:99px;"> \
        </li> ';
            $('.loadingBox').hide();
            $('.img-list').append(div);
        } else {
            toast.error(msg.info);
        }
    }, 'json')

}

function upAttachVal(type, attachId, obj) {
    var $attach_ids = obj;
    var attachVal = $attach_ids.val();
    var attachArr = attachVal.split(',');
    var newArr = [];

    for (var i in attachArr) {
        if (attachArr[i] !== '' && attachArr[i] !== attachId.toString()) {
            newArr.push(attachArr[i]);
        }
    }
    type === 'add' && newArr.push(attachId);
    if (newArr.length <= 9) {
        $attach_ids.val(newArr.join(','));
        return newArr;
    } else {
        return false;
    }

}




后台php代码:

public function uploadPictureBase64()
{

    $aData = $_POST['data'];

    if ($aData == '' || $aData == 'undefined') {
        $this->ajaxReturn(array('status'=>0,'info'=>'参数错误'));
    }

    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $aData, $result)) {
        $base64_body = substr(strstr($aData, ','), 1);

        empty($aExt) && $aExt = $result[2];
    } else {
        $base64_body = $aData;
    }

    empty($aExt) && $aExt = 'jpg';

    $pictureModel = D('Picture');

    $md5 = md5($base64_body);
    $sha1 = sha1($base64_body);


    $check = $pictureModel->where(array('md5' => $md5, 'sha1' => $sha1))->find();

    if ($check) {
        //已存在则直接返回信息
        $return['id'] = $check['id'];
        $return['path'] = render_picture_path($check['path']);
        $this->ajaxReturn(array('status'=>1,'id'=>$return['id'],'path'=> $return['path']));
    } else {
        //不存在则上传并返回信息
        $driver = modC('PICTURE_UPLOAD_DRIVER','local','config');
        $driver = check_driver_is_exist($driver);
        $date = date('Y-m-d');
        $saveName = uniqid();
        $savePath = '/Uploads/Picture/' . $date . '/';

        $path = $savePath . $saveName . '.' . $aExt;
        if($driver == 'local'){
            //本地上传
            mkdir('.' . $savePath, 0777, true);
            $data = base64_decode($base64_body);
            $rs = file_put_contents('.' . $path, $data);
        }
        else{
            $rs = false;
            //使用云存储
            $name = get_addon_class($driver);
            if (class_exists($name)) {
                $class = new $name();
                if (method_exists($class, 'uploadBase64')) {
                    $path = $class->uploadBase64($base64_body,$path);
                    $rs = true;
                }
            }
        }
        if ($rs) {
            $pic['type'] = $driver;
            $pic['path'] = $path;
            $pic['md5'] = $md5;
            $pic['sha1'] = $sha1;
            $pic['status'] = 1;
            $pic['create_time'] = time();
            $id = $pictureModel->add($pic);
           $this->ajaxReturn (array('status'=>1,'id' => $id, 'path' => render_picture_path($path)));
        } else {
            $this->ajaxReturn(array('status'=>0,'图片上传失败。'));
        }

    }
}


function render_picture_path($path)
{
    $path = get_pic_src($path);
    return is_bool(strpos($path, 'http://')) ? 'http://' . str_replace('//', '/', $_SERVER['HTTP_HOST'] . '/' . $path) : $path;
}

function get_pic_src($path)
{

    //不存在http://
    $not_http_remote = (strpos($path, 'http://') === false);
    //不存在https://
    $not_https_remote = (strpos($path, 'https://') === false);
    if ($not_http_remote && $not_https_remote) {
        //本地url
        return str_replace('//', '/', getRootUrl() . $path); //防止双斜杠的出现
    } else {
        //远端url
        return $path;
    }
}



插件代码:

!function (e) {
    Array.prototype.map || (Array.prototype.map = function (e, r) {
        var a, t, n;
        if (null == this)throw new TypeError(" this is null or not defined");
        var o = Object(this), i = o.length >>> 0;
        if ("function" != typeof e)throw new TypeError(e + " is not a function");
        for (r && (a = r), t = Array(i), n = 0; i > n;) {
            var l, d;
            n in o && (l = o[n], d = e.call(a, l, n, o), t[n] = d), n++
        }
        return t
    });
    var r = e.detect = function () {
        var e = function () {
        }, r = {
            browser_parsers: [{
                regex: "^(Opera)/(\\d+)\\.(\\d+) \\(Nintendo Wii",
                family_replacement: "Wii",
                manufacturer: "Nintendo"
            }, {
                regex: "(SeaMonkey|Camino)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)",
                family_replacement: "Camino",
                other: !0
            }, {
                regex: "(Pale[Mm]oon)/(\\d+)\\.(\\d+)\\.?(\\d+)?",
                family_replacement: "Pale Moon (Firefox Variant)",
                other: !0
            }, {
                regex: "(Fennec)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)",
                family_replacement: "Firefox Mobile"
            }, {
                regex: "(Fennec)/(\\d+)\\.(\\d+)(pre)",
                family_replacment: "Firefox Mobile"
            }, {
                regex: "(Fennec)/(\\d+)\\.(\\d+)",
                family_replacement: "Firefox Mobile"
            }, {
                regex: "Mobile.*(Firefox)/(\\d+)\\.(\\d+)",
                family_replacement: "Firefox Mobile"
            }, {
                regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?)",
                family_replacement: "Firefox ($1)"
            }, {
                regex: "(Firefox)/(\\d+)\\.(\\d+)(a\\d+[a-z]*)",
                family_replacement: "Firefox Alpha"
            }, {
                regex: "(Firefox)/(\\d+)\\.(\\d+)(b\\d+[a-z]*)",
                family_replacement: "Firefox Beta"
            }, {
                regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(a\\d+[a-z]*)",
                family_replacement: "Firefox Alpha"
            }, {
                regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(b\\d+[a-z]*)",
                family_replacement: "Firefox Beta"
            }, {
                regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?",
                family_replacement: "Firefox ($1)"
            }, {
                regex: "(Firefox).*Tablet browser (\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "MicroB",
                tablet: !0
            }, {regex: "(MozillaDeveloperPreview)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?"}, {
                regex: "(Flock)/(\\d+)\\.(\\d+)(b\\d+?)",
                family_replacement: "Flock",
                other: !0
            }, {
                regex: "(RockMelt)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Rockmelt",
                other: !0
            }, {
                regex: "(Navigator)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Netscape"
            }, {
                regex: "(Navigator)/(\\d+)\\.(\\d+)([ab]\\d+)",
                family_replacement: "Netscape"
            }, {
                regex: "(Netscape6)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Netscape"
            }, {
                regex: "(MyIBrow)/(\\d+)\\.(\\d+)",
                family_replacement: "My Internet Browser",
                other: !0
            }, {
                regex: "(Opera Tablet).*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                family_replacement: "Opera Tablet",
                tablet: !0
            }, {
                regex: "(Opera)/.+Opera Mobi.+Version/(\\d+)\\.(\\d+)",
                family_replacement: "Opera Mobile"
            }, {regex: "Opera Mobi", family_replacement: "Opera Mobile"}, {
                regex: "(Opera Mini)/(\\d+)\\.(\\d+)",
                family_replacement: "Opera Mini"
            }, {
                regex: "(Opera Mini)/att/(\\d+)\\.(\\d+)",
                family_replacement: "Opera Mini"
            }, {
                regex: "(Opera)/9.80.*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                family_replacement: "Opera"
            }, {regex: "(webOSBrowser)/(\\d+)\\.(\\d+)", family_replacement: "webOS"}, {
                regex: "(webOS)/(\\d+)\\.(\\d+)",
                family_replacement: "webOS"
            }, {regex: "(wOSBrowser).+TouchPad/(\\d+)\\.(\\d+)", family_replacement: "webOS TouchPad"}, {
                regex: "(luakit)",
                family_replacement: "LuaKit",
                other: !0
            }, {
                regex: "(Lightning)/(\\d+)\\.(\\d+)([ab]?\\d+[a-z]*)",
                family_replacement: "Lightning",
                other: !0
            }, {
                regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?) \\(Swiftfox\\)",
                family_replacement: "Swiftfox",
                other: !0
            }, {
                regex: "(Firefox)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)? \\(Swiftfox\\)",
                family_replacement: "Swiftfox",
                other: !0
            }, {
                regex: "rekonq",
                family_replacement: "Rekonq",
                other: !0
            }, {
                regex: "(conkeror|Conkeror)/(\\d+)\\.(\\d+)\\.?(\\d+)?",
                family_replacement: "Conkeror",
                other: !0
            }, {
                regex: "(konqueror)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Konqueror",
                other: !0
            }, {
                regex: "(WeTab)-Browser",
                family_replacement: "WeTab",
                other: !0
            }, {
                regex: "(Comodo_Dragon)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Comodo Dragon",
                other: !0
            }, {
                regex: "(YottaaMonitor)",
                family_replacement: "Yottaa Monitor",
                other: !0
            }, {regex: "(Kindle)/(\\d+)\\.(\\d+)", family_replacement: "Kindle"}, {
                regex: "(Symphony) (\\d+).(\\d+)",
                family_replacement: "Symphony",
                other: !0
            }, {
                regex: "Minimo",
                family_replacement: "Minimo",
                other: !0
            }, {
                regex: "(CrMo)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Chrome Mobile"
            }, {
                regex: "(CriOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Chrome Mobile iOS"
            }, {
                regex: "(Chrome)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+) Mobile",
                family_replacement: "Chrome Mobile"
            }, {
                regex: "(chromeframe)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Chrome Frame"
            }, {
                regex: "(UC Browser)(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "UC Browser",
                other: !0
            }, {
                regex: "(SLP Browser)/(\\d+)\\.(\\d+)",
                family_replacement: "Tizen Browser",
                other: !0
            }, {
                regex: "(Epiphany)/(\\d+)\\.(\\d+).(\\d+)",
                family_replacement: "Epiphany",
                other: !0
            }, {
                regex: "(SE 2\\.X) MetaSr (\\d+)\\.(\\d+)",
                family_replacement: "Sogou Explorer",
                other: !0
            }, {
                regex: "(Pingdom.com_bot_version_)(\\d+)\\.(\\d+)",
                family_replacement: "PingdomBot",
                other: !0
            }, {
                regex: "(facebookexternalhit)/(\\d+)\\.(\\d+)",
                family_replacement: "FacebookBot"
            }, {
                regex: "(Twitterbot)/(\\d+)\\.(\\d+)",
                family_replacement: "TwitterBot"
            }, {regex: "(AdobeAIR|Chromium|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iron|Iris|UP\\.Browser|Bunjaloo|Google Earth|Raven for Mac)/(\\d+)\\.(\\d+)\\.(\\d+)"}, {regex: "(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Iron|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris)/(\\d+)\\.(\\d+)"}, {regex: "(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\d+)\\.(\\d+)\\.(\\d+)"}, {regex: "(iCab|Lunascape|Opera|Android|Jasmine|Polaris|BREW) (\\d+)\\.(\\d+)\\.?(\\d+)?"}, {
                regex: "(Android) Donut",
                v2_replacement: "2",
                v1_replacement: "1"
            }, {regex: "(Android) Eclair", v2_replacement: "1", v1_replacement: "2"}, {
                regex: "(Android) Froyo",
                v2_replacement: "2",
                v1_replacement: "2"
            }, {regex: "(Android) Gingerbread", v2_replacement: "3", v1_replacement: "2"}, {
                regex: "(Android) Honeycomb",
                v1_replacement: "3"
            }, {
                regex: "(IEMobile)[ /](\\d+)\\.(\\d+)",
                family_replacement: "IE Mobile"
            }, {
                regex: "(MSIE) (\\d+)\\.(\\d+).*XBLWP7",
                family_replacement: "IE Large Screen"
            }, {regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+)"}, {regex: "(Firefox)/(\\d+)\\.(\\d+)(pre|[ab]\\d+[a-z]*)?"}, {
                regex: "(Obigo)InternetBrowser",
                other: !0
            }, {regex: "(Obigo)\\-Browser", other: !0}, {
                regex: "(Obigo|OBIGO)[^\\d]*(\\d+)(?:.(\\d+))?",
                other: !0
            }, {
                regex: "(MAXTHON|Maxthon) (\\d+)\\.(\\d+)",
                family_replacement: "Maxthon",
                other: !0
            }, {regex: "(Maxthon|MyIE2|Uzbl|Shiira)", v1_replacement: "0", other: !0}, {
                regex: "(PLAYSTATION) (\\d+)",
                family_replacement: "PlayStation",
                manufacturer: "Sony"
            }, {
                regex: "(PlayStation Portable)[^\\d]+(\\d+).(\\d+)",
                manufacturer: "Sony"
            }, {regex: "(BrowseX) \\((\\d+)\\.(\\d+)\\.(\\d+)", other: !0}, {
                regex: "(POLARIS)/(\\d+)\\.(\\d+)",
                family_replacement: "Polaris",
                other: !0
            }, {
                regex: "(Embider)/(\\d+)\\.(\\d+)",
                family_replacement: "Polaris",
                other: !0
            }, {
                regex: "(BonEcho)/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Bon Echo",
                other: !0
            }, {
                regex: "(iPod).+Version/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPod).*Version/(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPod)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPhone).*Version/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPhone).*Version/(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPhone)",
                family_replacement: "Mobile Safari",
                manufacturer: "Apple"
            }, {
                regex: "(iPad).*Version/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                tablet: !0,
                manufacturer: "Apple"
            }, {
                regex: "(iPad).*Version/(\\d+)\\.(\\d+)",
                family_replacement: "Mobile Safari",
                tablet: !0,
                manufacturer: "Apple"
            }, {
                regex: "(iPad)",
                family_replacement: "Mobile Safari",
                tablet: !0,
                manufacturer: "Apple"
            }, {regex: "(AvantGo) (\\d+).(\\d+)", other: !0}, {
                regex: "(Avant)",
                v1_replacement: "1",
                other: !0
            }, {
                regex: "^(Nokia)",
                family_replacement: "Nokia Services (WAP) Browser",
                manufacturer: "Nokia"
            }, {
                regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)\\.(\\d+)",
                manufacturer: "Nokia"
            }, {
                regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)",
                manufacturer: "Nokia"
            }, {
                regex: "(NokiaBrowser)/(\\d+)\\.(\\d+)",
                manufacturer: "Nokia"
            }, {
                regex: "(BrowserNG)/(\\d+)\\.(\\d+).(\\d+)",
                family_replacement: "NokiaBrowser",
                manufacturer: "Nokia"
            }, {
                regex: "(Series60)/5\\.0",
                v2_replacement: "0",
                v1_replacement: "7",
                family_replacement: "NokiaBrowser",
                manufacturer: "Nokia"
            }, {
                regex: "(Series60)/(\\d+)\\.(\\d+)",
                family_replacement: "Nokia OSS Browser",
                manufacturer: "Nokia"
            }, {
                regex: "(S40OviBrowser)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Nokia Series 40 Ovi Browser",
                manufacturer: "Nokia"
            }, {
                regex: "(Nokia)[EN]?(\\d+)",
                manufacturer: "Nokia"
            }, {
                regex: "(PlayBook).+RIM Tablet OS (\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Blackberry WebKit",
                tablet: !0,
                manufacturer: "Nokia"
            }, {
                regex: "(Black[bB]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)",
                family_replacement: "Blackberry WebKit",
                manufacturer: "RIM"
            }, {
                regex: "(Black[bB]erry)\\s?(\\d+)",
                family_replacement: "Blackberry",
                manufacturer: "RIM"
            }, {regex: "(OmniWeb)/v(\\d+)\\.(\\d+)", other: !0}, {
                regex: "(Blazer)/(\\d+)\\.(\\d+)",
                family_replacement: "Palm Blazer",
                manufacturer: "Palm"
            }, {
                regex: "(Pre)/(\\d+)\\.(\\d+)",
                family_replacement: "Palm Pre",
                manufacturer: "Palm"
            }, {regex: "(Links) \\((\\d+)\\.(\\d+)", other: !0}, {
                regex: "(QtWeb) Internet Browser/(\\d+)\\.(\\d+)",
                other: !0
            }, {
                regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?",
                other: !0,
                tablet: !0
            }, {
                regex: "(AppleWebKit)/(\\d+)\\.?(\\d+)?\\+ .* Version/\\d+\\.\\d+.\\d+ Safari/",
                family_replacement: "WebKit Nightly"
            }, {
                regex: "(Version)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari/",
                family_replacement: "Safari"
            }, {regex: "(Safari)/\\d+"}, {
                regex: "(OLPC)/Update(\\d+)\\.(\\d+)",
                other: !0
            }, {
                regex: "(OLPC)/Update()\\.(\\d+)",
                v1_replacement: "0",
                other: !0
            }, {regex: "(SEMC\\-Browser)/(\\d+)\\.(\\d+)", other: !0}, {
                regex: "(Teleca)",
                family_replacement: "Teleca Browser",
                other: !0
            }, {regex: "Trident(.*)rv.(\\d+)\\.(\\d+)", family_replacement: "IE"}, {
                regex: "(MSIE) (\\d+)\\.(\\d+)",
                family_replacement: "IE"
            }],
            os_parsers: [{regex: "(Android) (\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"}, {regex: "(Android)\\-(\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"}, {
                regex: "(Android) Donut",
                os_v2_replacement: "2",
                os_v1_replacement: "1"
            }, {regex: "(Android) Eclair", os_v2_replacement: "1", os_v1_replacement: "2"}, {
                regex: "(Android) Froyo",
                os_v2_replacement: "2",
                os_v1_replacement: "2"
            }, {
                regex: "(Android) Gingerbread",
                os_v2_replacement: "3",
                os_v1_replacement: "2"
            }, {regex: "(Android) Honeycomb", os_v1_replacement: "3"}, {
                regex: "(Silk-Accelerated=[a-z]{4,5})",
                os_replacement: "Android"
            }, {regex: "(Windows Phone 6\\.5)"}, {
                regex: "(Windows (?:NT 5\\.2|NT 5\\.1))",
                os_replacement: "Windows XP"
            }, {regex: "(XBLWP7)", os_replacement: "Windows Phone OS"}, {
                regex: "(Windows NT 6\\.1)",
                os_replacement: "Windows 7"
            }, {
                regex: "(Windows NT 6\\.0)",
                os_replacement: "Windows Vista"
            }, {regex: "(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\\.0|Windows Vista|Windows 2000)"}, {
                regex: "(Windows NT 6\\.2)",
                os_replacement: "Windows 8"
            }, {regex: "(Windows Phone 8)", os_replacement: "Windows Phone 8"}, {
                regex: "(Windows NT 5\\.0)",
                os_replacement: "Windows 2000"
            }, {regex: "(Windows Phone OS) (\\d+)\\.(\\d+)"}, {
                regex: "(Windows ?Mobile)",
                os_replacement: "Windows Mobile"
            }, {regex: "(WinNT4.0)", os_replacement: "Windows NT 4.0"}, {
                regex: "(Win98)",
                os_replacement: "Windows 98"
            }, {regex: "(Tizen)/(\\d+)\\.(\\d+)", other: !0}, {
                regex: "(Mac OS X) (\\d+)[_.](\\d+)(?:[_.](\\d+))?",
                manufacturer: "Apple"
            }, {
                regex: "(?:PPC|Intel) (Mac OS X)",
                manufacturer: "Apple"
            }, {
                regex: "(CPU OS|iPhone OS) (\\d+)_(\\d+)(?:_(\\d+))?",
                os_replacement: "iOS",
                manufacturer: "Apple"
            }, {
                regex: "(iPhone|iPad|iPod); Opera",
                os_replacement: "iOS",
                manufacturer: "Apple"
            }, {
                regex: "(iPad); Opera",
                tablet: !0,
                manufacturer: "Apple"
            }, {
                regex: "(iPhone|iPad|iPod).*Mac OS X.*Version/(\\d+)\\.(\\d+)",
                os_replacement: "iOS",
                manufacturer: "Apple"
            }, {
                regex: "(CrOS) [a-z0-9_]+ (\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                os_replacement: "Chrome OS"
            }, {
                regex: "(Debian)-(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                other: !0
            }, {
                regex: "(Linux Mint)(?:/(\\d+))?",
                other: !0
            }, {
                regex: "(Mandriva)(?: Linux)?/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                other: !0
            }, {
                regex: "(Symbian[Oo][Ss])/(\\d+)\\.(\\d+)",
                os_replacement: "Symbian OS"
            }, {
                regex: "(Symbian/3).+NokiaBrowser/7\\.3",
                os_replacement: "Symbian^3 Anna"
            }, {regex: "(Symbian/3).+NokiaBrowser/7\\.4", os_replacement: "Symbian^3 Belle"}, {
                regex: "(Symbian/3)",
                os_replacement: "Symbian^3"
            }, {regex: "(Series 60|SymbOS|S60)", os_replacement: "Symbian OS"}, {
                regex: "(MeeGo)",
                other: !0
            }, {
                regex: "Symbian [Oo][Ss]",
                os_replacement: "Symbian OS"
            }, {
                regex: "(Black[Bb]erry)[0-9a-z]+/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                os_replacement: "BlackBerry OS",
                manufacturer: "RIM"
            }, {
                regex: "(Black[Bb]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                os_replacement: "BlackBerry OS",
                manufacturer: "RIM"
            }, {
                regex: "(RIM Tablet OS) (\\d+)\\.(\\d+)\\.(\\d+)",
                os_replacement: "BlackBerry Tablet OS",
                tablet: !0,
                manufacturer: "RIM"
            }, {
                regex: "(Play[Bb]ook)",
                os_replacement: "BlackBerry Tablet OS",
                tablet: !0,
                manufacturer: "RIM"
            }, {
                regex: "(Black[Bb]erry)",
                os_replacement: "Blackberry OS",
                manufacturer: "RIM"
            }, {
                regex: "(webOS|hpwOS)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
                os_replacement: "webOS"
            }, {
                regex: "(SUSE|Fedora|Red Hat|PCLinuxOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
                other: !0
            }, {
                regex: "(SUSE|Fedora|Red Hat|Puppy|PCLinuxOS|CentOS)/(\\d+)\\.(\\d+)\\.(\\d+)",
                other: !0
            }, {regex: "(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\\d+)\\.(\\d+)"}, {regex: "(Windows|OpenBSD|FreeBSD|NetBSD|Ubuntu|Kubuntu|Android|Arch Linux|CentOS|WeTab|Slackware)"}, {
                regex: "(Linux|BSD)",
                other: !0
            }],
            mobile_os_families: ["Windows Phone 6.5", "Windows CE", "Symbian OS"],
            device_parsers: [{
                regex: "HTC ([A-Z][a-z0-9]+) Build",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {
                regex: "HTC ([A-Z][a-z0-9 ]+) \\d+\\.\\d+\\.\\d+\\.\\d+",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {
                regex: "HTC_Touch_([A-Za-z0-9]+)",
                device_replacement: "HTC Touch ($1)",
                manufacturer: "HTC"
            }, {
                regex: "USCCHTC(\\d+)",
                device_replacement: "HTC $1 (US Cellular)",
                manufacturer: "HTC"
            }, {
                regex: "Sprint APA(9292)",
                device_replacement: "HTC $1 (Sprint)",
                manufacturer: "HTC"
            }, {
                regex: "HTC ([A-Za-z0-9]+ [A-Z])",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {
                regex: "HTC-([A-Za-z0-9]+)",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {
                regex: "HTC_([A-Za-z0-9]+)",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {
                regex: "HTC ([A-Za-z0-9]+)",
                device_replacement: "HTC $1",
                manufacturer: "HTC"
            }, {regex: "(ADR[A-Za-z0-9]+)", device_replacement: "HTC $1", manufacturer: "HTC"}, {
                regex: "(HTC)",
                manufacturer: "HTC"
            }, {
                regex: "SonyEricsson([A-Za-z0-9]+)/",
                device_replacement: "Ericsson $1",
                other: !0,
                manufacturer: "Sony"
            }, {regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; WOWMobile (.+) Build"}, {regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"}, {regex: "Android[\\- ][\\d]+\\.[\\d]+\\-update1\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"}, {regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"}, {regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; (.+) Build"}, {
                regex: "NokiaN([0-9]+)",
                device_replacement: "Nokia N$1",
                manufacturer: "Nokia"
            }, {
                regex: "Nokia([A-Za-z0-9\\v-]+)",
                device_replacement: "Nokia $1",
                manufacturer: "Nokia"
            }, {
                regex: "NOKIA ([A-Za-z0-9\\-]+)",
                device_replacement: "Nokia $1",
                manufacturer: "Nokia"
            }, {
                regex: "Nokia ([A-Za-z0-9\\-]+)",
                device_replacement: "Nokia $1",
                manufacturer: "Nokia"
            }, {
                regex: "Lumia ([A-Za-z0-9\\-]+)",
                device_replacement: "Lumia $1",
                manufacturer: "Nokia"
            }, {
                regex: "Symbian",
                device_replacement: "Nokia",
                manufacturer: "Nokia"
            }, {
                regex: "(PlayBook).+RIM Tablet OS",
                device_replacement: "Blackberry Playbook",
                tablet: !0,
                manufacturer: "RIM"
            }, {regex: "(Black[Bb]erry [0-9]+);", manufacturer: "RIM"}, {
                regex: "Black[Bb]erry([0-9]+)",
                device_replacement: "BlackBerry $1",
                manufacturer: "RIM"
            }, {
                regex: "(Pre)/(\\d+)\\.(\\d+)",
                device_replacement: "Palm Pre",
                manufacturer: "Palm"
            }, {
                regex: "(Pixi)/(\\d+)\\.(\\d+)",
                device_replacement: "Palm Pixi",
                manufacturer: "Palm"
            }, {
                regex: "(Touchpad)/(\\d+)\\.(\\d+)",
                device_replacement: "HP Touchpad",
                manufacturer: "HP"
            }, {
                regex: "HPiPAQ([A-Za-z0-9]+)/(\\d+).(\\d+)",
                device_replacement: "HP iPAQ $1",
                manufacturer: "HP"
            }, {
                regex: "Palm([A-Za-z0-9]+)",
                device_replacement: "Palm $1",
                manufacturer: "Palm"
            }, {
                regex: "Treo([A-Za-z0-9]+)",
                device_replacement: "Palm Treo $1",
                manufacturer: "Palm"
            }, {
                regex: "webOS.*(P160UNA)/(\\d+).(\\d+)",
                device_replacement: "HP Veer",
                manufacturer: "HP"
            }, {regex: "(Kindle Fire)", manufacturer: "Amazon"}, {
                regex: "(Kindle)",
                manufacturer: "Amazon"
            }, {
                regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?",
                device_replacement: "Kindle Fire",
                tablet: !0,
                manufacturer: "Amazon"
            }, {regex: "(iPad) Simulator;", manufacturer: "Apple"}, {
                regex: "(iPad);",
                manufacturer: "Apple"
            }, {regex: "(iPod);", manufacturer: "Apple"}, {
                regex: "(iPhone) Simulator;",
                manufacturer: "Apple"
            }, {regex: "(iPhone);", manufacturer: "Apple"}, {
                regex: "Nexus\\ ([A-Za-z0-9\\-]+)",
                device_replacement: "Nexus $1"
            }, {
                regex: "acer_([A-Za-z0-9]+)_",
                device_replacement: "Acer $1",
                manufacturer: "Acer"
            }, {
                regex: "acer_([A-Za-z0-9]+)_",
                device_replacement: "Acer $1",
                manufacturer: "Acer"
            }, {
                regex: "Amoi\\-([A-Za-z0-9]+)",
                device_replacement: "Amoi $1",
                other: !0,
                manufacturer: "Amoi"
            }, {
                regex: "AMOI\\-([A-Za-z0-9]+)",
                device_replacement: "Amoi $1",
                other: !0,
                manufacturer: "Amoi"
            }, {
                regex: "Asus\\-([A-Za-z0-9]+)",
                device_replacement: "Asus $1",
                manufacturer: "Asus"
            }, {
                regex: "ASUS\\-([A-Za-z0-9]+)",
                device_replacement: "Asus $1",
                manufacturer: "Asus"
            }, {
                regex: "BIRD\\-([A-Za-z0-9]+)",
                device_replacement: "Bird $1",
                other: !0
            }, {
                regex: "BIRD\\.([A-Za-z0-9]+)",
                device_replacement: "Bird $1",
                other: !0
            }, {regex: "BIRD ([A-Za-z0-9]+)", device_replacement: "Bird $1", other: !0}, {
                regex: "Dell ([A-Za-z0-9]+)",
                device_replacement: "Dell $1",
                manufacturer: "Dell"
            }, {
                regex: "DoCoMo/2\\.0 ([A-Za-z0-9]+)",
                device_replacement: "DoCoMo $1",
                other: !0
            }, {
                regex: "([A-Za-z0-9]+)\\_W\\;FOMA",
                device_replacement: "DoCoMo $1",
                other: !0
            }, {
                regex: "([A-Za-z0-9]+)\\;FOMA",
                device_replacement: "DoCoMo $1",
                other: !0
            }, {
                regex: "vodafone([A-Za-z0-9]+)",
                device_replacement: "Huawei Vodafone $1",
                other: !0
            }, {
                regex: "i\\-mate ([A-Za-z0-9]+)",
                device_replacement: "i-mate $1",
                other: !0
            }, {
                regex: "Kyocera\\-([A-Za-z0-9]+)",
                device_replacement: "Kyocera $1",
                other: !0
            }, {
                regex: "KWC\\-([A-Za-z0-9]+)",
                device_replacement: "Kyocera $1",
                other: !0
            }, {
                regex: "Lenovo\\-([A-Za-z0-9]+)",
                device_replacement: "Lenovo $1",
                manufacturer: "Lenovo"
            }, {
                regex: "Lenovo\\_([A-Za-z0-9]+)",
                device_replacement: "Lenovo $1",
                manufacturer: "Levovo"
            }, {
                regex: "LG/([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LG-LG([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LGE-LG([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LGE VX([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LG ([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LGE LG\\-AX([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LG\\-([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LGE\\-([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "LG([A-Za-z0-9]+)",
                device_replacement: "LG $1",
                manufacturer: "LG"
            }, {
                regex: "(KIN)\\.One (\\d+)\\.(\\d+)",
                device_replacement: "Microsoft $1"
            }, {
                regex: "(KIN)\\.Two (\\d+)\\.(\\d+)",
                device_replacement: "Microsoft $1"
            }, {regex: "(Motorola)\\-([A-Za-z0-9]+)", manufacturer: "Motorola"}, {
                regex: "MOTO\\-([A-Za-z0-9]+)",
                device_replacement: "Motorola $1",
                manufacturer: "Motorola"
            }, {
                regex: "MOT\\-([A-Za-z0-9]+)",
                device_replacement: "Motorola $1",
                manufacturer: "Motorola"
            }, {
                regex: "Philips([A-Za-z0-9]+)",
                device_replacement: "Philips $1",
                manufacturer: "Philips"
            }, {
                regex: "Philips ([A-Za-z0-9]+)",
                device_replacement: "Philips $1",
                manufacturer: "Philips"
            }, {
                regex: "SAMSUNG-([A-Za-z0-9\\-]+)",
                device_replacement: "Samsung $1",
                manufacturer: "Samsung"
            }, {
                regex: "SAMSUNG\\; ([A-Za-z0-9\\-]+)",
                device_replacement: "Samsung $1",
                manufacturer: "Samsung"
            }, {
                regex: "Softbank/1\\.0/([A-Za-z0-9]+)",
                device_replacement: "Softbank $1",
                other: !0
            }, {
                regex: "Softbank/2\\.0/([A-Za-z0-9]+)",
                device_replacement: "Softbank $1",
                other: !0
            }, {
                regex: "(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)",
                device_replacement: "Generic Smartphone"
            }, {
                regex: "^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\\-|airn|alav|asus|attw|au\\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\\-n|bw\\-u|beck|benq|bilb|blac|c55/|cdm\\-|chtm|capi|comp|cond|craw|dall|dbte|dc\\-s|dica|ds\\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\\-|fly\\_|g\\-mo|g1 u|g560|gf\\-5|grun|gene|go.w|good|grad|hcit|hd\\-m|hd\\-p|hd\\-t|hei\\-|hp i|hpip|hs\\-c|htc |htc\\-|htca|htcg)",
                device_replacement: "Generic Feature Phone"
            }, {
                regex: "^(htcp|htcs|htct|htc\\_|haie|hita|huaw|hutc|i\\-20|i\\-go|i\\-ma|i230|iac|iac\\-|iac/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt/|kpt |kwc\\-|klon|lexi|lg g|lg\\-a|lg\\-b|lg\\-c|lg\\-d|lg\\-f|lg\\-g|lg\\-k|lg\\-l|lg\\-m|lg\\-o|lg\\-p|lg\\-s|lg\\-t|lg\\-u|lg\\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\\-|lge/|lynx|leno|m1\\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\\-|nem\\-|newg|neon)",
                device_replacement: "Generic Feature Phone"
            }, {
                regex: "^(netf|noki|nzph|o2 x|o2\\-x|opwv|owg1|opti|oran|ot\\-s|p800|pand|pg\\-1|pg\\-2|pg\\-3|pg\\-6|pg\\-8|pg\\-c|pg13|phil|pn\\-2|pt\\-g|palm|pana|pire|pock|pose|psio|qa\\-a|qc\\-2|qc\\-3|qc\\-5|qc\\-7|qc07|qc12|qc21|qc32|qc60|qci\\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\\-|scp\\-|sdk/|se47|sec\\-|sec0|sec1|semc|sgh\\-|shar|sie\\-|sk\\-0|sl45|slid|smb3|smt5|sp01|sph\\-|spv |spv\\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\\-mo|t218|t250|t600|t610|t618|tcl\\-|tdg\\-|telm|tim\\-|ts70|tsm\\-|tsm3|tsm5|tx\\-9|tagt)",
                device_replacement: "Generic Feature Phone"
            }, {
                regex: "^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\\-|your|zte\\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\\-|webc|whit|wmlb|xda\\-|xda\\_)",
                device_replacement: "Generic Feature Phone"
            }, {
                regex: "(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\\-webcrawler|converacrawler|dataparksearch|findlinks)",
                device_replacement: "Spider"
            }],
            mobile_browser_families: ["Firefox Mobile", "Opera Mobile", "Opera Mini", "Mobile Safari", "webOS", "IE Mobile", "Playstation Portable", "Nokia", "Blackberry", "Palm", "Silk", "Android", "Maemo", "Obigo", "Netfront", "AvantGo", "Teleca", "SEMC-Browser", "Bolt", "Iris", "UP.Browser", "Symphony", "Minimo", "Bunjaloo", "Jasmine", "Dolfin", "Polaris", "BREW", "Chrome Mobile", "Chrome Mobile iOS", "UC Browser", "Tizen Browser"]
        };
        e.parsers = ["device_parsers", "browser_parsers", "os_parsers", "mobile_os_families", "mobile_browser_families"], e.types = ["browser", "os", "device"], e.regexes = r || function () {
            var r = {};
            return e.parsers.map(function (e) {
                r[e] = []
            }), r
        }(), e.families = function () {
            var r = {};
            return e.types.map(function (e) {
                r[e] = []
            }), r
        }();
        var a = Array.prototype, t = (Object.prototype, Function.prototype, a.forEach);
        a.indexOf;
        var n = function (e, r) {
            for (var a = {}, t = 0; r.length > t && !(a = r[t](e)); t++);
            return a
        }, o = function (e, r) {
            i(e, function (e) {
                i(r, function (r) {
                    delete e[r]
                })
            })
        }, i = forEach = function (e, r, a) {
            if (null != e)if (t && e.forEach === t)e.forEach(r, a); else if (e.length === +e.length)for (var n = 0, o = e.length; o > n; n++)r.call(a, e[n], n, e); else for (var i in e)_.has(e, i) && r.call(a, e[i], i, e)
        }, l = function (e) {
            return !(!e || void 0 === e || null == e)
        }, d = function (e) {
            var r = "";
            return e = e || {}, l(e) && l(e.major) && (r += e.major, l(e.minor) && (r += "." + e.minor, l(e.patch) && (r += "." + e.patch))), r
        }, c = function (e) {
            e = e || {};
            var r = d(e);
            return r && (r = " " + r), e && l(e.family) ? e.family + r : ""
        };
        return e.parse = function (r) {
            var a = function (r) {
                return e.regexes[r + "_parsers"].map(function (e) {
                    function a(r) {
                        var a = r.match(t);
                        if (!a)return null;
                        var i = {};
                        return i.family = (n ? n.replace("$1", a[1]) : a[1]) || "other", i.major = parseInt(o ? o : a[2]) || null, i.minor = a[3] ? parseInt(a[3]) : null, i.patch = a[4] ? parseInt(a[4]) : null, i.tablet = e.tablet, i.man = e.manufacturer || null, i
                    }

                    var t = RegExp(e.regex), n = e[("browser" === r ? "family" : r) + "_replacement"], o = e.major_version_replacement;
                    return a
                })
            }, t = function () {
            }, i = a("browser"), m = a("os"), s = a("device"), p = new t;
            p.source = r, p.browser = n(r, i), l(p.browser) ? (p.browser.name = c(p.browser), p.browser.version = d(p.browser)) : p.browser = {}, p.os = n(r, m), l(p.os) ? (p.os.name = c(p.os), p.os.version = d(p.os)) : p.os = {}, p.device = n(r, s), l(p.device) ? (p.device.name = c(p.device), p.device.version = d(p.device)) : p.device = {
                tablet: !1,
                family: "Other"
            };
            var u = {};
            return e.regexes.mobile_browser_families.map(function (e) {
                u[e] = !0
            }), e.regexes.mobile_os_families.map(function (e) {
                u[e] = !0
            }), p.device.type = "Spider" === p.browser.family ? "Spider" : p.browser.tablet || p.os.tablet || p.device.tablet ? "Tablet" : u.hasOwnProperty(p.browser.family) ? "Mobile" : "Desktop", p.device.manufacturer = p.browser.man || p.os.man || p.device.man || null, o([p.browser, p.os, p.device], ["tablet", "man"]), p
        }, e
    }();
    "undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (exports = module.exports = r), exports.detect = r) : e.detect = r, "function" == typeof define && define.amd && define(function () {
        return r
    })
}(window), function () {
    function e(e) {
        return !!e.exifdata
    }

    function r(e, r) {
        r = r || e.match(/^data\:([^\;]+)\;base64,/im)[1] || "", e = e.replace(/^data\:([^\;]+)\;base64,/gim, "");
        for (var a = atob(e), t = a.length, n = new ArrayBuffer(t), o = new Uint8Array(n), i = 0; t > i; i++)o[i] = a.charCodeAt(i);
        return n
    }

    function a(e, r) {
        var a = new XMLHttpRequest;
        a.open("GET", e, !0), a.responseType = "blob", a.onload = function (e) {
            (200 == this.status || 0 === this.status) && r(this.response)
        }, a.send()
    }

    function t(e, t) {
        function n(r) {
            var a = o(r), n = i(r);
            e.exifdata = a || {}, e.iptcdata = n || {}, t && t.call(e)
        }

        if (e.src)if (/^data\:/i.test(e.src)) {
            var l = r(e.src);
            n(l)
        } else if (/^blob\:/i.test(e.src)) {
            var d = new FileReader;
            d.onload = function (e) {
                n(e.target.result)
            }, a(e.src, function (e) {
                d.readAsArrayBuffer(e)
            })
        } else {
            var c = new XMLHttpRequest;
            c.onload = function () {
                if (200 != this.status && 0 !== this.status)throw"Could not load image";
                n(c.response), c = null
            }, c.open("GET", e.src, !0), c.responseType = "arraybuffer", c.send(null)
        } else if (window.FileReader && (e instanceof window.Blob || e instanceof window.File)) {
            var d = new FileReader;
            d.onload = function (e) {
                p && console.log("Got file of length " + e.target.result.byteLength), n(e.target.result)
            }, d.readAsArrayBuffer(e)
        }
    }

    function o(e) {
        var r = new DataView(e);
        if (p && console.log("Got file of length " + e.byteLength), 255 != r.getUint8(0) || 216 != r.getUint8(1))return p && console.log("Not a valid JPEG"), !1;
        for (var a, t = 2, n = e.byteLength; n > t;) {
            if (255 != r.getUint8(t))return p && console.log("Not a valid marker at offset " + t + ", found: " + r.getUint8(t)), !1;
            if (a = r.getUint8(t + 1), p && console.log(a), 225 == a)return p && console.log("Found 0xFFE1 marker"), s(r, t + 4, r.getUint16(t + 2) - 2);
            t += 2 + r.getUint16(t + 2)
        }
    }

    function i(e) {
        var r = new DataView(e);
        if (p && console.log("Got file of length " + e.byteLength), 255 != r.getUint8(0) || 216 != r.getUint8(1))return p && console.log("Not a valid JPEG"), !1;
        for (var a = 2, t = e.byteLength, n = function (e, r) {
            return 56 === e.getUint8(r) && 66 === e.getUint8(r + 1) && 73 === e.getUint8(r + 2) && 77 === e.getUint8(r + 3) && 4 === e.getUint8(r + 4) && 4 === e.getUint8(r + 5)
        }; t > a;) {
            if (n(r, a)) {
                var o = r.getUint8(a + 7);
                o % 2 !== 0 && (o += 1), 0 === o && (o = 4);
                var i = a + 8 + o, d = r.getUint16(a + 6 + o);
                return l(e, i, d)
            }
            a++
        }
    }

    function l(e, r, a) {
        for (var t, n, o, i, l, d = new DataView(e), c = {}, s = r; r + a > s;)28 === d.getUint8(s) && 2 === d.getUint8(s + 1) && (i = d.getUint8(s + 2), i in y && (o = d.getInt16(s + 3), l = o + 5, n = y[i], t = m(d, s + 5, o), c.hasOwnProperty(n) ? c[n]instanceof Array ? c[n].push(t) : c[n] = [c[n], t] : c[n] = t)), s++;
        return c
    }

    function d(e, r, a, t, n) {
        var o, i, l, d = e.getUint16(a, !n), m = {};
        for (l = 0; d > l; l++)o = a + 12 * l + 2, i = t[e.getUint16(o, !n)], !i && p && console.log("Unknown tag: " + e.getUint16(o, !n)), m[i] = c(e, o, r, a, n);
        return m
    }

    function c(e, r, a, t, n) {
        var o, i, l, d, c, s, p = e.getUint16(r + 2, !n), u = e.getUint32(r + 4, !n), g = e.getUint32(r + 8, !n) + a;
        switch (p) {
            case 1:
            case 7:
                if (1 == u)return e.getUint8(r + 8, !n);
                for (o = u > 4 ? g : r + 8, i = [], d = 0; u > d; d++)i[d] = e.getUint8(o + d);
                return i;
            case 2:
                return o = u > 4 ? g : r + 8, m(e, o, u - 1);
            case 3:
                if (1 == u)return e.getUint16(r + 8, !n);
                for (o = u > 2 ? g : r + 8, i = [], d = 0; u > d; d++)i[d] = e.getUint16(o + 2 * d, !n);
                return i;
            case 4:
                if (1 == u)return e.getUint32(r + 8, !n);
                for (i = [], d = 0; u > d; d++)i[d] = e.getUint32(g + 4 * d, !n);
                return i;
            case 5:
                if (1 == u)return c = e.getUint32(g, !n), s = e.getUint32(g + 4, !n), l = new Number(c / s), l.numerator = c, l.denominator = s, l;
                for (i = [], d = 0; u > d; d++)c = e.getUint32(g + 8 * d, !n), s = e.getUint32(g + 4 + 8 * d, !n), i[d] = new Number(c / s), i[d].numerator = c, i[d].denominator = s;
                return i;
            case 9:
                if (1 == u)return e.getInt32(r + 8, !n);
                for (i = [], d = 0; u > d; d++)i[d] = e.getInt32(g + 4 * d, !n);
                return i;
            case 10:
                if (1 == u)return e.getInt32(g, !n) / e.getInt32(g + 4, !n);
                for (i = [], d = 0; u > d; d++)i[d] = e.getInt32(g + 8 * d, !n) / e.getInt32(g + 4 + 8 * d, !n);
                return i
        }
    }

    function m(e, r, a) {
        var t = "";
        for (n = r; n < r + a; n++)t += String.fromCharCode(e.getUint8(n));
        return t
    }

    function s(e, r) {
        if ("Exif" != m(e, r, 4))return p && console.log("Not valid EXIF data! " + m(e, r, 4)), !1;
        var a, t, n, o, i, l = r + 6;
        if (18761 == e.getUint16(l))a = !1; else {
            if (19789 != e.getUint16(l))return p && console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)"), !1;
            a = !0
        }
        if (42 != e.getUint16(l + 2, !a))return p && console.log("Not valid TIFF data! (no 0x002A)"), !1;
        var c = e.getUint32(l + 4, !a);
        if (8 > c)return p && console.log("Not valid TIFF data! (First offset less than 8)", e.getUint32(l + 4, !a)), !1;
        if (t = d(e, l, l + c, x, a), t.ExifIFDPointer) {
            o = d(e, l, l + t.ExifIFDPointer, f, a);
            for (n in o) {
                switch (n) {
                    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":
                        o[n] = b[n][o[n]];
                        break;
                    case"ExifVersion":
                    case"FlashpixVersion":
                        o[n] = String.fromCharCode(o[n][0], o[n][1], o[n][2], o[n][3]);
                        break;
                    case"ComponentsConfiguration":
                        o[n] = b.Components[o[n][0]] + b.Components[o[n][1]] + b.Components[o[n][2]] + b.Components[o[n][3]]
                }
                t[n] = o[n]
            }
        }
        if (t.GPSInfoIFDPointer) {
            i = d(e, l, l + t.GPSInfoIFDPointer, h, a);
            for (n in i) {
                switch (n) {
                    case"GPSVersionID":
                        i[n] = i[n][0] + "." + i[n][1] + "." + i[n][2] + "." + i[n][3]
                }
                t[n] = i[n]
            }
        }
        return t
    }

    var p = !1, u = this, g = function (e) {
        return e instanceof g ? e : this instanceof g ? void(this.EXIFwrapped = e) : new g(e)
    };
    "undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (exports = module.exports = g), exports.EXIF = g) : u.EXIF = g;
    var f = g.Tags = {
        36864: "ExifVersion",
        40960: "FlashpixVersion",
        40961: "ColorSpace",
        40962: "PixelXDimension",
        40963: "PixelYDimension",
        37121: "ComponentsConfiguration",
        37122: "CompressedBitsPerPixel",
        37500: "MakerNote",
        37510: "UserComment",
        40964: "RelatedSoundFile",
        36867: "DateTimeOriginal",
        36868: "DateTimeDigitized",
        37520: "SubsecTime",
        37521: "SubsecTimeOriginal",
        37522: "SubsecTimeDigitized",
        33434: "ExposureTime",
        33437: "FNumber",
        34850: "ExposureProgram",
        34852: "SpectralSensitivity",
        34855: "ISOSpeedRatings",
        34856: "OECF",
        37377: "ShutterSpeedValue",
        37378: "ApertureValue",
        37379: "BrightnessValue",
        37380: "ExposureBias",
        37381: "MaxApertureValue",
        37382: "SubjectDistance",
        37383: "MeteringMode",
        37384: "LightSource",
        37385: "Flash",
        37396: "SubjectArea",
        37386: "FocalLength",
        41483: "FlashEnergy",
        41484: "SpatialFrequencyResponse",
        41486: "FocalPlaneXResolution",
        41487: "FocalPlaneYResolution",
        41488: "FocalPlaneResolutionUnit",
        41492: "SubjectLocation",
        41493: "ExposureIndex",
        41495: "SensingMethod",
        41728: "FileSource",
        41729: "SceneType",
        41730: "CFAPattern",
        41985: "CustomRendered",
        41986: "ExposureMode",
        41987: "WhiteBalance",
        41988: "DigitalZoomRation",
        41989: "FocalLengthIn35mmFilm",
        41990: "SceneCaptureType",
        41991: "GainControl",
        41992: "Contrast",
        41993: "Saturation",
        41994: "Sharpness",
        41995: "DeviceSettingDescription",
        41996: "SubjectDistanceRange",
        40965: "InteroperabilityIFDPointer",
        42016: "ImageUniqueID"
    }, x = g.TiffTags = {
        256: "ImageWidth",
        257: "ImageHeight",
        34665: "ExifIFDPointer",
        34853: "GPSInfoIFDPointer",
        40965: "InteroperabilityIFDPointer",
        258: "BitsPerSample",
        259: "Compression",
        262: "PhotometricInterpretation",
        274: "Orientation",
        277: "SamplesPerPixel",
        284: "PlanarConfiguration",
        530: "YCbCrSubSampling",
        531: "YCbCrPositioning",
        282: "XResolution",
        283: "YResolution",
        296: "ResolutionUnit",
        273: "StripOffsets",
        278: "RowsPerStrip",
        279: "StripByteCounts",
        513: "JPEGInterchangeFormat",
        514: "JPEGInterchangeFormatLength",
        301: "TransferFunction",
        318: "WhitePoint",
        319: "PrimaryChromaticities",
        529: "YCbCrCoefficients",
        532: "ReferenceBlackWhite",
        306: "DateTime",
        270: "ImageDescription",
        271: "Make",
        272: "Model",
        305: "Software",
        315: "Artist",
        33432: "Copyright"
    }, h = g.GPSTags = {
        0: "GPSVersionID",
        1: "GPSLatitudeRef",
        2: "GPSLatitude",
        3: "GPSLongitudeRef",
        4: "GPSLongitude",
        5: "GPSAltitudeRef",
        6: "GPSAltitude",
        7: "GPSTimeStamp",
        8: "GPSSatellites",
        9: "GPSStatus",
        10: "GPSMeasureMode",
        11: "GPSDOP",
        12: "GPSSpeedRef",
        13: "GPSSpeed",
        14: "GPSTrackRef",
        15: "GPSTrack",
        16: "GPSImgDirectionRef",
        17: "GPSImgDirection",
        18: "GPSMapDatum",
        19: "GPSDestLatitudeRef",
        20: "GPSDestLatitude",
        21: "GPSDestLongitudeRef",
        22: "GPSDestLongitude",
        23: "GPSDestBearingRef",
        24: "GPSDestBearing",
        25: "GPSDestDistanceRef",
        26: "GPSDestDistance",
        27: "GPSProcessingMethod",
        28: "GPSAreaInformation",
        29: "GPSDateStamp",
        30: "GPSDifferential"
    }, b = g.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: {
            0: "Flash did not fire",
            1: "Flash fired",
            5: "Strobe return light not detected",
            7: "Strobe return light detected",
            9: "Flash fired, compulsory flash mode",
            13: "Flash fired, compulsory flash mode, return light not detected",
            15: "Flash fired, compulsory flash mode, return light detected",
            16: "Flash did not fire, compulsory flash mode",
            24: "Flash did not fire, auto mode",
            25: "Flash fired, auto mode",
            29: "Flash fired, auto mode, return light not detected",
            31: "Flash fired, auto mode, return light detected",
            32: "No flash function",
            65: "Flash fired, red-eye reduction mode",
            69: "Flash fired, red-eye reduction mode, return light not detected",
            71: "Flash fired, red-eye reduction mode, return light detected",
            73: "Flash fired, compulsory flash mode, red-eye reduction mode",
            77: "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
            79: "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
            89: "Flash fired, auto mode, red-eye reduction mode",
            93: "Flash fired, auto mode, return light not detected, red-eye reduction mode",
            95: "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"}
    }, y = {
        120: "caption",
        110: "credit",
        25: "keywords",
        55: "dateCreated",
        80: "byline",
        85: "bylineTitle",
        122: "captionWriter",
        105: "headline",
        116: "copyright",
        15: "category"
    };
    g.getData = function (r, a) {
        return (r instanceof Image || r instanceof HTMLImageElement) && !r.complete ? !1 : (e(r) ? a && a.call(r) : t(r, a), !0)
    }, g.getTag = function (r, a) {
        return e(r) ? r.exifdata[a] : void 0
    }, g.getAllTags = function (r) {
        if (!e(r))return {};
        var a, t = r.exifdata, n = {};
        for (a in t)t.hasOwnProperty(a) && (n[a] = t[a]);
        return n
    }, g.pretty = function (r) {
        if (!e(r))return "";
        var a, t = r.exifdata, n = "";
        for (a in t)t.hasOwnProperty(a) && (n += "object" == typeof t[a] ? t[a]instanceof Number ? a + " : " + t[a] + " [" + t[a].numerator + "/" + t[a].denominator + "]\r\n" : a + " : [" + t[a].length + " values]\r\n" : a + " : " + t[a] + "\r\n");
        return n
    }, g.readFromBinaryFile = function (e) {
        return o(e)
    }, "function" == typeof define && define.amd && define("exif-js", [], function () {
        return g
    })
}.call(this);
function JPEGEncoder(r) {
    function a(r) {
        for (var a = [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], e = 0; 64 > e; e++) {
            var t = U((a[e] * r + 50) / 100);
            1 > t ? t = 1 : t > 255 && (t = 255), k[q[e]] = t
        }
        for (var n = [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], o = 0; 64 > o; o++) {
            var i = U((n[o] * r + 50) / 100);
            1 > i ? i = 1 : i > 255 && (i = 255), p[q[o]] = i
        }
        for (var c = [1, 1.387039845, 1.306562965, 1.175875602, 1, .785694958, .5411961, .275899379], f = 0, s = 0; 8 > s; s++)for (var v = 0; 8 > v; v++)M[f] = 1 / (k[q[f]] * c[s] * c[v] * 8), j[f] = 1 / (p[q[f]] * c[s] * c[v] * 8), f++
    }

    function e(r, a) {
        for (var e = 0, t = 0, n = new Array, o = 1; 16 >= o; o++) {
            for (var i = 1; i <= r[o]; i++)n[a[t]] = [], n[a[t]][0] = e, n[a[t]][1] = o, t++, e++;
            e *= 2
        }
        return n
    }

    function t() {
        y = e(z, G), L = e(S, F), I = e(J, Q), A = e(K, V)
    }

    function n() {
        for (var r = 1, a = 2, e = 1; 15 >= e; e++) {
            for (var t = r; a > t; t++)C[32767 + t] = e, E[32767 + t] = [], E[32767 + t][1] = e, E[32767 + t][0] = t;
            for (var n = -(a - 1); -r >= n; n++)C[32767 + n] = e, E[32767 + n] = [], E[32767 + n][1] = e, E[32767 + n][0] = a - 1 + n;
            r <<= 1, a <<= 1
        }
    }

    function o() {
        for (var r = 0; 256 > r; r++)_[r] = 19595 * r, _[r + 256 >> 0] = 38470 * r, _[r + 512 >> 0] = 7471 * r + 32768, _[r + 768 >> 0] = -11059 * r, _[r + 1024 >> 0] = -21709 * r, _[r + 1280 >> 0] = 32768 * r + 8421375, _[r + 1536 >> 0] = -27439 * r, _[r + 1792 >> 0] = -5329 * r
    }

    function i(r) {
        for (var a = r[0], e = r[1] - 1; e >= 0;)a & 1 << e && (H |= 1 << O), e--, O--, 0 > O && (255 == H ? (c(255), c(0)) : c(H), O = 7, H = 0)
    }

    function c(r) {
        P.push(B[r])
    }

    function f(r) {
        c(r >> 8 & 255), c(255 & r)
    }

    function s(r, a) {
        var e, t, n, o, i, c, f, s, v, h = 0;
        const u = 8, d = 64;
        for (v = 0; u > v; ++v) {
            e = r[h], t = r[h + 1], n = r[h + 2], o = r[h + 3], i = r[h + 4], c = r[h + 5], f = r[h + 6], s = r[h + 7];
            var g = e + s, l = e - s, w = t + f, m = t - f, b = n + c, y = n - c, L = o + i, I = o - i, A = g + L, R = g - L, U = w + b, k = w - b;
            r[h] = A + U, r[h + 4] = A - U;
            var p = .707106781 * (k + R);
            r[h + 2] = R + p, r[h + 6] = R - p, A = I + y, U = y + m, k = m + l;
            var M = .382683433 * (A - k), j = .5411961 * A + M, E = 1.306562965 * k + M, C = .707106781 * U, x = l + C, P = l - C;
            r[h + 5] = P + j, r[h + 3] = P - j, r[h + 1] = x + E, r[h + 7] = x - E, h += 8
        }
        for (h = 0, v = 0; u > v; ++v) {
            e = r[h], t = r[h + 8], n = r[h + 16], o = r[h + 24], i = r[h + 32], c = r[h + 40], f = r[h + 48], s = r[h + 56];
            var H = e + s, O = e - s, T = t + f, W = t - f, N = n + c, B = n - c, _ = o + i, q = o - i, z = H + _, G = H - _, J = T + N, Q = T - N;
            r[h] = z + J, r[h + 32] = z - J;
            var S = .707106781 * (Q + G);
            r[h + 16] = G + S, r[h + 48] = G - S, z = q + B, J = B + W, Q = W + O;
            var F = .382683433 * (z - Q), K = .5411961 * z + F, V = 1.306562965 * Q + F, X = .707106781 * J, Y = O + X, Z = O - X;
            r[h + 40] = Z + K, r[h + 24] = Z - K, r[h + 8] = Y + V, r[h + 56] = Y - V, h++
        }
        var $;
        for (v = 0; d > v; ++v)$ = r[v] * a[v], D[v] = $ > 0 ? $ + .5 | 0 : $ - .5 | 0;
        return D
    }

    function v() {
        f(65504), f(16), c(74), c(70), c(73), c(70), c(0), c(1), c(1), c(0), f(1), f(1), c(0), c(0)
    }

    function h(r, a) {
        f(65472), f(17), c(8), f(a), f(r), c(3), c(1), c(17), c(0), c(2), c(17), c(1), c(3), c(17), c(1)
    }

    function u() {
        f(65499), f(132), c(0);
        for (var r = 0; 64 > r; r++)c(k[r]);
        c(1);
        for (var a = 0; 64 > a; a++)c(p[a])
    }

    function d() {
        f(65476), f(418), c(0);
        for (var r = 0; 16 > r; r++)c(z[r + 1]);
        for (var a = 0; 11 >= a; a++)c(G[a]);
        c(16);
        for (var e = 0; 16 > e; e++)c(J[e + 1]);
        for (var t = 0; 161 >= t; t++)c(Q[t]);
        c(1);
        for (var n = 0; 16 > n; n++)c(S[n + 1]);
        for (var o = 0; 11 >= o; o++)c(F[o]);
        c(17);
        for (var i = 0; 16 > i; i++)c(K[i + 1]);
        for (var s = 0; 161 >= s; s++)c(V[s])
    }

    function g() {
        f(65498), f(12), c(3), c(1), c(0), c(2), c(17), c(3), c(17), c(0), c(63), c(0)
    }

    function l(r, a, e, t, n) {
        var o, c = n[0], f = n[240];
        const v = 16, h = 63, u = 64;
        for (var d = s(r, a), g = 0; u > g; ++g)x[q[g]] = d[g];
        var l = x[0] - e;
        e = x[0], 0 == l ? i(t[0]) : (o = 32767 + l, i(t[C[o]]), i(E[o]));
        for (var w = 63; w > 0 && 0 == x[w]; w--);
        if (0 == w)return i(c), e;
        for (var m, b = 1; w >= b;) {
            for (var y = b; 0 == x[b] && w >= b; ++b);
            var L = b - y;
            if (L >= v) {
                m = L >> 4;
                for (var I = 1; m >= I; ++I)i(f);
                L = 15 & L
            }
            o = 32767 + x[b], i(n[(L << 4) + C[o]]), i(E[o]), b++
        }
        return w != h && i(c), e
    }

    function w() {
        for (var r = String.fromCharCode, a = 0; 256 > a; a++)B[a] = r(a)
    }

    function m(r) {
        if (0 >= r && (r = 1), r > 100 && (r = 100), R != r) {
            var e = 0;
            e = Math.floor(50 > r ? 5e3 / r : 200 - 2 * r), a(e), R = r, console.log("Quality set to: " + r + "%")
        }
    }

    function b() {
        var a = (new Date).getTime();
        r || (r = 50), w(), t(), n(), o(), m(r);
        var e = (new Date).getTime() - a;
        console.log("Initialization " + e + "ms")
    }

    var y, L, I, A, R, U = (Math.round, Math.floor), k = new Array(64), p = new Array(64), M = new Array(64), j = new Array(64), E = new Array(65535), C = new Array(65535), D = new Array(64), x = new Array(64), P = [], H = 0, O = 7, T = new Array(64), W = new Array(64), N = new Array(64), B = new Array(256), _ = new Array(2048), q = [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], z = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], G = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], J = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125], Q = [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], S = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], F = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], K = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119], V = [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];
    this.encode = function (r, a, e) {
        var t = (new Date).getTime();
        a && m(a), P = new Array, H = 0, O = 7, f(65496), v(), u(), h(r.width, r.height), d(), g();
        var n = 0, o = 0, c = 0;
        H = 0, O = 7, this.encode.displayName = "_encode_";
        for (var s, w, b, R, U, k, p, E, C, D = r.data, x = r.width, B = r.height, q = 4 * x, z = 0; B > z;) {
            for (s = 0; q > s;) {
                for (U = q * z + s, k = U, p = -1, E = 0, C = 0; 64 > C; C++)E = C >> 3, p = 4 * (7 & C), k = U + E * q + p, z + E >= B && (k -= q * (z + 1 + E - B)), s + p >= q && (k -= s + p - q + 4), w = D[k++], b = D[k++], R = D[k++], T[C] = (_[w] + _[b + 256 >> 0] + _[R + 512 >> 0] >> 16) - 128, W[C] = (_[w + 768 >> 0] + _[b + 1024 >> 0] + _[R + 1280 >> 0] >> 16) - 128, N[C] = (_[w + 1280 >> 0] + _[b + 1536 >> 0] + _[R + 1792 >> 0] >> 16) - 128;
                n = l(T, M, n, y, I), o = l(W, j, o, L, A), c = l(N, j, c, L, A), s += 32
            }
            z += 8
        }
        if (O >= 0) {
            var G = [];
            G[1] = O + 1, G[0] = (1 << O + 1) - 1, i(G)
        }
        if (f(65497), e) {
            for (var J = P.length, Q = new Uint8Array(J), S = 0; J > S; S++)Q[S] = P[S].charCodeAt();
            P = [];
            var F = (new Date).getTime() - t;
            return console.log("Encoding time: " + F + "ms"), Q
        }
        var K = "data:image/jpeg;base64," + btoa(P.join(""));
        P = [];
        var F = (new Date).getTime() - t;
        return console.log("Encoding time: " + F + "ms"), K
    }, b()
}
!function () {
    function r(r) {
        var a = r.naturalWidth, e = r.naturalHeight;
        if (a * e > 1048576) {
            var t = document.createElement("canvas");
            t.width = t.height = 1;
            var n = t.getContext("2d");
            return n.drawImage(r, -a + 1, 0), 0 === n.getImageData(0, 0, 1, 1).data[3]
        }
        return !1
    }

    function a(r, a, e) {
        var t = document.createElement("canvas");
        t.width = 1, t.height = e;
        var n = t.getContext("2d");
        n.drawImage(r, 0, 0);
        for (var o = n.getImageData(0, 0, 1, e).data, i = 0, c = e, f = e; f > i;) {
            var s = o[4 * (f - 1) + 3];
            0 === s ? c = f : i = f, f = c + i >> 1
        }
        var v = f / e;
        return 0 === v ? 1 : v
    }

    function e(r, a, e) {
        var n = document.createElement("canvas");
        return t(r, n, a, e), n.toDataURL("image/jpeg", a.quality || .8)
    }

    function t(e, t, o, i) {
        var c = e.naturalWidth, f = e.naturalHeight;
        if (c + f) {
            var s = o.width, v = o.height, h = t.getContext("2d");
            h.save(), n(t, h, s, v, o.orientation);
            var u = r(e);
            u && (c /= 2, f /= 2);
            var d = 1024, g = document.createElement("canvas");
            g.width = g.height = d;
            for (var l = g.getContext("2d"), w = i ? a(e, c, f) : 1, m = Math.ceil(d * s / c), b = Math.ceil(d * v / f / w), y = 0, L = 0; f > y;) {
                for (var I = 0, A = 0; c > I;)l.clearRect(0, 0, d, d), l.drawImage(e, -I, -y), h.drawImage(g, 0, 0, d, d, A, L, m, b), I += d, A += m;
                y += d, L += b
            }
            h.restore(), g = l = null
        }
    }

    function n(r, a, e, t, n) {
        switch (n) {
            case 5:
            case 6:
            case 7:
            case 8:
                r.width = t, r.height = e;
                break;
            default:
                r.width = e, r.height = t
        }
        switch (n) {
            case 2:
                a.translate(e, 0), a.scale(-1, 1);
                break;
            case 3:
                a.translate(e, t), a.rotate(Math.PI);
                break;
            case 4:
                a.translate(0, t), a.scale(1, -1);
                break;
            case 5:
                a.rotate(.5 * Math.PI), a.scale(1, -1);
                break;
            case 6:
                a.rotate(.5 * Math.PI), a.translate(0, -t);
                break;
            case 7:
                a.rotate(.5 * Math.PI), a.translate(e, -t), a.scale(-1, 1);
                break;
            case 8:
                a.rotate(-.5 * Math.PI), a.translate(-e, 0)
        }
    }

    function o(r) {
        if (window.Blob && r instanceof Blob) {
            if (!i)throw Error("No createObjectURL function found to create blob url");
            var a = new Image;
            a.src = i.createObjectURL(r), this.blob = r, r = a
        }
        if (!r.naturalWidth && !r.naturalHeight) {
            var e = this;
            r.onload = r.onerror = function () {
                var r = e.imageLoadListeners;
                if (r) {
                    e.imageLoadListeners = null;
                    for (var a = 0, t = r.length; t > a; a++)r[a]()
                }
            }, this.imageLoadListeners = []
        }
        this.srcImage = r
    }

    var i = window.URL && window.URL.createObjectURL ? window.URL : window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null;
    o.prototype.render = function (r, a, n) {
        if (this.imageLoadListeners) {
            var o = this;
            return void this.imageLoadListeners.push(function () {
                o.render(r, a, n)
            })
        }
        a = a || {};
        var c = this.srcImage.naturalWidth, f = this.srcImage.naturalHeight, s = a.width, v = a.height, h = a.maxWidth, u = a.maxHeight, d = !this.blob || "image/jpeg" === this.blob.type;
        s && !v ? v = f * s / c << 0 : v && !s ? s = c * v / f << 0 : (s = c, v = f), h && s > h && (s = h, v = f * s / c << 0), u && v > u && (v = u, s = c * v / f << 0);
        var g = {width: s, height: v};
        for (var l in a)g[l] = a[l];
        var w = r.tagName.toLowerCase();
        "img" === w ? r.src = e(this.srcImage, g, d) : "canvas" === w && t(this.srcImage, r, g, d), "function" == typeof this.onrender && this.onrender(r), n && n(), this.blob && (this.blob = null, i.revokeObjectURL(this.srcImage.src))
    }, "function" == typeof define && define.amd ? define([], function () {
        return o
    }) : this.MegaPixImage = o
}();
!function () {
    function e(e, t) {
        this.file = e, this.defaults = {quality: .7, done: null, fail: null, before: null, always: null};
        for (var a in t)this.defaults[a] = t[a];
        this.defaults.quality > 1 && (this.defaults.quality = 1), this.results = {
            origin: null,
            base64: null,
            base64Len: null
        }, this.init()
    }

    window.URL = window.URL || window.webkitURL;
    var t = detect.parse(navigator.userAgent);
    e.prototype = {
        constructor: e, init: function () {
            var e = this;
            if ("undefined" == typeof window.URL || "function" != typeof document.createElement("canvas").getContext) {
                var t = new Error("不支持此设备");
                return "function" == typeof e.defaults.fail && e.defaults.fail(t), void("function" == typeof e.defaults.always && e.defaults.always())
            }
            e.create(e.file)
        }, create: function (e) {
            var a = this, i = new Image, n = a.results, s = "string" == typeof e ? e : URL.createObjectURL(e);
            i.crossOrigin = "*", i.onerror = function () {
                var e = new Error("图片加载失败");
                "function" == typeof a.defaults.fail && a.defaults.fail(e), "function" == typeof a.defaults.always && a.defaults.always()
            }, i.onload = function () {
                function l(e) {
                    canvas = null, i = null, URL.revokeObjectURL(s), e.base64Len = e.base64.length, "function" == typeof a.defaults.done && a.defaults.done(e), "function" == typeof a.defaults.always && a.defaults.always()
                }

                EXIF.getData(i, function () {
                    var s, r = EXIF.getTag(this, "Orientation"), o = a.resize(this, r), h = document.createElement("canvas");
                    if (h.width = o.w, h.height = o.h, s = h.getContext("2d"), s.fillStyle = "#fff", s.fillRect(0, 0, o.w, o.h), n.origin = e, "iOS" === t.os.family && parseInt(t.os.version) < 8) {
                        var f = new MegaPixImage(i);
                        "5678".indexOf(r) > -1 ? f.render(h, {
                            width: h.height,
                            height: h.width,
                            orientation: r
                        }) : f.render(h, {
                            width: h.width,
                            height: h.height,
                            orientation: r
                        }), n.base64 = h.toDataURL("image/jpeg", a.defaults.quality), l(n)
                    } else {
                        switch (r) {
                            case 3:
                                s.rotate(180 * Math.PI / 180), s.drawImage(i, -o.w, -o.h, o.w, o.h);
                                break;
                            case 6:
                                s.rotate(90 * Math.PI / 180), s.drawImage(i, 0, -o.w, o.h, o.w);
                                break;
                            case 8:
                                s.rotate(270 * Math.PI / 180), s.drawImage(i, -o.h, 0, o.h, o.w);
                                break;
                            case 2:
                                s.translate(o.w, 0), s.scale(-1, 1), s.drawImage(i, 0, 0, o.w, o.h);
                                break;
                            case 4:
                                s.translate(o.w, 0), s.scale(-1, 1), s.rotate(180 * Math.PI / 180), s.drawImage(i, -o.w, -o.h, o.w, o.h);
                                break;
                            case 5:
                                s.translate(o.w, 0), s.scale(-1, 1), s.rotate(90 * Math.PI / 180), s.drawImage(i, 0, -o.w, o.h, o.w);
                                break;
                            case 7:
                                s.translate(o.w, 0), s.scale(-1, 1), s.rotate(270 * Math.PI / 180), s.drawImage(i, -o.h, 0, o.h, o.w);
                                break;
                            default:
                                s.drawImage(i, 0, 0, o.w, o.h)
                        }
                        if ("Android" === t.os.family && t.os.version.slice(0, 3) < 4.5) {
                            var w = new JPEGEncoder;
                            n.base64 = w.encode(s.getImageData(0, 0, h.width, h.height), 100 * a.defaults.quality)
                        } else n.base64 = h.toDataURL("image/jpeg", a.defaults.quality);
                        l(n)
                    }
                })
            }, "function" == typeof this.defaults.before && this.defaults.before(), i.src = s
        }, resize: function (e, t) {
            var a = this.defaults.width, i = this.defaults.height, n = {w: e.width, h: e.height};
            "5678".indexOf(t) > -1 && (n.w = e.height, n.h = e.width);
            var s = n.w / n.h;
            return a && i ? s >= a / i ? n.w > a && (n.w = a, n.h = Math.ceil(a / s)) : n.h > i && (n.h = i, n.w = Math.ceil(i * s)) : a ? (n.w = a, n.h = Math.ceil(a / s)) : i && (n.w = Math.ceil(i * s), n.h = i), (n.w >= 3264 || n.h >= 2448) && (n.w *= .8, n.h *= .8), n
        }
    }, window.lrz = function (t, a) {
        return new e(t, a)
    }
}();

注:当上传的图片被分割时,手机游览器设置一下即可,换成手机版或者电脑版。

其中一些上传到某个地点,云或本地的,我使用的是OpenSNS的一些他们有的的内部函数,有不懂的,可以下个OpenSNS或者留言给我,我可以把所有代码发出来或者详解下。

相关文章推荐

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

使用lrz压缩上传图片,后台使用java

pageEncoding="GBK"%> -->                                   document...

使用HTML5 canvas 标签进行图片裁剪、旋转、缩放

代码使用到的js插件:jquery、bootstrap、lrz。 jquery就不说了,基本都知道。bootstrap是一个响应式的前端ui框架。使用它是为了在手机端查看页面时能够自适应宽高。lrz...
  • hzw2312
  • hzw2312
  • 2015年08月17日 15:12
  • 16861

H5技术完美实现调用手机摄像头、相册。图片上传base64,图片压缩、预览、删除以及图片旋转90度的处理--demo。

看了帖子上有很多关于H5调用手机摄像头、相册的例子,也有很多可靠的栗子,综合技术点针对HTML5调用用手机相机、相册的的一次代码整合。实现提供完成的Demo提供给大家,可直接应用于项目中需要图片上传的...

HTML5 MUI 手机预览图片,裁剪上传base64,保存数据库

需要的文件: 这些晚间都需要, 页面头部引用: 页面底部引用(但是在body里): 布局: //触发选择图片事件 //默认图片以及选择裁剪后展示的效果 确认提交//保...

Android 与JS交互 调用本地相册在Html页面显示图片

Android 与JS交互浅谈Android 与 JS 交互主要分为: JS 调用Android中的方法 Android首先要用WebView加载Html页面 -mWebView.getSetti...

前端本地客户端压缩图片,兼容IOS,Android,PC、自动按需加载文件

演示一下 自己试试 点我直接进入演示页面 说明 在客户端压缩好要上传的图片可以节省带宽更快的发送给后端,特别适合在移动设备上使用。 为什么需要 ...

上传图片前端js压缩

function uploadImg(_this) { var fileName = _this.value;//文件名 var extension = new String(fileNa...

微信手机网页上传图片高效率压缩(Canvas+Base64)

最近有一个小项目,有这么一个需求,要把照片上传到服务器,可是现在手机照片都是几M几M的,所以必须压缩下,我百度来百度去,也问了下网友,终于,在网友的帮助下,写出来了.. 下面先上个压缩效果图 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:手机网页版JS压缩上传图片--base64位 兼容IOS和安卓
举报原因:
原因补充:

(最多只允许输入30个字)