我一直在研究一个读取图像的Java程序,将其细分为可定义数量的矩形图块,然后将每个图块的像素与另一个图块的像素交换,然后将它们重新组合在一起并渲染图像
对这个想法的解释:http://i.imgur.com/OPefpjf.png
我一直在使用BufferedImage
类,所以我的想法是首先从其数据缓冲区中读取所有width * height
像素并将它们保存到数组中。
然后,根据图块的高度和宽度,将每个图块的整个像素信息复制到小数组中,对其进行混洗,然后将这些数组中包含的数据写回到它们在数据缓冲区中的位置。然后,应该足以使用原始颜色和样本模型以及更新的数据缓冲区创建新的BufferedImage
。
但是,从更新的数据缓冲区创建新的WriteableRaster
时,我遇到了不祥的错误,并且像素数不匹配(我突然得到24而不是原来的8,依此类推),所以我认为我解决像素信息的方式有问题。
(BufferedImage和WriteableRaster的参考页面)
我使用以下循环来遍历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];
}
}
}
}
这段代码有问题吗?或者是否有一种更容易实现的方法,我还没有想到呢?
答案 0 :(得分:1)
下面的代码就是在适当的位置编辑图像。所以不需要创建新的对象,这应该简化。如果您需要保留原件,请先完全复制。此外,无需保存到单独的阵列。
既然你说“shuffle”我假设你想随机交换瓷砖。我为此做了一个功能,如果你多次调用它,你最终会随机交换瓷砖。如果您想要一个模式或其他规则来交换它们,只需直接使用您选择的图块调用另一个函数。
我之前没有使用过BufferedImage,但是看一下文档,
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
和这篇文章,
似乎一种简单的方法是使用方法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);
}
}
}