JIC - Java 图像压缩器:无法在 'CanvasRenderingContext2D' 上执行 'drawImage':找不到与签名匹配的函数

JIC - Java Image Compressor : Failed to execute 'drawImage' on 'CanvasRenderingContext2D': No function was found that matched the signature

刚开始尝试JIC,但总是遇到这个错误:

Failed to execute 'drawImage' on 'CanvasRenderingContext2D': No function was found that matched the signature.

以下是我的代码:

HTML 查看:

<input type="file" ng-file-select="uploadJobImage($files)" class="upload" id="imgFle"> 

控制器方法:

$scope.uploadJobImage              = function($files){
//Images Objects
        var source_image = $files[0],
         target_img = $files[0];
         console.log(source_image);
        //(NOTE: see the examples/js/demo.js file to understand how this object could be a local image 
        //from your filesystem using the File API)
        var output_format = {
                    resizeType        : 'jpg',
                    resizeQuality     : 80,
                    resizeMaxHeight   : 456,
                    resizeMaxWidth    : window.innerWidth,
                };
        target_img.src = jic.compress(source_image,output_format);

} JIC压缩方法:

var jic = {
    /**
     * Receives an Image Object (can be JPG OR PNG) and returns a new Image Object compressed
     * @param {Image} source_img_obj The source Image Object
     * @param {Integer} quality The output quality of Image Object
     * @param {String} output format. Possible values are jpg and png
     * @return {Image} result_image_obj The compressed Image Object
     */

    compress: function(sourceImgObj, options){
        console.log(sourceImgObj);

         // var mime_type = "image/jpeg";
         // if(typeof output_format !== "undefined" && output_format=="png"){
         //    mime_type = "image/png";
         // }
         // var cvs = document.createElement('canvas');
         // cvs.width = source_img_obj.naturalWidth;
         // cvs.height = source_img_obj.naturalHeight;
         // var ctx = cvs.getContext("2d").drawImage(source_img_obj, 0, 0);
         // var newImageData = cvs.toDataURL(mime_type, quality/100);
         // var result_image_obj = new Image();
         // result_image_obj.src = newImageData;
         // return result_image_obj;

        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;

        // calculate the width and height, constraining the proportions
        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;
    },

非常感谢对此的任何帮助。

终于找到问题了,图片对象source_image应该是dataURL base 64编码的图片格式,JIC才能正确处理。经过长时间的努力,问题被解决为:

test.html 文件
- 为源图像和目标图像添加了几个 div 和一个文件选择器

<img src="" height="100%" align="middle" id="source_image">
<img src="" height="100%" align="middle" id="result_image">
<input type="file" ng-file-select="uploadJobImage($files)" 
 class="upload" id="imgFle"> 

testController.js

1) 检索到文件 blob url
- 使用 var URL = window.webkitURL || window.URL; var url = URL.createObjectURL($files[0]);

代码:

 // Retieves the file's blob url and passes it onto 
 //convertImgToBase64URL() method to convert it to base 64 encoded format
 $scope.uploadJobImage              = function($files){
        var URL = window.webkitURL || window.URL;
        var url = URL.createObjectURL($files[0]);
        alert("Image quality : "+$scope.qlty);
        var  output_format = 'jpg';
        $scope.convertImgToBase64URL(url, output_format);
    };


2) 使用 Base 64 编码
然后使用 $scope.convertImgToBase64URL(url, output_format); 方法使用 base 64 编码对其进行编码:

代码:

   // convertImgToBase64URL returns a dataurl corresponding to the 
   // input blob url
   $scope.convertImgToBase64URL  =  function(url,  outputFormat){
            alert();
            var canvas = document.createElement('CANVAS'),
                ctx = canvas.getContext('2d'),
                img = new Image;
            img.crossOrigin = 'Anonymous';
            img.onload = function(){
                var dataURL;
                canvas.height = img.height;
                canvas.width = img.width;
                ctx.drawImage(img, 0, 0);
                dataURL = canvas.toDataURL(outputFormat);
                $scope.callback(dataURL);
                // console.log("hhhh dataurl : "dataURL);
                canvas = null; 
            };
            img.src = url;
        }


3)使用JIC压缩码:
- 在callback()方法中,调用JIC图像压缩方法使用:result_image.src = jic.compress(source_image,quality,'jpg').src;

代码:

$scope.callback = function(dataURL){
                console.log("callback dataURL: "+dataURL);
                document.getElementById("source_image").src = dataURL;

                 var source_image = document.getElementById('source_image');
                var result_image = document.getElementById('result_image');
                if (source_image.src == "") {
                    alert("You must load an image first!");
                    return false;
                }

                var quality = parseInt($scope.qlty);
                console.log("Quality >>" + quality);

                console.log("process start...");
                var time_start = new Date().getTime();

                // The JIC compression Method
                result_image.src = jic.compress(source_image,quality,'jpg').src; 
               console.log(source_image+'  '+quality+'  '+output_format);
                result_image.onload = function(){
                    var image_width=$(result_image).width(),
                    image_height=$(result_image).height();

                    if(image_width > image_height){
                        result_image.style.width="320px";
                    }else{
                        result_image.style.height="300px";
                    }
                   result_image.style.display = "block";
                }
                var duration = new Date().getTime() - time_start;

                console.log("process finished...");
                console.log('Processed in: ' + duration + 'ms');   
                console.log(document.getElementById('result_image'));       
            }


JIC开源图像压缩库:

/*!
 * JIC JavaScript Library v1.1
 * https://github.com/brunobar79/J-I-C/
 *
 * Copyright 2012, Bruno Barbieri
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Date: Sat Mar 24 15:11:03 2012 -0200
 */



/**
 * Create the jic object.
 * @constructor
 */

var jic = {
        /**
         * Receives an Image Object (can be JPG OR PNG) and returns a new Image Object compressed
         * @param {Image} source_img_obj The source Image Object
         * @param {Integer} quality The output quality of Image Object
         * @param {String} output format. Possible values are jpg and png
         * @return {Image} result_image_obj The compressed Image Object
         */

        compress: function(source_img_obj, quality, output_format){

             var mime_type = "image/jpeg";
             if(typeof output_format !== "undefined" && output_format=="png"){
                mime_type = "image/png";
             }

             var cvs = document.createElement('canvas');
             cvs.width = source_img_obj.naturalWidth;
             cvs.height = source_img_obj.naturalHeight;
             // alert(source_img_obj.naturalWidth);
             // alert(source_img_obj.naturalHeight);
             console.log(source_img_obj);
             var ctx = cvs.getContext("2d").drawImage(source_img_obj, 0, 0);
             var newImageData = cvs.toDataURL(mime_type, quality/100);

             console.log(newImageData);
             var result_image_obj = new Image();
             result_image_obj.src = newImageData;
             return result_image_obj;
        },

        /**
         * Receives an Image Object and upload it to the server via ajax
         * @param {Image} compressed_img_obj The Compressed Image Object
         * @param {String} The server side url to send the POST request
         * @param {String} file_input_name The name of the input that the server will receive with the file
         * @param {String} filename The name of the file that will be sent to the server
         * @param {function} successCallback The callback to trigger when the upload is succesful.
         * @param {function} (OPTIONAL) errorCallback The callback to trigger when the upload failed.
         * @param {function} (OPTIONAL) duringCallback The callback called to be notified about the image's upload progress.
         * @param {Object} (OPTIONAL) customHeaders An object representing key-value  properties to inject to the request header.
         */

        upload: function(compressed_img_obj, upload_url, file_input_name, filename, successCallback, errorCallback, duringCallback, customHeaders){


            var cvs = document.createElement('canvas');
            cvs.width = compressed_img_obj.naturalWidth;
            cvs.height = compressed_img_obj.naturalHeight;
            var ctx = cvs.getContext("2d").drawImage(compressed_img_obj, 0, 0);

            //ADD sendAsBinary compatibilty to older browsers
            if (XMLHttpRequest.prototype.sendAsBinary === undefined) {
                XMLHttpRequest.prototype.sendAsBinary = function(string) {
                    var bytes = Array.prototype.map.call(string, function(c) {
                        return c.charCodeAt(0) & 0xff;
                    });
                    this.send(new Uint8Array(bytes).buffer);
                };
            }

            var type = "image/jpeg";
            if(filename.substr(-4)==".png"){
                type = "image/png";
            }

            var data = cvs.toDataURL(type);
            data = data.replace('data:' + type + ';base64,', '');

            var xhr = new XMLHttpRequest();
            xhr.open('POST', upload_url, true);
            var boundary = 'someboundary';

            xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);

        // Set custom request headers if customHeaders parameter is provided
        if (customHeaders && typeof customHeaders === "object") {
            for (var headerKey in customHeaders){
                xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
            }
        }

        // If a duringCallback function is set as a parameter, call that to notify about the upload progress
        if (duringCallback && duringCallback instanceof Function) {
            xhr.onprogress = function (evt) {
                if (evt.lengthComputable) {  
                    return (evt.loaded / evt.total)*100;  
                }
            };
        }

            xhr.sendAsBinary(['--' + boundary, 'Content-Disposition: form-data; name="' + file_input_name + '"; filename="' + filename + '"', 'Content-Type: ' + type, '', atob(data), '--' + boundary + '--'].join('\r\n'));

            xhr.onreadystatechange = function() {
            if (this.readyState == 4){
                if (this.status == 200) {
                    successCallback(this.responseText);
                }else if (this.status >= 400) {
                    if (errorCallback &&  errorCallback instanceof Function) {
                        errorCallback(this.responseText);
                    }
                }
            }
            };


        }
};