Javascript影象處理之虛擬邊緣

weixin_34041003發表於2013-01-18

  原理來自Justany_WhiteSnowJavascript影象處理——虛擬邊緣一文。  

/*
 * 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();

  效果:

 

 

 

 

 

相關文章