Problem with reading Bitmaps in C

Asked

Viewed 324 times

1

I’m having trouble reading files Bitmap. Results not as expected.

  • The size is always the same regardless of which image I open
  • Height and width do not match the size stated in the image viewer
  • The color values are not always those of the colors that are in the image
  • bmp. h:

    #ifndef  BMP_H
    #define  BMP_H
    
    #include <string.h>
    #include <stdio.h>
    #include <malloc.h>
    #include <stdlib.h>
    
    __attribute__((packed)) struct RGB{ // Color of Bitmap file
        char red;
        char green;
        char blue;
        char reserved;
    };
    
    __attribute__((packed)) struct bmp_header{
        char id[2]; // File identificator
        int size; // Size on bytes
        short int r_area_1; // Reserved area
        short int r_area_2; // Reserved area
        int offset; // Offset of Bitmap
    };
    
    __attribute__((packed)) struct bmp_header_map{
        int size; // Size of Header - 40 bytes
        int width; // Width of Bitmap
        int height; // Height of Bitmap
        short int p_quality; // Qualit of planes (default = 1)
        short int bpp; // Bits per Pixel
        int compression; // Compresion method
        int image_size; // Size of image
        int h_resolution; // Horizontal resolution
        int v_resolution; // Vertical resolution
        int p_color; // Number of color in palet
        int i_color; // Number of important colors
    };
    
    struct bitmap{
        struct bmp_header *header;
        struct bmp_header_map *map;
        struct RGB *rgb;
    };
    
    typedef struct bitmap Bitmap;
    
    extern Bitmap *bmp_read(const char *fname); // read bitmap files
    extern char bmp_write(const char *fname, Bitmap *bmp); // write bitmap files
    
    #endif  // BMP_H*/
    

    bmp_read. c

    #include "bmp.h"
    
    struct bmp_header *bmp_get_header(FILE *bmp);
    struct bmp_header_map *bmp_get_header_map(FILE *bmp);
    struct RGB *bmp_get_colors(FILE *bmp, int width, int height);
    
    extern Bitmap *bmp_read(const char *fname){
        struct bmp_header *header;
        struct bmp_header_map *map;
        struct RGB *rgb;
    
        Bitmap *bmp = (Bitmap *) malloc(sizeof(Bitmap));
        FILE *file = fopen(fname, "r");
    
        header = bmp_get_header(file);
        map = bmp_get_header_map(file);
        //rgb = bmp_get_colors(file);
    
        fclose(file);
        bmp->header = header;
        bmp->map = map;
        bmp->rgb = rgb;
    
        return bmp;
    }
    
    struct bmp_header *bmp_get_header(FILE *bmp){
        struct bmp_header *header;
        header = (struct bmp_header *) malloc(sizeof(struct bmp_header));
        bzero(header, sizeof(struct bmp_header));
    
        fread(header, sizeof(struct bmp_header), 1, bmp);
    
        return header;
    }
    
    struct bmp_header_map *bmp_get_header_map(FILE *bmp){
        struct bmp_header_map *map;
        map = (struct bmp_header_map *) malloc(sizeof(struct bmp_header_map));
        bzero(map, sizeof(struct bmp_header_map));
    
        fread(map, sizeof(struct bmp_header_map), 1, bmp);
    
        return map;
    }
    
    struct RGB *bmp_get_colors(FILE *bmp, int width, int height){
        struct RGB *rgb = (struct RGB*) malloc(sizeof(struct RGB)*width*height);
        bzero(rgb, sizeof(struct RGB));
        fread(rgb, width*height*3, 1, bmp);
    
        return rgb;
    }
    
    int main(int argc, char *argv[]){
        struct bmp_header *header;
        struct bmp_header_map *map;
        struct RGB *rgb;
        struct bitmap *bmp;
    
        bmp = bmp_read("teste.bmp");
        header = bmp->header;
        map = bmp->map;
        rgb = bmp->rgb;
    
        printf("%c%c %d %d\n",header->id[0], header->id[1], header->size, header->offset);
        printf("%dx%d %d %d\n",map->width, map->height, map->image_size, map->i_color);
        printf("%d\n", map->i_color);
        int x;
        for(x=0; x<=30; x++){
            printf("%d %dx%dx%d\n",x,rgb[x].red, rgb[x].green, rgb[x].blue);
        }
        return 0;
    }
    

    Output obtained (Ena.bmp):

    BM 3 2621440
    16777216x65536 185729024 372834304
    372834304
    0 0x0
    1 1x0x0
    2 84x8x64
    3 0x0
    4 0x0
    5 0x0
    6 109x123x113
    7 10x-65x51
    8 -48x5x64
    9 0x0
    10 -96x-68x-105
    11 -4x127x0
    12 0x0
    13 0x0
    14 0x0
    15 0x0
    16 109x123x-111
    17 -91x68x-53
    18 109x123x-31
    19 -27x-120x-75
    20 0x0
    21 0x0
    22 0x0
    23 0x0
    24 0x0
    25 0x0
    26 -96x9x64
    27 0x0
    28 -88x-68x-105
    29 -4x127x0
    30 1x0x0

    Exits obtained (test.bmp):

    BM 0 8126464
    655360x65536 185794560 -134217728
    -134217728
    0 0x0
    1 1x0x0
    2 84x8x64
    3 0x0
    4 0x0
    5 0x0
    6 -72x-4x53
    7 -39x70x-63
    8 -48x5x64
    9 0x0
    10 32x-19x-51
    11 -4x127x0
    12 0x0
    13 0x0
    14 0x0
    15 0x0
    16 -72x-4x-43
    17 -62x91x56
    18 -72x-4x-91
    19 47x4x-110
    20 0x0
    21 0x0
    22 0x0
    23 0x0
    24 0x0
    25 0x0
    26 -96x9x64
    27 0x0
    28 40x-19x-51
    29 -4x127x0
    30 1x0x0

    Lena.bmp 256x256:
    inserir a descrição da imagem aqui

    test.bmp 10x10:
    inserir a descrição da imagem aqui

    Thanks for the help!

    • The function Bitmap *bmp_read(const char *fname) does not have an instruction of return. I advise you to use as many warnings as possible from your compiler and pay attention :-)

    • I fixed it, but it’s still the same output.

    • 16777216(10) = 1000000000000000000000000(2); 65536(10) = 10000000000000000(2) ... you may have a problem with endianness

    1 answer

    1


    I believe that the problem may be in the creation of structs with multiple size of 4 bytes. In the tests I did on my machine I inserted the line

    printf("size of bmp header: %ul\n", sizeof(struct bmp_header));
    

    and was returning 16 and not 14 (despite the "attribute((packed)) struct bmp_header").

    I then entered the lines:

    #pragma pack(push, 1)
    

    and

    #pragma pack(pop)
    

    respectively at the beginning and at the end of the bmp. h file and started working. The output of the size test looked like this:

    size of bmp header: 14
    

    And the rest of the output was also consistent in my test, although I haven’t tested the excerpt:

    int x;
    for(x=0; x<=30; x++){
        printf("%d %dx%dx%d\n",x,rgb[x].red, rgb[x].green, rgb[x].blue);
    }
    

    Since the line

    //rgb = bmp_get_colors(file);
    

    was commented.

    • hahaha... It’s perfect dude, Valew by the help.

    Browser other questions tagged

    You are not signed in. Login or sign up in order to post.