Bitmap is read wrong

I'm trying to read a .bmb file with c++ and save the grey values (average over RGB values) normalized into a vector under Ubuntu 14.04. Somehow the values of the vector end up completely wrong. Can you imagine why?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
std::vector<double> readBMP(const char* filename, int* width, int* height){
    std::vector<double> bmp;
    FILE* f = fopen(filename, "rb");
    
    if(f == NULL){
        std::cerr << "file not found!" << std::endl;
        std::vector<double> empty;
        width = NULL;
        height = NULL;
        return empty;
    }
    
    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
    
    // extract image height and width from header
    *width = *(int*)&info[18];
    *height = *(int*)&info[22];
    int data_offset = *(int*)(&info[0x0A]);
    fseek(f, (long int)(data_offset - 54), SEEK_CUR);
    
    int row_padded = (*width*3 + 3) & (~3);
    unsigned char* data = new unsigned char[row_padded];
    unsigned char tmp;
    
    for(int i = 0; i < *height; i++)
    {
        fread(data, sizeof(unsigned char), row_padded, f);
        for(int j = 0; j < *width*3; j += 3)
        {
            // Convert (B, G, R) to (R, G, B)
            tmp = data[j];
            data[j] = data[j+2];
            data[j+2] = tmp;
            bmp.push_back(((double)data[j]+(double)data[j+1]+(double)data[j+2])/(3*255));
    
            std::cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< std::endl;
        }
    }
    return bmp;
}


I print the rgb values, and checked it with an example image, which has nine pixels:

black | black | black
---------------------
grey | grey | grey
---------------------
white | white | white


The expected output should be (it's reversed):


R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 128 G: 128 B: 128
R: 128 G: 128 B: 128
R: 128 G: 128 B: 128
R: 0 G: 0 B: 0
R: 0 G: 0 B: 0
R: 0 G: 0 B: 0




but it is:

 
R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 128 G: 128 B: 255
R: 128 G: 255 B: 128
R: 255 G: 128 B: 128
R: 0 G: 0 B: 255
R: 0 G: 255 B: 0
R: 255 G: 0 B: 0
Last edited on
could not reproduce.
Upload the image that you are using (make sure that there is no conversion)

width = NULL;
conceptual error, you are modifying a local variable

unsigned char* data = new unsigned char[row_padded];
never deleted, memory leak

// Convert (B, G, R) to (R, G, B)
useless, you are making an average.

> which has four pixels
3x3=9
Last edited on
I hope the link is working:
http://s000.tinyupload.com/index.php?file_id=74340124465018188766
It's my simple bitmap file.

I'm aware of the useless conversion and the memory leak and should have changed that, but I was just changing an existing code for my use. Anyway these are not the problems.
Last edited on
> Anyway these are not the problems.
But they add unnecessary complications to the analysis.

$ file example.bmp
example.bmp: PC bitmap, Windows 98/2000 and newer format, 3 x 3 x 32
each pixel has a depth of 32, corresponding to R, G, B, A.
You did not take into account the `A' field and so were reading the end of one pixel and the start of the neighbour.

changes
1
2
    fseek(f, (long int)(data_offset - 53), SEEK_CUR); //start later (¿is it ABGR?)
        for(int j = 0; j < row_padded; j += 4) //jump 4 fields 
Last edited on
Thank you, now it's working fine.
Just two last questions, how can I know if the bitmap is ARGB or only RGB?
And is the -53 instead of the -54 at the offset because of the ARGB or was the -54 simply wrong?
Last edited on
You should read the file specification

https://en.wikipedia.org/wiki/BMP_file_format
(1C) the number of bits per pixel, which is the color depth of the image. Typical values are 1, 4, 8, 16, 24 and 32.



Although the examples there show BGRA, doing an hexdump got ABGR in images created with gimp.

Also, there is no need to load the whole header if you are only interested on the first 0A (or 1C) bytes.
And using 54 is error-prone, you may `fgetpos()' instead.
Topic archived. No new replies allowed.