:
Javascript图像处理之虚拟边缘
/*
* BORDER_REPLICATE: aaaaaaaa|abcdefgh|hhhhhhhh
* BORDER_REFLECT: hgfedcba|abcdefgh|hgfedcba
* BORDER_REFLECT_101: hgfedcb|abcdefgh|gfedcba
* BORDER_WRAP: efgh|abcdefgh|abcd
* BORDER_CONSTANT: iiiiiiii|abcdefgh|iiiiiiii with some specified 'i'(default value [0, 0, 0, 255])
*/
(function () {
function imageVariousBorder(iCanvas, url, borderType, orientation, value) {
this.canvas = iCanvas;
this.iCtx = this.canvas.getContext("2d");
this.url = url;
this.borderType = borderType;
this.orientation = orientation || "bottom";
this.value = value || [0, 0, 0, 255];
}
imageVariousBorder.prototype = {
imread: function (_image) {
var width = _image.width,
height = _image.height;
this.iResize(width, height);
this.iCtx.drawImage(_image, 0, 0);
var imageData = this.iCtx.getImageData(0, 0, width, height),
tempMat = new Mat(height, width, imageData.data);
imageData = null;
this.iCtx.clearRect(0, 0, width, height);
return tempMat;
},
iResize: function (_width, _height) {
this.canvas.width = _width;
this.canvas.height = _height;
},
RGBA2ImageData: function (_imgMat) {
var width = _imgMat.col,
height = _imgMat.row;
var imageData = this.iCtx.createImageData(width, height);
imageData.data.set(_imgMat.data);
return imageData;
},
render: function () {
var img = new Image();
var _this = this;
img.onload = function () {
var myMat = _this.imread(img);
var width = myMat.col;
var height = myMat.row;
if (_this.borderType == "BORDER_WRAP") {
width = width/2;
height = height/2;
}
var strOrientation = {
"left": [0, width, 0, 0],
"right": [0, 0, 0, width],
"bottom": [0, 0, height, 0],
"top": [height, 0, 0, 0],
"left_right": [0, width, 0, width]
};
var newImage = copyMakeBorder(myMat,
strOrientation[_this.orientation][0],
strOrientation[_this.orientation][1],
strOrientation[_this.orientation][2],
strOrientation[_this.orientation][3],
_this.borderType,
_this.value);
var newIamgeData = _this.RGBA2ImageData(newImage);
var newWidth = newImage.col;
var newHeight = newImage.row;
_this.iResize(newWidth, newHeight);
_this.iCtx.putImageData(newIamgeData, 0, 0);
};
img.src = this.url;
}
};
function Mat(_row, _col, _data, _buffer) {
this.row = _row || 0;
this.col = _col || 0;
this.channel = 4;
this.buffer = _buffer || new ArrayBuffer(_row * _col * 4);
this.data = new Uint8ClampedArray(this.buffer);
_data && this.data.set(_data);
this.bytes = 1;
this.type = "CV_RGBA";
}
function copyMakeBorder(_src, _top, _left, _bottom, _right, _borderType, _value) {
if (_src.type != "CV_RGBA") {
console.log("not support this type");
} else if (_borderType == "BORDER_CONSTANT") {
return copyMakeConstBorder_8U(_src, _top, _left, _bottom, _right, _value);
} else {
return copyMakeBorder_8U(_src, _top, _left, _bottom, _right, _borderType);
}
}
function borderInterpolate(_p, _len, _borderType) {
if (_p < 0 || _p >= _len) {
switch (_borderType) {
case "BORDER_REPLICATE":
_p = _p < 0 ? 0 : _len - 1;
break;
case "BORDER_REFLECT":
case "BORDER_REFLECT_101":
var delta = (_borderType == "BORDER_REFLECT_101");
if (_len == 1) {
return 0;
}
do {
if (_p < 0) {
_p = -_p - 1 + delta;
} else {
_p = _len - 1 - (_p - _len) - delta;
}
} while (_p < 0 || _p >= _len);
break;
case "BORDER_WRAP":
if (_p < 0) {
_p -= ((_p - _len + 1) / _len | 0) * _len;
}
if (_p >= _len) {
_p %= _len;
}
break;
case "BORDER_CONSTANT":
_p = -1;
default:
console.log(arguments.callee, "UNSPPORT_BORDER_TYPE");
}
}
return _p;
}
function copyMakeBorder_8U(_src, _top, _left, _bottom, _right, _borderType) {
var i, j;
var width = _src.col,
height = _src.row;
var top = _top,
left = _left || _top,
right = _right || left,
bottom = _bottom || top,
dstWidth = width + left + right,
dstHeight = height + top + bottom,
borderType = _borderType || "BORDER_REFLECT";
var buffer = new ArrayBuffer(dstHeight * dstWidth * 4),
tab = new Uint32Array(left + right);
for (i = 0; i < left; i++) {
tab[i] = borderInterpolate(i - left, width, borderType);
}
for (i = 0; i < right; i++) {
tab[i + left] = borderInterpolate(width + i, width, borderType);
}
var tempArray, data;
for (i = 0; i < height; i++) {
tempArray = new Uint32Array(buffer, (i + top) * dstWidth * 4, dstWidth);
data = new Uint32Array(_src.buffer, i * width * 4, width);
for (j = 0; j < left; j++)
tempArray[j] = data[tab[j]];
for (j = 0; j < right; j++)
tempArray[j + width + left] = data[tab[j + left]];
tempArray.set(data, left);
}
var allArray = new Uint32Array(buffer);
for (i = 0; i < top; i++) {
j = borderInterpolate(i - top, height, _borderType);
tempArray = new Uint32Array(buffer, i * dstWidth * 4, dstWidth);
tempArray.set(allArray.subarray((j + top) * dstWidth, (j + top + 1) * dstWidth));
}
for (i = 0; i < bottom; i++) {
j = borderInterpolate(i + height, height, borderType);
tempArray = new Uint32Array(buffer, (i + top + height) * dstWidth * 4, dstWidth);
tempArray.set(allArray.subarray((j + top) * dstWidth, (j + top + 1) * dstWidth));
}
return new Mat(dstHeight, dstWidth, new Uint8ClampedArray(buffer));
}
function copyMakeConstBorder_8U(_src, _top, _left, _bottom, _right, _value) {
var i, j;
var width = _src.col,
height = _src.row;
var top = _top,
left = _left || _top,
right = _right || left,
bottom = _bottom || top,
dstWidth = width + left + right,
dstHeight = height + top + bottom,
value = _value || [0, 0, 0, 255];
var constBuf = new ArrayBuffer(dstWidth * 4),
constArray = new Uint8ClampedArray(constBuf);
buffer = new ArrayBuffer(dstHeight * dstWidth * 4);
for (i = 0; i < dstWidth; i++) {
for (j = 0; j < 4; j++) {
constArray[i * 4 + j] = value[j];
}
}
constArray = new Uint32Array(constBuf);
var tempArray;
for (i = 0; i < height; i++) {
tempArray = new Uint32Array(buffer, (i + top) * dstWidth * 4, left);
tempArray.set(constArray.subarray(0, left));
tempArray = new Uint32Array(buffer, ((i + top + 1) * dstWidth - right) * 4, right);
tempArray.set(constArray.subarray(0, right));
tempArray = new Uint32Array(buffer, ((i + top) * dstWidth + left) * 4, width);
tempArray.set(new Uint32Array(_src.buffer, i * width * 4, width));
}
for (i = 0; i < top; i++) {
tempArray = new Uint32Array(buffer, i * dstWidth * 4, dstWidth);
tempArray.set(constArray);
}
for (i = 0; i < bottom; i++) {
tempArray = new Uint32Array(buffer, (i + top + height) * dstWidth * 4, dstWidth);
tempArray.set(constArray);
}
return new Mat(dstHeight, dstWidth, new Uint8ClampedArray(buffer));
}
window.imageVariousBorder = imageVariousBorder;
})();
调用示例:
var iCanvas = document.getElementById("variousBorder_replicate");
var imgVariousBorder = new imageVariousBorder(iCanvas, "images/1.jpg", "BORDER_REPLICATE", "right");
imgVariousBorder.render();