Java BufferedImage: 如何通过访问像素数组正确地将图像复制多次?

huangapple go评论62阅读模式
英文:

Java BufferedImage: How do i copy an image properly n times by accessing the pixel - array?

问题

以下是您提供的内容的翻译部分:

我正在处理一个问题,这个问题有点像是从我正在进行的一个项目中“分叉”出来的。虽然对于项目本身来说并不是必需的解决方案,但我提到了这个起源,因为这是一个有点“奇特具体”的任务。

我试图从文件中读取一个小的BufferedImage(8x8像素)。这个图像的像素被写入一个长度为64的整数数组中(显然是64个像素)。

然后,创建一个长度为64 * 64(=4096)的新数组。小数组的像素被复制到大数组中,每次到达末尾时,较小的索引都会被重置为0。

最后,我创建一个新的BufferedImage,宽度=64,高度=64。然后将大数组设置为该BufferedImage的rgbArray。代码如下:

public static void main(String[] args) throws IOException {
    
    BufferedImage toCopy = ImageIO.read(new File("smallStripes.png"));
    BufferedImage copiedNTimes = new BufferedImage(64, 64, BufferedImage.TYPE_BYTE_BINARY); 
    // copiedNTimes 将成为结果图像

    Graphics2D g2d = (Graphics2D) copiedNTimes.getGraphics();
    g2d.setColor(Color.WHITE);
    g2d.fillRect(0, 0, 64, 64);

    int[] smallPixels = new int[64];

    toCopy.getRGB(0, 0, 8, 8, smallPixels, 0, 8);
    // 将读取图像的rgb数组复制到64个数组中

    int[] copied = copyNTimes(smallPixels, new int[64*64]);

    copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 8);
    // 将结果图像的rgb数组设置为复制的数组

    FileOutputStream fos = new FileOutputStream(new File("result.png"));
    ImageIO.write(copiedNTimes, "png", fos);
}

static int[] copyNTimes(int[] small, int[] big){

    // 这个方法将小数组复制到大数组中,直到大数组“填满为止”
    
    int index = 0;

    for(int x = 0 ; x < big.length; x++){
        big[x] = small[index];
        index++;
        if(index == small.length)
            index = 0;
    }

    return big;
}

它基本上按照我预期的方式工作,但图像被“偏移”写入:

smallStripes.png:

Java BufferedImage: 如何通过访问像素数组正确地将图像复制多次?

result.png :

Java BufferedImage: 如何通过访问像素数组正确地将图像复制多次?

我的问题是:

我怎样才能让这些条纹“对齐”在一起?现在,从左到右,是8像素的黑色,8像素的白色,8像素的黑色... 依此类推。为什么不是64像素的黑色(新行)64像素的白色(新行)等等?

正如已经提到的,这是一个非常具体且过于简化的描述,以便我可以更好地描述它。

英文:

I am dealing with a problem which kind of "forked" from a project I'm working on. It was not necessary solving for the project itself, but I'm mentioning the origin because it is kind of a 'strangely specific' task.

I am trying to read in a small BufferedImage from a file (8x8 pixels).
This image's pixels are written into an integer array, with length 64 (obviously).

Then, a new Array with the length 64*64 (=4096) is created. The pixels of the small array are copied into the large one 64 times, just resetting the smaller index to 0 everytime it reaches the end.

Finally, I create a new BufferedImage with width = 64 and height = 64. The large array is then set as rgbArray of said BufferedImage. The code is as follows:

public static void main(String[] args)throws IOException {
BufferedImage toCopy = ImageIO.read(new File(&quot;smallStripes.png&quot;));
BufferedImage copiedNTimes = new BufferedImage(64, 64, BufferedImage.TYPE_BYTE_BINARY); 
//copiedNTimes is to be the resulting image
Graphics2D g2d = (Graphics2D) copiedNTimes.getGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, 64, 64);
int[] smallPixels = new int[64];
toCopy.getRGB(0, 0, 8, 8, smallPixels, 0, 8);
//copy the rgb array of read image into the 64 - array
int[] copied = copyNTimes(smallPixels, new int[64*64]);
copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 8);
//setting the rgb array of result image to the copied one
FileOutputStream fos = new FileOutputStream(new File(&quot;result.png&quot;));
ImageIO.write(copiedNTimes, &quot;png&quot;, fos);
}
static int[] copyNTimes(int[] small, int[] big){
//this method copies the small array into the larger one
//until the larger one is &#39;filled up&#39;
int index = 0;
for(int x = 0 ; x &lt; big.length; x++){
big[x] = small[index];
index++;
if(index == small.length)
index = 0;
}
return big;
}

It works more or less as I expected it to, but images are written 'shifted':

smallStripes.png:

Java BufferedImage: 如何通过访问像素数组正确地将图像复制多次?

result.png :

Java BufferedImage: 如何通过访问像素数组正确地将图像复制多次?

My question is:

How could I accomplish that the stripes 'line up' to each other? Right now it is, from left to right, 8px black, 8px white, 8px black... and so forth.
Why not 64 px black (new line) 64 px white (new line) etc.?

As is already said, it is oddly specific and oversimplified so I can describe it better.

答案1

得分: 2

代码中使用scanline=8作为setRGB的最后一个参数,并且在copyNTimes函数中存在错误逻辑,这导致了条纹效果。如果您希望将8x8像素图像重复到64x64像素图像中,以8x8块的形式重复,可以使用以下代码替换setRGB调用,将小图像重复到大图像中:

for (int x = 0; x < 64; x += 8)
    for (int y = 0; y < 64; y += 8)
        copiedNTimes.setRGB(x, y, 8, 8, smallPixels, 0, 8);

或者使用以下代码替换setRGB调用,首先构建较大的int[],然后一次性应用:

copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 64);

另外,可以使用以下代码来替换copyNTimes函数,以正确实现复制逻辑:

static int[] copyNTimes(int[] small, int[] big){
    for(int x = 0; x < big.length; x++){
        big[x] = small[8 * ((x / 64) % 8) + (x % 8)];
    }
    return big;
}
英文:

The code you have uses scanline=8 as last parameter to setRGB and also wrong logic in copyNTimes which causes your stripped effect. If you want 8x8 pixel image repeating into 64x64 pixel image as 8x8 blocks either replace your setRGB call with this to repeat the small image into the larger one:

for (int x = 0 ; x &lt; 64 ; x += 8)
for (int y = 0 ; y &lt; 64 ; y += 8)
copiedNTimes.setRGB(x, y, 8, 8, smallPixels, 0, 8);

Or replace your setRGB call with this to build the larger int[] first and apply it in one step:

copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 64);
static int[] copyNTimes(int[] small, int[] big){
for(int x = 0 ; x &lt; big.length; x++){
big[x] = small[8 * ((x / 64) % 8) + (x % 8)];
}
return big;
}

huangapple
  • 本文由 发表于 2020年10月23日 21:38:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/64501105.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定