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

时间:2015-05-27 21:05:14

标签: java arrays image-processing bufferedimage

我一直在研究一个读取图像的Java程序,将其细分为可定义数量的矩形图块,然后将每个图块的像素与另一个图块的像素交换,然后将它们重新组合在一起并渲染图像

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

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

然后,根据图块的高度和宽度,将每个图块的整个像素信息复制到小数组中,对其进行混洗,然后将这些数组中包含的数据写回到它们在数据缓冲区中的位置。然后,应该足以使用原始颜色和样本模型以及更新的数据缓冲区创建新的BufferedImage

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

BufferedImageWriteableRaster的参考页面)

我使用以下循环来遍历1D数据缓冲区:

// 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];
            }
        }
    }
}

这段代码有问题吗?或者是否有一种更容易实现的方法,我还没有想到呢?

1 个答案:

答案 0 :(得分:1)

下面的代码就是在适当的位置编辑图像。所以不需要创建新的对象,这应该简化。如果您需要保留原件,请先完全复制。此外,无需保存到单独的阵列。

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

我之前没有使用过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)

  

返回默认RGB颜色模型中的整数像素   (TYPE_INT_ARGB)和默认的sRGB色彩空间。

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

  

将此BufferedImage中的像素设置为指定的RGB值。

我会尝试以下内容:(未经测试的代码)

使用随机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);
        }
    }
}