js图片压缩并保留EXIF信息

1.html代码:

<%@ page language="java" contentType="text/html; charset=utf-8"  pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>JS实现图片压缩</title>
        <jsp:include page="/WEB-INF/jsps/common/scriptIncEs.jsp"></jsp:include>
        <jsp:include page="/WEB-INF/jsps/common/styleIncEs.jsp"></jsp:include>
        <script type="text/javascript" src="<c:url value='/js/image/image.min.js'/>"></script>
    </head>
    <body>
        <input type="file" id="filedom" onchange="auploadFile('12345678901234567890123456789012','OCR')"/>
        <img src="#" id="img" class="none">
    </body>
</html>

2.js部分代码:

var ImageTool = {
    /*
     * @param rawImageArray{ArrayBuffer|Array|Blob}
     */
    getSegments: function(rawImage, callback) {
        if (rawImage instanceof Blob) {
            var that = this;
            var fileReader = new FileReader();
            fileReader.onload = function() {
                that.getSegments(fileReader.result, callback);
            };
            fileReader.readAsArrayBuffer(rawImage);
        } else {
            if (!rawImage.length && !rawImage.byteLength) {
                return [];
            }
            var head = 0,
                segments = [];
            var length,
                endPoint,
                seg;
            var arr = [].slice.call(new Uint8Array(rawImage), 0);

            while (1) {
                if (arr[head] === 0xff && arr[head + 1] === 0xda) { //Start of Scan 0xff 0xda  SOS
                    break;
                }

                if (arr[head] === 0xff && arr[head + 1] === 0xd8) { //Start of Image 0xff 0xd8  SOI
                    head += 2;
                } else { //找到每个marker
                    length = arr[head + 2] * 256 + arr[head + 3]; //每个marker 后 的两个字节为 该marker信息的长度
                    endPoint = head + length + 2;
                    seg = arr.slice(head, endPoint); //截取信息
                    head = endPoint;
                    segments.push(seg); //将每个marker + 信息 push 进去。
                }
                if (head > arr.length) {
                    break;
                }
            }
            callback(segments);
        }
    },
    /*
     * @param resizedImg{ArrayBuffer|Blob}
     * @param exifArr{Array|Uint8Array}
     */
    insertEXIF: function(resizedImg, exifArr, callback) {
        if (resizedImg instanceof Blob) {
            var that = this;
            var fileReader = new FileReader();
            fileReader.onload = function() {
                that.insertEXIF(fileReader.result, exifArr, callback);
            };
            fileReader.readAsArrayBuffer(resizedImg);
        } else {
            var arr = [].slice.call(new Uint8Array(resizedImg), 0);
            if (arr[2] !== 0xff || arr[3] !== 0xe0) {
                // throw new Error("Couldn't find APP0 marker from resized image data.");
                return resizedImg; //不是标准的JPEG文件
            }

            var app0_length = arr[4] * 256 + arr[5]; //两个字节

            var newImage = [0xff, 0xd8].concat(exifArr, arr.slice(4 + app0_length)); //合并文件 SOI + EXIF + 去除APP0的图像信息

            callback(new Uint8Array(newImage));
        }
    },
    /*
     * @param segments{Array|Uint8Array}
     */
    getEXIF: function(segments) {
        if (!segments.length) {
            return [];
        }
        var seg = [];
        for (var x = 0; x < segments.length; x++) {
            var s = segments[x];
            //TODO segments
            if (s[0] === 0xff && s[1] === 0xe1) { // app1 exif 0xff 0xe1
                seg = seg.concat(s);
            }
        }
        return seg;
    },
    /*
     *@param base64{String}
     */
    decode64: function(base64) {
        var b64 = "data:image/jpeg;base64,";
        if (base64.slice(0, 23) !== b64) {
            return [];
        }
        var binStr = window.atob(base64.replace(b64, ""));
        var buf = new Uint8Array(binStr.length);
        for (var i = 0, len = binStr.length; i < len; i++) {
            buf[i] = binStr.charCodeAt(i);
        }
        return buf;
    },
    /*
     *@param arr{Array}
     */
    encode64: function(arr) {
        var data = "";
        for (var i = 0, len = arr.length; i < len; i++) {
            data += String.fromCharCode(arr[i]);
        }
        return "data:image/jpeg;base64," + window.btoa(data);
    }
};

function showImage(file,callback){
    var reader = new FileReader();
    reader.onload = function(){
        callback(reader.result);
    }
    reader.readAsDataURL(file);
}

function imageResize(img, rete, quality,callback) {
    var type = "image/jpeg";
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    // quality = options.quality || 0.8;
    const { width: originWidth, height: originHeight } = img
    console.dir("originWidth * originHeight:"+originWidth+"*"+originHeight);
    var widthNew = rete * originWidth;
    var heightNew = rete * originHeight;
    console.dir("widthNew * heightNew:"+widthNew+"*"+heightNew);
    canvas.width = widthNew;
    canvas.height = heightNew;
    ctx.drawImage(img, 0, 0, widthNew, heightNew);
    canvas.toBlob(callback, type, quality);
}


/** base64转file
 * filename图片的名字,dataurl是base64地址
 */
function dataURLtoFile(dataurl, filename) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {type:mime});
}

/**
 * 调用互联网平台接口解析压缩有的图片,并返回解析map
 * (弃用,原因是跨域)
 * */

function ocr(fileNew){
    var params = {
            "ocr":fileNew
    };
    var formArray = $("#ocrForm").serializeArray();
    $.each(formArray, function(i, item) {
        params[item.name] = item.value;
    });
    
    console.dir(params);
    var url = "";
    $.ajax({
        url:url,
        type:"post",
        dataType:"json",
        data:params,
        success:function(data){
            console.dir(data);
        },
        error:function(){
            alert("解析error");
        }
    });
}


/**
 * 上传附件
 * */
function uploadFile(fileNew,bid,btype){
    var formData = new FormData();
    formData.append("upload",fileNew);
    var uploadUrl = $WEB_ROOT_PATH+'/mupload/muploadCtrl?BLHMI=msave&uploadAttachment.businessId='+bid+'&uploadAttachment.businessType='+btype;
    $.ajax({
        url:uploadUrl,
        type:"post",
        dataType:"json",
        async: false,
        cache: false,
        contentType: false,
        processData: false,
        data:formData,
        success:function(data){
            //这里是上传之后做的事情,我这里打开了上传服务的图片地址。
            console.dir(data.mResult.data[0].url);
            window.open(data.mResult.data[0].url,'_blank');
        },
        error:function(){
            alert("上传error");
        }
    });
}


/**
 * file-onchange 
 * 1.判断选取图片的大小
 * 2.小于bigFileSize则继续上传;大于bigFileSize则进行压缩,压缩到(smallFileSize,bigFileSize)之间。将压缩后得文件上传
 * */
var rete = 0.3;
function auploadFile(bid,bType){
    var filedom = document.getElementById("filedom");
    var imgdom = document.getElementById("img");
    var bigFileSize = 95;
    var smallFileSize = 85;
    var reteS = 0.01;
    
    var startTime = Date.now();
    console.dir("=========================");
    console.dir("等比例压缩比例:"+rete);
    var imgFile = filedom.files[0];
    if(!imgFile){    
        alert("请选择图片文件!");
        return false;
    }
    
    var fileSize = imgFile.size / 1024;
    console.dir("文件大小:"+fileSize + "kb");
    if(fileSize < bigFileSize){
        console.dir("文件不需要压缩");
        uploadFile(imgFile,bid,bType);
    }else if(fileSize>bigFileSize){
        showImage(imgFile,function(src){
            imgdom.src = src;
            imgdom.onload = function(){
                imageResize(imgdom,rete,1,function(blob){
                    ImageTool.getSegments(imgFile,function(segments){
                        var exif = ImageTool.getEXIF(segments);//获取exif信息
                        ImageTool.insertEXIF(blob,exif,function(newImage){
                                fileSize = newImage.length / 1024;
                                console.dir("压缩后的文件大小:"+fileSize+"kb");
                                if(fileSize < smallFileSize){
                                    rete += reteS;
                                    auploadFile(bid,bType);
                                }
                                if(fileSize > bigFileSize){
                                    rete -= reteS;
                                    auploadFile(bid,bType);
                                }
                                
                                if(fileSize >= smallFileSize && fileSize <= bigFileSize){
                                    showImage(new Blob([newImage],{type : "image/jpeg"}),function(src){
                                        /*var img = new Image();
                                        img.src = src;
                                        document.body.appendChild(img);*/
                                        var fileNew = dataURLtoFile(src, imgFile.name);
                                        console.dir("新文件对象:"+fileNew);
                                        var endTime = Date.now();
                                        console.dir("压缩用时:"+ (endTime- startTime) + "ms");
                                        console.dir("开始上传===================");
//                                        ocr(fileNew);
                                        uploadFile(fileNew,bid,bType);
                                        var ocrEndTime = Date.now();
                                        console.dir("上传用时:"+ (ocrEndTime- endTime) + "ms");
                                    });
                                }  
                        });
                    });//获取 分割 segments
                });
            }
        });
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值