0

I am trying to learn image processing using c.

#include <stdio.h>

int main(){
    FILE *streamIn;
    streamIn=fopen("lena512.bmp","r");

    //read imageHeader and colorTable
    unsigned char header[54];//to store the image header
    //unsigned char colorTable[1024];//to store the colorTable,if it exists

    for(int i=0;i<54;i++){
            header[i]=getc(streamIn);
    }
    /*
      width of the image(18th byte)
      height of the image(22nd byte)
      bitDepth of the image(28th byte)
    */
    int width=*(int*)(&header[18]);
    int height=*(int*)(&header[22]);
    int bitDepth=*(int*)(&header[28]);


}

I came across the line which i couldn't understand.

int width=*(int*)(&header[18]);

Why can't we simply do the type casting like int width=(int)(header[18]);?

  • Because `header` is declared `unsigned char (array of)`. Aside: it's better to use the official Windows headers for this. – 500 - Internal Server Error Oct 18 '21 at 12:20
  • To clarify, `(int)` does not mean treat `` as if it were an `int` reference. Rather it means, _convert_ whatever `` is to `(int)`. In this case `` is `header[18]`, which is an `unsigned char` value. So that will take that one byte value and expand it to `int` size. – 500 - Internal Server Error Oct 18 '21 at 12:31

2 Answers2

2

I came across the line which i couldn't understand.
int width=*(int*)(&header[18]);

Neither did the person who wrote it, because this is blatant undefined behavior in several different ways. It gives This gives a misaligned address (on mainstream systems) as well as a strict aliasing violation. What is the strict aliasing rule?

Those 3 lines at the end are bugs, you cannot write C code like that. The correct way to write this program might be to copy the data into pre-defined structs, provided by the OS API.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • (Unfortunately in case of Windows wingdi.h, the bitmap API is broken by design and relies on the ancient "struct hack". So it cannot be reliably used by standard C compilers...) – Lundin Oct 18 '21 at 13:36
1

You are using *(int*)(&header[18]) and you want to know why (int)(header[18]) can't be used.

Well, these are completely different expressions.

The first one takes the address of header[18], which is an unsigned char, so this gives a pointer to such. Casting it to a pointer to int and dereferencing it by * in the assignment copies a complete int starting at that address, reading all necessary bytes.

The second one simply reads the single unsigned char in header[18] and casts the value to an int. This will use only the first byte.


Note: Microsoft's header files provide structure definitions of the BMP header. It's much better to use them. You can for example call fread() to read the header.

the busybee
  • 10,755
  • 3
  • 13
  • 30