3
\$\begingroup\$

What my code does is it reads a 24 bit bitmap image in color, runs a very simple edge detection algorithm and outputs a monochrome 1 bit bitmap with the edges in white. Here is an example of the output.

The basic algorithm is that I am looping through all of the pixels in the 24 bit bitmap two pixels at a time and if the difference between the average values of the two pixels is greater than 10 I set the equivalent pixels in the 1 bit file to white.

To give the code context, the variable "header" is an object that holds all of the information about the 24 bit bitmap file such as the height and width and the pointer to where the header ends and the bitmap that holds the pixel values begins. The "header" object was passed into the constructor of the object that has the ten() function.

The one_bit_bitmap "small" variable does the same thing for the 1 bit bitmap that I am outputting to.

The file format of the 24 bit is there is one byte per color (blue,green,red) per pixel. The format for the 1 bit is that there are two 32 bit pixels just after the header information and setting a bit to 0 points that pixel to the value of the first pixel while setting it to 1 sets to to the value of the second pixel.

This is a personal project that I started to learn about file formats, C++ pointers and flipping individual bits.

void bmp_binary_edge::ten() {
    char * pointer_ahead = header.getBytesAhead();
    unsigned int width_bytes = header.getWidthBytes();
    unsigned int padding_bytes = header.getPaddingBytes();
    unsigned int height = header.getHeightPixels();
    one_bit_bitmap small = one_bit_bitmap(header);
    char * small_ahead = small.getBytesAhead();
    unsigned int small_position = 0;
    for (unsigned int y = 0; y < height; y++) {
        int small_bit_position = 7;
        for (unsigned int x = 0; x < width_bytes; x += 6) {
            unsigned int starting_position = x + (y * width_bytes) + y * padding_bytes;
            unsigned char blue = (unsigned char) pointer_ahead[starting_position];
            unsigned char green = (unsigned char) pointer_ahead[starting_position + 1];
            unsigned char red = (unsigned char) pointer_ahead[starting_position + 2];
            unsigned char blue2 = (unsigned char) pointer_ahead[starting_position + 3];
            unsigned char green2 = (unsigned char) pointer_ahead[starting_position + 4];
            unsigned char red2 = (unsigned char) pointer_ahead[starting_position + 5];
            unsigned char first_av = (blue + red + green) / 3;
            unsigned char second_av = (blue2 + red2 + green2) / 3;
            int difference = first_av - second_av;
            if (difference < 0) {
                difference *= -1;
            }
            //One
            if (difference > 10) {
                small_ahead[small_position ] ^= (-1 ^ small_ahead[small_position]) & (1 << small_bit_position);
                small_ahead[small_position ] ^= (-1 ^ small_ahead[small_position]) & (1 << (small_bit_position - 1));
            }
            if (small_bit_position == 1) {
                small_position++;
                small_bit_position = 7;
            }
            else {
                small_bit_position -= 2;
            }
        }
        small_position += small.getPaddingBytes();
    }
    small.fileWrite(ext_ten);
    cout << "bmp_binary_edge ten" << endl;
    cout << line_break;
    header.deleteBytes();
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

I'm just going to rattle off the things I see as I find them.

  • header.getBytesAhead() should return a void *
  • pointer_ahead should be a unsigned char const *
  • small_ahead should be a unsigned char *
  • Loop x over the pixels (width) not the bytes.
  • for (unsigned int x = 0; x < width; x += 2)
  • starting_position = x * 6 + y * ( width * 3 + padding_bytes )
  • int difference = abs(first_av - second_av)
  • small_position = x / 8 + y * ( small_width + small_padding_bytes )
  • small_bit_position = x % 8
  • small_ahead[ small_position ] |= 3 << small_bit_position
  • Use std::vector so header.deleteBytes is unnecessary.

Edit:

  • small_position = x / 8 + y * ( ( width + 7 ) / 8 + small_padding_bytes )
  • To handle an odd width: for (unsigned int x = 0; x + 1 < width; x += 2)
\$\endgroup\$
2
  • \$\begingroup\$ Why the difference between the suggestion for the pointer_head and small_ahead ? \$\endgroup\$ Apr 7, 2017 at 2:53
  • 1
    \$\begingroup\$ pointer_ahead is reading and small_ahead is writing. \$\endgroup\$ Apr 7, 2017 at 2:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.