Create BMP File with byte array

47 Views Asked by At

I have a problem with the code, the idea is to create an image in black, and then make color changes. At the moment the only thing I want to do is to create the black image using the ByteBuffer class, but when I run the image is corrupted. This is the code

package co.edu.uptc.persistence;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class BMFile {
    private String fileName;
    private int width;
    private int heigth;
    private int imageSize;
    private int fileSize;

    private String fileType;
    private short reserved1;
    private short reserved2;
    private int dataBegin;
    private int headSize;
    private short layers;
    private short pixelSize;
    private int compresion;
    private int horizontalResolution;
    private int verticalResolution;
    private int colorTableSize;
    private int countMainColor;
    private int adjustment;

    public BMFile(String fileName, int width, int heigth) {
        this.fileName = fileName;

        this.width = width;
        this.heigth = heigth;
        imageSize = width * heigth * 3;
        fileSize = imageSize + 54;

        fileType = "BM";
        reserved1 = 0;
        reserved2 = 0;
        dataBegin = 54;
        headSize = 40;
        layers = 1;
        pixelSize = 24;
        compresion = 0;
        horizontalResolution = 0;
        verticalResolution = 0;
        colorTableSize = 0;
        countMainColor = 0;
    }

    public void saveFile() throws Exception {
        createFile(fileName, createHeader(), createImage());
    }

    private void createFile(String objectFile, byte[] header, byte[] image) throws Exception {
        try (FileOutputStream fuente = new FileOutputStream(objectFile)) {
            fuente.write(header);
            fuente.write(image);
        } catch (FileNotFoundException e) {
            System.out.println("eroooooorrrr");
            throw new Exception("Ha ocurrido un error archivo no encontrado");
        } catch (IOException e) {
            System.out.println("eroooooorrrr");
            throw new Exception("Ha ocurrido un error I/O");
        }
    }

    private byte[] createHeader() {
        byte[] header = new byte[54];
        
        header[0] = 'B';
        header[1] = 'M';
        ByteBuffer.wrap(header, 2, 4).putInt(fileSize);
        ByteBuffer.wrap(header, 10, 4).putInt(dataBegin);
        ByteBuffer.wrap(header, 14, 4).putInt(headSize);
        ByteBuffer.wrap(header, 18, 4).putInt(width);
        ByteBuffer.wrap(header, 22, 4).putInt(heigth);
        ByteBuffer.wrap(header, 26, 2).putShort(layers);
        ByteBuffer.wrap(header, 28, 2).putShort(pixelSize);
        ByteBuffer.wrap(header, 30, 4).putInt(compresion);
        ByteBuffer.wrap(header, 34, 4).putInt(imageSize);
        ByteBuffer.wrap(header, 38, 4).putInt(horizontalResolution);
        ByteBuffer.wrap(header, 42, 4).putInt(verticalResolution);
        ByteBuffer.wrap(header, 46, 4).putInt(colorTableSize);
        ByteBuffer.wrap(header, 50, 4).putInt(countMainColor);
        
        return header;
    }

    private byte[] createImage() {
        byte[] image = new byte[this.imageSize];
        for (int i = 0; i < image.length; i += 3) {
            image[i] = 0;
            image[i + 1] = 0;
            image[i + 2] = (byte) 0;
        }
        return image;
    }
    

When I look at the image properties I notice that the image size is fine, but the rest for some reason fails.

As I said before, the idea is to create a black image, and then modify the createImage method to set other colors, but the image is corrupted.

1

There are 1 best solutions below

0
matt On

There are two problems with this. 1st the bmp should be little endian. 2nd You were missing a header.

Here is how I changed the header method so that it would create a black bmp file.

private byte[] createHeader() {
    byte[] header = new byte[54];
    
    ByteBuffer buffer = ByteBuffer.wrap(header);
    buffer.order(ByteOrder.LITTLE_ENDIAN);
    buffer.put((byte)'B');
    buffer.put((byte)'M');
    buffer.putInt(fileSize);
    buffer.putInt(0); //missing
    buffer.putInt(dataBegin);
    
    buffer.putInt(headSize);
    buffer.putInt(width);
    buffer.putInt(heigth);
    buffer.putShort(layers);
    buffer.putShort(pixelSize);
    buffer.putInt(compresion);
    buffer.putInt(0); // ignored
    buffer.putInt(horizontalResolution);
    buffer.putInt(verticalResolution);
    buffer.putInt(colorTableSize);
    buffer.putInt(countMainColor);
    
    return header;
}

I used this as a reference for the bmp header.