简体   繁体   中英

java create BMP image from pixel matrix and reverse

Have a task to generate BMP file from int RGB matrix and than read that matrix from BMP image.

I've used this class to generate BMP file but it seems that it is hard to reverse this approach for getting rgbValues array from image:

/**
 * Class for creating bmp images from the pixel matrix (an int matrix).
 * @author eafkuor
 * @link http://forum.codecall.net/topic/62457-creating-a-bmp-image-in-java/
 */
import java.io.File;
import java.io.FileOutputStream;

public class BMP {
    private final static int BMP_CODE = 19778;

    byte[] bytes;

    public void saveBMP(String filename, int[][] rgbValues) {
        try {
            FileOutputStream fos = new FileOutputStream(new File(filename));

            bytes = new byte[54 + 3 * rgbValues.length * rgbValues[0].length + getPadding(rgbValues[0].length) * rgbValues.length];

            saveFileHeader();
            saveInfoHeader(rgbValues.length, rgbValues[0].length);
            saveRgbQuad();
            saveBitmapData(rgbValues);

            fos.write(bytes);

            fos.close();

        } catch (Exception ignored) {}

    }

    private void saveFileHeader() {
        byte[] a = intToByteCouple(BMP_CODE);
        bytes[0] = a[1];
        bytes[1] = a[0];

        a = intToFourBytes(bytes.length);
        bytes[5] = a[0];
        bytes[4] = a[1];
        bytes[3] = a[2];
        bytes[2] = a[3];

        //data offset
        bytes[10] = 54;
    }

    private void saveInfoHeader(int height, int width) {
        bytes[14] = 40;

        byte[] a = intToFourBytes(width);
        bytes[22] = a[3];
        bytes[23] = a[2];
        bytes[24] = a[1];
        bytes[25] = a[0];

        a = intToFourBytes(height);
        bytes[18] = a[3];
        bytes[19] = a[2];
        bytes[20] = a[1];
        bytes[21] = a[0];

        bytes[26] = 1;

        bytes[28] = 24;
    }

    private void saveRgbQuad() {

    }

    private void saveBitmapData(int[][] rgbValues) {
        int i;

        for (i = 0; i < rgbValues.length; i++) {
            writeLine(i, rgbValues);
        }

    }

    private void writeLine(int row, int[][] rgbValues) {
        final int offset = 54;
        final int rowLength = rgbValues[row].length;
        final int padding = getPadding(rgbValues[0].length);
        int i;

        for (i = 0; i < rowLength; i++) {
            int rgb = rgbValues[row][i];
            int temp = offset + 3 * (i + rowLength * row) + row * padding;

            bytes[temp] = (byte) (rgb >> 16);
            bytes[temp + 1] = (byte) (rgb >> 8);
            bytes[temp + 2] = (byte) rgb;
        }
        i--;
        int temp = offset + 3 * (i + rowLength * row) + row * padding + 3;

        for (int j = 0; j < padding; j++)
            bytes[temp + j] = 0;

    }

    private byte[] intToByteCouple(int x) {
        byte[] array = new byte[2];

        array[1] = (byte) x;
        array[0] = (byte) (x >> 8);

        return array;
    }

    private byte[] intToFourBytes(int x) {
        byte[] array = new byte[4];

        array[3] = (byte) x;
        array[2] = (byte) (x >> 8);
        array[1] = (byte) (x >> 16);
        array[0] = (byte) (x >> 24);

        return array;
    }

    private int getPadding(int rowLength) {

        int padding = (3 * rowLength) % 4;
        if (padding != 0)
            padding = 4 - padding;


        return padding;
    }
}

Is there any java lib for making such things? Or maybe someone can suggest how to reverse BMP file?

Using an API is, in my opinion, a lazy thing to do, if the task is easy to implement AND you could get a better understanding of what is happening behind the scenes. After you have done it at least once yourself, you can use an API with a good conscience. In the end you SHOULD use an API, because the working code is probably much powerful and safe to use than your own version.

Reversing an image is a very simple thing to do, in theory at least. The process consists of two steps:

  1. put the color matrix of the image into memory
  2. create a new image so that every pixel, starting from the left, is chosen from the image in memory, only starting from the right.

To illustrate:

Say we have an image that is 4px in width and 4px in height. 0 indicates the pixel is black and 1 indicates it is white.

So we have, in practice, a 4x4 binary matrix. Let us compose it as follows:

[1][0]
[1][0]

To reverse it, we simply copy the array into a new 4x4 matrix, but we copy the values to the new matrix starting from the right:

[1][0] => [0][1]
[1][0] => [0][1]

And now we have the reversed image:

[0][1]
[0][1]

This is the idea.

In an RGB context, the matrix of the original image would look something like this:

[rgb(255, 255, 255)][rgb(0, 0, 0)]
[rgb(255, 255, 255)][rgb(0, 0, 0)]

Now go find out how to extract the color of each pixel and write it to a new one. This is an easy task.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM