0

I'm trying to convert 480x280 24-bit bitmap file to a C array (1-bit per pixel). Here is my code which is based on this answer:

int main(void)
{
    int i, j;
    int avg = 0;
    unsigned int line = 0;
    unsigned char byte = 0;
    unsigned char *ptr;

    FILE* f = fopen("test.bmp", "rb");
    unsigned char info[54];

    // read the 54-byte header
    fread(info, sizeof(unsigned char), 54, f);

    // extract image height and width from header
    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    // allocate 3 bytes per pixel
    int size = 3 * 280 * 480;
    unsigned char* data = (unsigned char*)malloc(size);

    // read the rest of the data at once
    fread(data, sizeof(unsigned char), size, f);
    fclose(f);

    /* convert 24-bit to 1-bit -> each 3 bytes (r,g,b) to 1 bit (black,white) */
    for(i = 0; i < size; i += 24)
    {
        ptr = &data[i];

        /* take 24 bytes in each iteration (3 colors per pixel x 8 pixels) */
        for(j = 0; j < 24; j += 3)
        {
            /* convert 3 bytes to 1 byte */
            avg = (ptr[j] + ptr[j+1] + ptr[j+2]) / 3;

            /* convert 1 byte to white or black bit */
            if(avg > 128)
                byte |= (1 << (j / 3)); /* black */
            else
                byte |= (0 << (j / 3)); /* white */
        }

        printf("0x%02X,", byte);
        byte = 0;
        avg = 0;

        if(++line == 16)
        {
            printf("\n");
            line = 0;
        }
    }
}

This does the job but the result array produces edgy image. Check these original and converted images: original

converted

What am I missing to get a smooth result image?

Salahuddin
  • 1,617
  • 3
  • 23
  • 37
  • You're missing something in the header data fields. Use proper structures for the headers, and examine them using a debugger. – Some programmer dude Jan 26 '22 at 12:14
  • Either that, or your byte-ordering is incorrect. – Some programmer dude Jan 26 '22 at 12:30
  • Or maybe the bit ordering inside the bytes? Try `byte |= (0x80 >> (j / 3));`. I suggest to use an input image that contains a diagonal line only. This might better show if the bytes are arranged in a wrong way or flipped. – Bodo Jan 26 '22 at 12:42
  • 2
    Your result is not just edgy and doesn't need to get smoother. Your result is just completely wrong. It is mirrored. Without opening in an bitmap editor I would guess each 8 pixels are horizontally mirrored. I would assume that you feed the bits into your `byte` variable from the wrong side.: `byte |= (1 << (j / 3)); /* black */` should be `byte |= (1 << (7 - j / 3)); /* black */` or `byte |= (0x80 >> (j / 3));` as Bodo just commented. – Gerhardh Jan 26 '22 at 12:42
  • Why do you take 8 pixels at once in averaging? – tshiono Jan 26 '22 at 12:49
  • Thank you all. The problem was in the bit ordering and in the offset address where I start reading the bitmap data. – Salahuddin Jan 26 '22 at 13:19

1 Answers1

0

the image You Convert Is RGB888 may be your Runnning Controller accepct ARGB888. Convert RGB Image With Alpha ARGB888.