Java 将位图RGB像素加载到BuffereImage

Java 将位图RGB像素加载到BuffereImage,java,colors,bitmap,rgb,Java,Colors,Bitmap,Rgb,因此,我最终编写了代码来检测位图的所有正确RGB值,并将其存储 BufferedImage image = new BufferedImage(adjWidth, this.height, BufferedImage.TYPE_3BYTE_BGR); // start from bottom row for(int i = this

因此,我最终编写了代码来检测位图的所有正确RGB值,并将其存储

BufferedImage image = new BufferedImage(adjWidth, 
                                        this.height, 
                                        BufferedImage.TYPE_3BYTE_BGR);

// start from bottom row
for(int i = this.height-1; i >= 0; i--) {
    for(int j = 0; j < adjWidth-2; j += 3) {
        int index = adjWidth*i + j;
        int b = iData[index];
        int g = iData[index+1];
        int r = iData[index+2];
        int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff); // merge rgb values to single int
        /*
        System.out.printf("\nRow: %s\nColumn: %s\nRed: %s\n"
                            + "Green: %s\nBlue: %s\n", i, j, 
                            (rgb>>16)&0x0ff, (rgb>>8)&0x0ff, (rgb)&0x0ff);
        System.out.println("Color value: " + rgb);
        */
        // build image from bottom up
        image.setRGB(j, this.height-i-1, rgb);
    }
}
BufferedImage image=新的BufferedImage(adjWidth,
这个,身高,
buffereImage.TYPE_3BYTE_BGR);
//从最底层开始
对于(int i=this.height-1;i>=0;i--){
对于(int j=0;j
iData是从文件中读取的字节[]。我知道我的RGB值在调试完它们的值之后是正确的,并且将它们与十六进制编辑器进行了比较。AdjWidth是包含填充的宽度

但是,我的图像在整个图像上以垂直黑带输出。当我将图像与源图像进行比较时,我知道图像部分是正确的,尽管有点失真,但我认为所有这些源都来自这个问题。我怀疑这是因为j增加了3,所以当我设置像素值时,它会跳过那些像素。如何避免这种情况,并创建正确的图像

输入bmp:

输出bmp:

编辑
顺便说一句,我这样做是为了练习。

它可能缺少一些代码和进一步的解释,但是:您有一个数组,每个像素包含3个值。因此,您在内部循环中以
j+=3
递增。但是,对于每三个值,输出图像应仅接收一个像素

所以你可以用

image.setRGB(j/3, this.height-i-1, rgb);
或者让循环遍历输出图像的大小,并在访问数组时将坐标乘以3,大致如下所示:

for(int j = 0; j < adjWidth-2; j++) {
    int index = (adjWidth*i + j) * 3;
    int b = iData[index];
    int g = iData[index+1];
    int r = iData[index+2];
    ...
    image.setRGB(j, this.height-i-1, rgb);
}

为什么不使用ImageIO.read()?我这样做是为了练习。您确定源图像是bgr 24位格式的吗?为什么你的目标BuffereImage是3BYTE_BGR而不是INT_RGB或INT_ARGB?是的,因为我已经正确读取了头。因为我以为位图是以3字节BGR格式存储像素的?然而,将格式更改为INT_RGB不会改变任何内容。“我知道java有原生bmp支持。”事实上,不,java没有bmp支持。我以前尝试过第一种方法,它给出了这个输出(如预期的那样):下一种方法给出了该图像的左三分之一在整个过程中复制三次。@TetraComputerTure添加了一个示例,也许会有帮助。哇,是的,确实有用。我终于做到了!!起初我使用了你的*3方法,但显然我没有考虑改变其余的变量,这次我考虑了,而且很有效!对非常感谢你!我知道这毫无意义,但这是理解文件格式的一个很好的练习,不是吗?(: @Marco13@Tetramputechture“无意义”一词指的是我的例子,在我的例子中,我必须创建数组,当然,我创建数组的方式可以在以后使用它的地方使用-但它有帮助,这才是最重要的;-)
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class ImagePixelsTest {
    public static void main(String[] args) {

        int w = 256;
        int h = 256;
        byte bgr[] = new byte[w * h * 3];
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                int index = (y * w + x) * 3;
                bgr[index + 0] = (byte) x;
                bgr[index + 1] = (byte) y;
                bgr[index + 2] = 0;
            }
        }

        final BufferedImage image = createImage(w, h, bgr);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.getContentPane().add(new JLabel(new ImageIcon(image)));
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }

    private static BufferedImage createImage(int w, int h, byte bgr[]) {
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);

        for (int y = h - 1; y >= 0; y--) {
            for (int x = 0; x < w; x++) {
                int index = (y * w + x) * 3;
                int b = bgr[index + 0];
                int g = bgr[index + 1];
                int r = bgr[index + 2];
                int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);
                image.setRGB(x, y, rgb);
            }
        }
        return image;
    }

}