1

我目前正在研究 javascript 中的水平模糊算法,尽管我怀疑语言是否重要。

我从画布中获取数据,该画布基本上是一个巨大的数组,其中每四个(RGBA)值代表一个像素。一个值可以包含一个范围从 0 到 255 的 int。

当我模糊图像时,两种不同颜色之间的区域会变成奇怪的颜色!我在黑色背景上绘制了一个红色矩形。使用下面的算法,我得到以下结果(4px 大小):

4px 不良结果

虽然当使用 1 或 2 像素大小时,一切似乎都正常工作。

2px 想要的结果

请注意,这有点混乱。我打算让这一切都面向对象!

// s: size
// w: width
// h: height
function blur( s, w, h ) {
    var src = ctx.getImageData( 0, 0, w, h ); // get imagedata from source
    var dst = ctx.createImageData( w, h );    // create imagedata for dest
    var x, y, xo, index, rgb; // predefine vars

    // loop through y axis
    for( y = 0; y < h; y++ ) {
        // loop through x axis
        for( x = 0; x < w; x++ ) {
            rgb = 0; // set total to 0

            // loop through area around current pixel
            for( xo = 0 - s; xo <= s; xo++ ) {
                // get specific index
                index = getIndex( x + xo, y, w );

                // add nothing if the value doesn't exist (borders)
                // if( isNaN( src.data[index] ) ) continue;
                if( typeof src.data[index] === 'undefined' ) continue;

                // add the values to total
                rgb += ( src.data[index] << 16 ) + ( src.data[index + 1] << 8 ) + src.data[index + 2];
            }

            // get the average of all pixels in that area
            rgb = rgb / ( s * 2 + 1);

            // get index of current pixel
            index = getIndex( x, y, w );

            // set pixel in dest
            dst.data[index] = ( rgb & 0xff0000 ) >> 16;    // red
            dst.data[index + 1] = ( rgb & 0x00ff00 ) >> 8; // green
            dst.data[index + 2] = ( rgb & 0x0000ff );      // blue
            dst.data[index + 3] = 255; // alpha
        }
    }

    // add the new image data
    ctx.putImageData( dst, 0, 0 );
}

function getIndex( x, y, w ) {
    // calculate the appropriate index, since every pixel has 4 array values
    return ( y * ( w * 4 ) + ( x * 4 ) );
}

那么我的算法有什么问题?我有点失落。请注意,我不是在寻找用于画布模糊的现有对象/库/文件。我喜欢重新发明一切来教育自己。


编辑:我还想补充一点,我得到的值确实是代表画布上显示的颜色的值。这意味着这绝对是我算法中的错误计算。

4

2 回答 2

2

0x030000(深红色)和(黑色)之间的平均值0x000000变为0x018000,得到很多绿色(0x80) 您应该分别平均通道。

于 2012-06-18T12:34:08.253 回答
2

您应该分别平均您的频道。除以打包的三通道值不太可能将每个通道保持在其字节内。

于 2012-06-18T12:31:56.103 回答