java - 如何随机交换图像的像素?

标签 java arrays image-processing bufferedimage

我一直在研究一个 Java 程序,该程序读取图像,将其分割为可定义数量的矩形图 block ,然后将每个图 block 的像素与另一个图 block 的像素交换,然后将它们放回一起并渲染图像.

想法的解释:http://i.imgur.com/OPefpjf.png

我一直在使用 BufferedImage 类,所以我的想法是首先从它的数据缓冲区中读取所有 width * height 像素并将它们保存到一个数组中。

然后,根据瓦片的高宽,将每个瓦片的全部像素信息复制到小数组中,并打乱,然后将这些数组中包含的数据写回到数据缓冲区中的位置。然后用原始颜色和样本模型以及更新的数据缓冲区创建一个新的 BufferedImage 就足够了。

但是,在从更新的数据缓冲区创建新的 WriteableRaster 时,我遇到了不祥的错误,并且像素数不匹配(我突然得到 24 而不是原来的 8,所以第四),所以我认为我处理像素信息的方式有问题。

(BufferedImageWriteableRaster 的引用页)

我使用以下循环遍历一维数据缓冲区:

// maximum iteration values
int numRows = height/tileHeight;
int numCols = width/tileWidth;

// cut picture into tiles

// for each column of the image matrix
// addressing columns (1D)
for ( int column = 0; column < numCols; column++ )
{
    // for each row of the matrix
    // addressing cells (2D)
    for ( int row = 0; row < numRows; row++ )
    {
        byte[] pixels = new byte[(tileWidth+1) * (tileHeight+1)];
        int celloffset = (column + (width * row)); // find cell base address

        // for each row inside the cell
        // adressing column inside a tile (3D)
        for ( int colpixel = 0; colpixel < tileWidth; colpixel++ )
        {
            // for each column inside the tile -> each pixel of the cell
            for ( int rowpixel = 0; rowpixel < tileHeight; rowpixel++ )
            {
                // address of pixel in original image buffer array allPixels[]
                int origpos = celloffset + ((rowpixel * tileWidth) + colpixel);

                // translated address of pixel in local pixels[] array of current tile
                int transpos = colpixel + (rowpixel * tileWidth);

                // source, start, dest, offset, length 
                pixels[transpos] = allPixels[origpos];
            }
        }
    }
}

这段代码有问题吗?或者是否有一种我还没有想到的更简单的方法来做到这一点?

最佳答案

下面的代码就地编辑图像。所以不需要创建新的对象,这应该会简化。如果您需要保留原件,只需先将其完整复制即可。此外,无需保存到单独的数组。

既然你说“洗牌”,我假设你想随机交换瓷砖。我为此做了一个函数,如果你多次调用它,你最终会随机交换瓷砖。如果您想要交换它们的模式或其他规则,只需使用您选择的图 block 直接调用其他函数即可。

之前没有用过BufferedImage,但是看了文档,

http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html

还有这篇文章,

Edit pixel values

似乎一个简单的方法是使用方法 getRGB 和 setRGB

int getRGB(int x, int y)

Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace.

void setRGB(int x, int y, int rgb)

Sets a pixel in this BufferedImage to the specified RGB value.

我会尝试如下操作:(未经测试的代码)

使用随机 http://docs.oracle.com/javase/7/docs/api/java/util/Random.html

int numRows = height/tileHeight;
int numCols = width/tileWidth;

void swapTwoRandomTiles (BufferedImage b) {
    //choose x and y coordinates randomly for the tiles
    int xt1 = random.nextInt (numCols);
    int yt1 = random.nextInt (numRows);
    int xt2 = random.nextInt (numCols);
    int yt2 = random.nextInt (numRows);

    swapTiles (b,xt1,yt1,xt2,yt2);
}

void swapTiles(BufferedImage b, int xt1, int yt1, int xt2, int yt2) {
    int tempPixel = 0;
    for (int x=0; x<tileWidth; x++) {
        for (int y=0; y<tileHeight; y++) {
            //save the pixel value to temp
            tempPixel = b.getRGB(x + xt1*tileWidth, y + yt1*tileHeight);
            //write over the part of the image that we just saved, getting data from the other tile
            b.setRGB ( x + xt1*tileWidth, y + yt1*tileHeight, b.getRGB ( x+xt2*tileWidth, y+yt2*tileHeight));
            //write from temp back to the other tile
            b.setRGB ( x + xt2*tileWidth, y + yt2*tileHeight, tempPixel);
        }
    }
}

关于java - 如何随机交换图像的像素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30493127/

相关文章:

java - FrameLayout 和 setLayoutParams 使我的 View 无效

java - Twitter4J:从用户那里获取超过 1 条推文

opencv - 从索贝尔确定图像梯度方向?

algorithm - 检测文本的颜色

java - 我们可以在 java opencv 中为纹理/颜色特征创建词袋吗?

java - spring-data-mongodb: findAll() 包含输入文档列表和嵌入式 DBRef 文档的搜索参数

java - 在应用程序运行时更新 Spring Boot 属性的更好方法

javascript - 如何将相同的元素添加到javascript数组n次

arrays - SQLite 从表中删除字段与数组中的对象不匹配的表

java - 如何将该数组的每个元素放入字符串中?