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);
}
}
}
};
}
};
刚开始尝试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);
}
}
}
};
}
};