web前端之HTML5压缩图片compress image with canvas

在android开发中上传图片(头像)到服务器,压缩图片,直接用对应的API,获取原图的长宽,然后取得压缩比例,compress到指定的质量,输出保存就行了,下文介绍。今天因为web活动页广告中需要上传图片,如果太大直接上传,用户体验和服务器压力,简直不能直视。so,一起学习下前端压缩图片的方式吧。

1,实现原理

compress jpeg or png files using angularjs on client side - using HTML5 Canvas & File API (based off of a J-I-C project on github).

本案例可以在github上面找到,我fork了:
https://github.com/duqian291902259/ng-image-compress
选择一张图片,用FileReader读取,然后计算图片的宽和高,确定缩放比例,在canvas上面drawImage,最后用toDataURL获得压缩后的图片。
亲测ok

2,web HTML页面

<div>
    <input id="inputImage" type="file" accept="image/*" image="image1" resize-max-height="1000" resize-max-width="1000" resize-quality="0.7" resize-type="image/jpg" /> 
    <img ng-src="{{image1.compressed.dataURL}}" /> <!-- just do a console.log of {{image1}} to see what other options are in the file object -->
  </div>
  <!--<script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>-->
  <script src="scripts/angular.min.js"></script>
  <script src="scripts/app.js"></script>
  <script src="scripts/ng-image-compress.js"></script>

3,angular.min.js

angularJs,你懂得,很火的前端框架,适合移动端web页面,可以去官网下载,也可以这下载,不是最新,凑合着用吧:
http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js

4,app.js

可以拿到app变量,方便在在其他文件中定义controller directive。

'use strict';
var app = angular.module('angNewsApp', []);

5,ng-image-compress.js

页面中没有canvas,就创建canvas控件,并将其隐藏。

'use strict';
app.directive('image', ['$q',
    function($q) {
        var URL = window.URL || window.webkitURL;
        var getResizeArea = function() {
            var resizeAreaId = 'fileupload-resize-area';
            var resizeArea = document.getElementById(resizeAreaId);
            if (!resizeArea) {
                resizeArea = document.createElement('canvas');
                resizeArea.id = resizeAreaId;
                resizeArea.style.visibility = 'hidden';
                document.body.appendChild(resizeArea);
            }
            return resizeArea;
        };

        /**
         * 接收JPG OR PNG图片,返回压缩图片对象
         * @param {Image} sourceImgObj 原图
         * @param {Integer} quality 输出图片的质量,最高100
         * @return {Image} result_image_obj 压缩后的图片
         */

        var jicCompress = function(sourceImgObj, options) {
            var outputFormat = options.resizeType;
            var quality = options.resizeQuality * 100 || 70;
            var mimeType = 'image/jpeg';
            if (outputFormat !== undefined && outputFormat === 'png') {
                mimeType = 'image/png';
            }
            var maxHeight = options.resizeMaxHeight || 300;
            var maxWidth = options.resizeMaxWidth || 250;
            var height = sourceImgObj.height;
            var width = sourceImgObj.width;
            // 计算宽高,限制压缩后的最大尺寸
            if (width > height) {
                if (width > maxWidth) {
                    height = Math.round(height *= maxWidth / width);
                    width = maxWidth;
                }
            }
            else {
                if (height > maxHeight) {
                    width = Math.round(width *= maxHeight / height);
                    height = maxHeight;
                }
            }
            //画布绘制图片
            var cvs = document.createElement('canvas');
            cvs.width = width; //sourceImgObj.naturalWidth;
            cvs.height = height; //sourceImgObj.naturalHeight;
            var ctx = cvs.getContext('2d').drawImage(sourceImgObj, 0, 0, width, height);
            var newImageData = cvs.toDataURL(mimeType, quality / 100);
            var resultImageObj = new Image();
            resultImageObj.src = newImageData;
            return resultImageObj.src;
        };

        var resizeImage = function(origImage, options) {
            var maxHeight = options.resizeMaxHeight || 300;
            var maxWidth = options.resizeMaxWidth || 250;
            var quality = options.resizeQuality || 0.7;
            var type = options.resizeType || 'image/jpg';
            var canvas = getResizeArea();
            var height = origImage.height;
            var width = origImage.width;
            if (width > height) {
                if (width > maxWidth) {
                    height = Math.round(height *= maxWidth / width);
                    width = maxWidth;
                }
            }
            else {
                if (height > maxHeight) {
                    width = Math.round(width *= maxHeight / height);
                    height = maxHeight;
                }
            }
            //画布的宽高与指定的相同
            canvas.width = width;
            canvas.height = height;
            //canvas上绘制图片
            var ctx = canvas.getContext('2d');
            ctx.drawImage(origImage, 0, 0, width, height);

            // 获取指定格式和质量的图片数据
            return canvas.toDataURL(type, quality);
        };

        var createImage = function(url, callback) {
            var image = new Image();
            image.onload = function() {
                callback(image);
            };
            image.src = url;
        };

        var fileToDataURL = function(file) {
            var deferred = $q.defer();
            var reader = new FileReader();
            reader.onload = function(e) {
                deferred.resolve(e.target.result);
            };
            reader.readAsDataURL(file);
            return deferred.promise;
        };


        return {
            restrict: 'A',
            scope: {
                image: '=',
                resizeMaxHeight: '@?',
                resizeMaxWidth: '@?',
                resizeQuality: '@?',
                resizeType: '@?'
            },
            link: function postLink(scope, element, attrs) {

                var doResizing = function(imageResult, callback) {
                    createImage(imageResult.url, function(image) {
                        //var dataURL = resizeImage(image, scope);
                        var dataURLcompressed = jicCompress(image, scope);
                        // imageResult.resized = {
                        //  dataURL: dataURL,
                        //  type: dataURL.match(/:(.+\/.+);/)[1]
                        // };
                        imageResult.compressed = {
                            dataURL: dataURLcompressed,
                            type: dataURLcompressed.match(/:(.+\/.+);/)[1]
                        };
                        callback(imageResult);
                    });
                };

                var applyScope = function(imageResult) {
                    scope.$apply(function() {
                        console.log(imageResult);
                        if (attrs.multiple) {
                            scope.image.push(imageResult);
                        }
                        else {
                            scope.image = imageResult;
                        }
                    });
                };


                element.bind('change', function(evt) {
                    //选中文件后,如果有多个文件,则遍历取出
                    if (attrs.multiple)
                        {scope.image = [];}

                    var files = evt.target.files;
                    for (var i = 0; i < files.length; i++) {
                        //create a result object for each file in files
                        var imageResult = {
                            file: files[i],
                            url: URL.createObjectURL(files[i])
                        };

                        fileToDataURL(files[i]).then(function(dataURL) {
                            console.log(dataURL)
                            imageResult.dataURL = dataURL;
                        });

                        if (scope.resizeMaxHeight || scope.resizeMaxWidth) { //resize image
                            doResizing(imageResult, function(imageResult) {
                                applyScope(imageResult);
                            });
                        }
                        else { //no resizing
                            applyScope(imageResult);
                        }
                    }
                });
            }
        };
    }
]);

6,总结

之前做了一年多的web前端。现在的前端技术,越来越6666了。js是不能写压缩图片的功能的,只能用HTML5的canvas,有一定的兼容性。足见HTML5的强大,此文,我只是分享的搬运工,拿去研究吧。
Dusan,291902259,OpenDeveloper。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值