You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
6.6 KiB
264 lines
6.6 KiB
/**
|
|
* covert canvas to image
|
|
* and save the image file
|
|
*/
|
|
|
|
var Canvas2Image = function () {
|
|
|
|
// check if support sth.
|
|
var $support = function () {
|
|
var canvas = document.createElement('canvas'),
|
|
ctx = canvas.getContext('2d');
|
|
|
|
return {
|
|
canvas: !!ctx,
|
|
imageData: !!ctx.getImageData,
|
|
dataURL: !!canvas.toDataURL,
|
|
btoa: !!window.btoa
|
|
};
|
|
}();
|
|
|
|
var downloadMime = 'image/octet-stream';
|
|
|
|
function scaleCanvas (canvas, width, height) {
|
|
var w = canvas.width,
|
|
h = canvas.height;
|
|
if (width == undefined) {
|
|
width = w;
|
|
}
|
|
if (height == undefined) {
|
|
height = h;
|
|
}
|
|
|
|
var retCanvas = document.createElement('canvas');
|
|
var retCtx = retCanvas.getContext('2d');
|
|
retCanvas.width = width;
|
|
retCanvas.height = height;
|
|
retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);
|
|
return retCanvas;
|
|
}
|
|
|
|
function getDataURL (canvas, type, width, height) {
|
|
canvas = scaleCanvas(canvas, width, height);
|
|
return canvas.toDataURL(type);
|
|
}
|
|
|
|
function saveFile (strData) {
|
|
document.location.href = strData;
|
|
}
|
|
|
|
function genImage(strData) {
|
|
var img = document.createElement('img');
|
|
img.src = strData;
|
|
return img;
|
|
}
|
|
function fixType (type) {
|
|
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
|
|
var r = type.match(/png|jpeg|bmp|gif/)[0];
|
|
return 'image/' + r;
|
|
}
|
|
function encodeData (data) {
|
|
if (!window.btoa) { throw 'btoa undefined' }
|
|
var str = '';
|
|
if (typeof data == 'string') {
|
|
str = data;
|
|
} else {
|
|
for (var i = 0; i < data.length; i ++) {
|
|
str += String.fromCharCode(data[i]);
|
|
}
|
|
}
|
|
|
|
return btoa(str);
|
|
}
|
|
function getImageData (canvas) {
|
|
var w = canvas.width,
|
|
h = canvas.height;
|
|
return canvas.getContext('2d').getImageData(0, 0, w, h);
|
|
}
|
|
function makeURI (strData, type) {
|
|
return 'data:' + type + ';base64,' + strData;
|
|
}
|
|
|
|
|
|
/**
|
|
* create bitmap image
|
|
* 按照规则生成图片响应头和响应体
|
|
*/
|
|
var genBitmapImage = function (data) {
|
|
var imgHeader = [],
|
|
imgInfoHeader = [];
|
|
|
|
var width = data.width,
|
|
height = data.height;
|
|
|
|
imgHeader.push(0x42); // 66 -> B
|
|
imgHeader.push(0x4d); // 77 -> M
|
|
|
|
var fsize = width * height * 3 + 54; // header size:54 bytes
|
|
imgHeader.push(fsize % 256); // r
|
|
fsize = Math.floor(fsize / 256);
|
|
imgHeader.push(fsize % 256); // g
|
|
fsize = Math.floor(fsize / 256);
|
|
imgHeader.push(fsize % 256); // b
|
|
fsize = Math.floor(fsize / 256);
|
|
imgHeader.push(fsize % 256); // a
|
|
|
|
imgHeader.push(0);
|
|
imgHeader.push(0);
|
|
imgHeader.push(0);
|
|
imgHeader.push(0);
|
|
|
|
imgHeader.push(54); // offset -> 6
|
|
imgHeader.push(0);
|
|
imgHeader.push(0);
|
|
imgHeader.push(0);
|
|
|
|
// info header
|
|
imgInfoHeader.push(40); // info header size
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(0);
|
|
|
|
// 横向info
|
|
var _width = width;
|
|
imgInfoHeader.push(_width % 256);
|
|
_width = Math.floor(_width / 256);
|
|
imgInfoHeader.push(_width % 256);
|
|
_width = Math.floor(_width / 256);
|
|
imgInfoHeader.push(_width % 256);
|
|
_width = Math.floor(_width / 256);
|
|
imgInfoHeader.push(_width % 256);
|
|
|
|
// 纵向info
|
|
var _height = height;
|
|
imgInfoHeader.push(_height % 256);
|
|
_height = Math.floor(_height / 256);
|
|
imgInfoHeader.push(_height % 256);
|
|
_height = Math.floor(_height / 256);
|
|
imgInfoHeader.push(_height % 256);
|
|
_height = Math.floor(_height / 256);
|
|
imgInfoHeader.push(_height % 256);
|
|
|
|
imgInfoHeader.push(1);
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(24); // 24位bitmap
|
|
imgInfoHeader.push(0);
|
|
|
|
// no compression
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(0);
|
|
imgInfoHeader.push(0);
|
|
|
|
// pixel data
|
|
var dataSize = width * height * 3;
|
|
imgInfoHeader.push(dataSize % 256);
|
|
dataSize = Math.floor(dataSize / 256);
|
|
imgInfoHeader.push(dataSize % 256);
|
|
dataSize = Math.floor(dataSize / 256);
|
|
imgInfoHeader.push(dataSize % 256);
|
|
dataSize = Math.floor(dataSize / 256);
|
|
imgInfoHeader.push(dataSize % 256);
|
|
|
|
// blank space
|
|
for (var i = 0; i < 16; i ++) {
|
|
imgInfoHeader.push(0);
|
|
}
|
|
|
|
var padding = (4 - ((width * 3) % 4)) % 4;
|
|
var imgData = data.data;
|
|
var strPixelData = '';
|
|
var y = height;
|
|
do {
|
|
var offsetY = width * (y - 1) * 4;
|
|
var strPixelRow = '';
|
|
for (var x = 0; x < width; x ++) {
|
|
var offsetX = 4 * x;
|
|
strPixelRow += String.fromCharCode(imgData[offsetY + offsetX + 2]);
|
|
strPixelRow += String.fromCharCode(imgData[offsetY + offsetX + 1]);
|
|
strPixelRow += String.fromCharCode(imgData[offsetY + offsetX]);
|
|
}
|
|
for (var n = 0; n < padding; n ++) {
|
|
strPixelRow += String.fromCharCode(0);
|
|
}
|
|
|
|
strPixelData += strPixelRow;
|
|
} while(-- y);
|
|
|
|
return (encodeData(imgHeader.concat(imgInfoHeader)) + encodeData(strPixelData));
|
|
|
|
};
|
|
|
|
/**
|
|
* saveAsImage
|
|
* @param canvasElement
|
|
* @param {String} image type
|
|
* @param {Number} [optional] png width
|
|
* @param {Number} [optional] png height
|
|
*/
|
|
var saveAsImage = function (canvas, width, height, type) {
|
|
if ($support.canvas && $support.dataURL) {
|
|
if (type == undefined) { type = 'png'; }
|
|
type = fixType(type);
|
|
if (/bmp/.test(type)) {
|
|
var data = getImageData(scaleCanvas(canvas, width, height));
|
|
var strData = genBitmapImage(data);
|
|
saveFile(makeURI(strData, downloadMime));
|
|
} else {
|
|
var strData = getDataURL(canvas, type, width, height);
|
|
saveFile(strData.replace(type, downloadMime));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
var convertToImage = function (canvas, width, height, type) {
|
|
if ($support.canvas && $support.dataURL) {
|
|
if (type == undefined) { type = 'png'; }
|
|
type = fixType(type);
|
|
|
|
if (/bmp/.test(type)) {
|
|
var data = getImageData(scaleCanvas(canvas, width, height));
|
|
var strData = genBitmapImage(data);
|
|
return genImage(makeURI(strData, 'image/bmp'));
|
|
} else {
|
|
var strData = getDataURL(canvas, type, width, height);
|
|
return genImage(strData);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
saveAsImage: saveAsImage,
|
|
saveAsPNG: function (canvas, width, height) {
|
|
return saveAsImage(canvas, width, height, 'png');
|
|
},
|
|
saveAsJPEG: function (canvas, width, height) {
|
|
return saveAsImage(canvas, width, height, 'jpeg');
|
|
},
|
|
saveAsGIF: function (canvas, width, height) {
|
|
return saveAsImage(canvas, width, height, 'gif')
|
|
},
|
|
saveAsBMP: function (canvas, width, height) {
|
|
return saveAsImage(canvas, width, height, 'bmp');
|
|
},
|
|
|
|
convertToImage: convertToImage,
|
|
convertToPNG: function (canvas, width, height) {
|
|
return convertToImage(canvas, width, height, 'png');
|
|
},
|
|
convertToJPEG: function (canvas, width, height) {
|
|
return convertToImage(canvas, width, height, 'jpeg');
|
|
},
|
|
convertToGIF: function (canvas, width, height) {
|
|
return convertToImage(canvas, width, height, 'gif');
|
|
},
|
|
convertToBMP: function (canvas, width, height) {
|
|
return convertToImage(canvas, width, height, 'bmp');
|
|
}
|
|
};
|
|
|
|
}();
|