JavaFX writing bmp image pixel by pixel

岁酱吖の 提交于 2020-06-29 03:37:37

问题


I have written a class to read the BMP files with all the necessary headers as stated here "http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm"

The class reads all the necessary headers and for the raw data, it reads them as bytes as shown below -

private byte[] calcBytes(String path) throws IOException {
    //Get the path of the file
    Path file_path = Paths.get(path);

    //Return the byte array of the file
    return Files.readAllBytes(file_path);
}

Following this, I convert the bytes(stored as little-endian) values to the decimal equivalent and store them as pixel(RGB) values in an array(size: width*height) as shown below.

private int[][] calcPixels(byte[] bytes){
    //Find padding, if divisible by 4
    int padding = this.width % 4;

    //If not divisible by 4, find the closest next that is divisible
    if(padding != 0){

        //Find closest bigger padding number divisible by 4
        while ((padding % 4) != 0){
            padding++;
        }
    }

    //Output Pixel array store the pixel values[R,G,B] format
    int[][] output_pixels = new int[((this.width + padding) * this.height)][3];

    //Initialize the cols(column) of the pixel data as zero
    int col = 0;
    //Position to fill the output pixel array in correct index
    int pos = 0;

    //Iterate through the bytes array
    for (int index = 0; index < bytes.length; index += 3){

        //Increment the col
        col++;

        //Bytes to hex
        String blue_hex  = String.format("%02X", bytes[index]);
        String green_hex = String.format("%02X", bytes[index+1]);
        String red_hex   = String.format("%02X", bytes[index+2]);

        //Hex to int/short values
        short blue  = (short) Integer.parseInt(blue_hex, 16);
        short green = (short) Integer.parseInt(green_hex, 16);
        short red   = (short) Integer.parseInt(red_hex, 16);

        //Adding to the main array
        output_pixels[pos++] = new int[] {red, green, blue};

        //Increment Padding with at last column
        if(col == (this.width+padding)/4){

            //Skip the bytes since it is the padding
            index += padding;

            //Denote the end of the row or last column[RGB] as [-1,-1,-1], reset the value of the last stored pixel
            output_pixels[pos - 1] = new int[] {(short)-1, (short)-1, (short)-1};

            //Row will change now
            col = 0;

        }
    }

    return output_pixels;
}

Having generated the pixel array with necessary RGB data. I then use JavaFX to generate the pixel represented by a Rectangle shape class and giving it a when iterating through the pixel data array as generated above.

@Override
    public void start(Stage primaryStage) throws Exception{

    Button button = new Button("Select Image File");

    String path = System.getProperty("user.dir") + "/filePath/image.bmp";

    //Reads the BMP file and generate headers, bytes and pixels as shown above
    BMP bmp = new BMP(path);

    //Initialize the root
    Group root = new Group();

    int[][] pixelsData = bmp.getPixelsData();

    //X (to manipulate the x coordinate of the pixel i.e. rectangle shape class)
    double xFactor = 1.0;
    double startX = 0.0;
    double endX   = startX + xFactor;

    //Y (to manipulate the x coordinate of the pixel i.e. rectangle shape class)
    double yFactor = 0.5;
    double startY = 0.0;
    double endY   = startY + yFactor;

    for (int index = 0; index < pixelsData.length; index++){

        //Get Colors
        int red   = pixelsData[index][0];
        int green = pixelsData[index][1];
        int blue  = pixelsData[index][2];

        if(red == -1 && green == -1 && blue == -1){
            
            //Start Next Line
            startY += yFactor;
            endY += yFactor;
            startX = 0.0;
            endX = startX + xFactor;

            continue;
        }
        else {//keep moving the x coordinate
            startX += xFactor;
            endX += xFactor;
        }

        Color color = Color.rgb(red,green,blue);

        Rectangle rectangle = new Rectangle(startX,startY,endX,endY);
        rectangle.setFill(color);
        root.getChildren().add(rectangle);
    }

    primaryStage.setScene(new Scene(root, 700, 700));
    primaryStage.show();
}

Now when I actually generate the image with the code above. The image seems to blur out towards the end of the x-axis and also misses a lot of pixels in on the sides. Example as shown below:

Original Image

JavaFX Image

I also reversed the iteration of my JavaFX pixel data loop in order to generate the image in the right order but no luck.

If you look closely at the original image and the two JavaFX images, it is evident that the left and right side of the "cat" in the pictures is printed fine but blurs out only because of the co-ordinate in my opinion.

I have spent 2 days trying to figure it out but I am really confused. Can someone please help out with my understanding or point out any mistake I might be committing in my code.

来源:https://stackoverflow.com/questions/62625348/javafx-writing-bmp-image-pixel-by-pixel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!