如何随机交换图像的像素?
How to swap pixels of an image randomly?
我一直在开发一个 Java 程序,该程序读取图像,将其细分为可定义数量的矩形图块,然后将每个图块的像素与另一个图块的像素交换,然后将它们放入回到一起并渲染图像。
想法的解释:http://i.imgur.com/OPefpjf.png
我一直在使用 BufferedImage
class,所以我的想法是首先从它的数据缓冲区中读取所有 width * height
像素并将它们保存到一个数组中。
然后,根据瓦片的高宽,将每个瓦片的全部像素信息复制到小数组中,打乱,然后将这些数组中包含的数据写回到数据缓冲区中的位置。然后用原始颜色和样本模型以及更新的数据缓冲区创建一个新的 BufferedImage
就足够了。
然而,当我从更新的数据缓冲区创建一个新的 WriteableRaster
时出现了不祥的错误,并且像素数不匹配(我突然得到 24 而不是原来的 8,等等), 所以我认为我处理像素信息的方式有问题。
(BufferedImage and WriteableRaster 的参考页数)
我使用以下循环遍历一维数据缓冲区:
// 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];
}
}
}
}
这段代码有问题吗?或者是否有一种我还没有想到的更简单的方法来做到这一点?
下面的代码就地编辑图像。所以不需要创建新的对象,这应该会简化。如果您需要保留原件,只需先将其完整复制即可。此外,无需保存到单独的数组。
既然你说 "shuffle" 我假设你想随机交换瓷砖。我为此做了一个函数,如果你多次调用它,你最终会随机交换瓷砖。如果您想要交换它们的模式或其他规则,只需使用您选择的图块直接调用其他函数即可。
之前没有用过BufferedImage,但是看了文档,
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
还有这个post,
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 程序,该程序读取图像,将其细分为可定义数量的矩形图块,然后将每个图块的像素与另一个图块的像素交换,然后将它们放入回到一起并渲染图像。
想法的解释:http://i.imgur.com/OPefpjf.png
我一直在使用 BufferedImage
class,所以我的想法是首先从它的数据缓冲区中读取所有 width * height
像素并将它们保存到一个数组中。
然后,根据瓦片的高宽,将每个瓦片的全部像素信息复制到小数组中,打乱,然后将这些数组中包含的数据写回到数据缓冲区中的位置。然后用原始颜色和样本模型以及更新的数据缓冲区创建一个新的 BufferedImage
就足够了。
然而,当我从更新的数据缓冲区创建一个新的 WriteableRaster
时出现了不祥的错误,并且像素数不匹配(我突然得到 24 而不是原来的 8,等等), 所以我认为我处理像素信息的方式有问题。
(BufferedImage and WriteableRaster 的参考页数)
我使用以下循环遍历一维数据缓冲区:
// 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];
}
}
}
}
这段代码有问题吗?或者是否有一种我还没有想到的更简单的方法来做到这一点?
下面的代码就地编辑图像。所以不需要创建新的对象,这应该会简化。如果您需要保留原件,只需先将其完整复制即可。此外,无需保存到单独的数组。
既然你说 "shuffle" 我假设你想随机交换瓷砖。我为此做了一个函数,如果你多次调用它,你最终会随机交换瓷砖。如果您想要交换它们的模式或其他规则,只需使用您选择的图块直接调用其他函数即可。
之前没有用过BufferedImage,但是看了文档,
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
还有这个post,
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);
}
}
}