Reputation: 1
I am trying to code a program that works to downscale a bitmap file. I can read successfully the size of the file and height and width values but I have to get RGB values of pixels and assign them into pixels array. But I get irrelevant values and I couldn't understand why I'm not getting the exact values of pixels. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include "bitmap.h"
int main()
{
FILE *bmp_input;
bmp_input=fopen("itu.bmp","rb");
BITMAPFILEHEADER fh;
BITMAPINFOHEADER fi;
fread(&fh, sizeof(fh),1,bmp_input);
fread(&fi, sizeof(fi),1,bmp_input);
int *pixels;
pixels= malloc(sizeof(fh.bfSize-54));
fread(pixels, sizeof(pixels),1,bmp_input);
fclose(bmp_input);
printf("bfSize: %d\n", fh.bfSize);
printf("Width: %d\n", fi.biWidth);
printf("Height: %d\n",fi.biHeight);
printf("First pixel data: %d %d %d",*pixels,*pixels+1,*pixels+2);
return 0;
}
And the values that i get are here in the picture:
Header File:bitmap.h
#include <stdint.h>
typedef struct
{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} __attribute__((__packed__)) BITMAPFILEHEADER;
typedef struct
{
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} __attribute__((__packed__)) BITMAPINFOHEADER;
Thanks for your help.
Upvotes: 0
Views: 189
Reputation: 58251
You need to read the data into a byte buffer rather than an int buffer. The colors in a BMP file are stored using 1, 2, 4, 8, 16, 24 or 32 bits per pixel, so you need to extract the red, green and blue components more carefully than you're doing. It looks like your particular bmp uses 24 bits per pixel (because size is roughly three times the width and height). Thus you can read the components as single bytes, with each pixel three bytes long. For bytes, I use uint8_t
from stdint.h
although unsigned char
could be used instead.
The components in 24bpp are stored in the order blue, green, red.
Here's some example code that prints out the colours of every pixel in the image, assuming it's 24 bpp.
It would be better to check the bpp
field of bitmap header to handle the pixel access correctly. Sorry, I don't know what the exact name of the field is in your header, because you don't provide it. More error checking would also be desirable. The code is untested, because I don't have access to your header file.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "bitmap.h"
int main(){
FILE *bmp_input;
bmp_input=fopen("itu.bmp","rb");
BITMAPFILEHEADER fh;
BITMAPINFOHEADER fi;
fread(&fh, sizeof(fh),1,bmp_input);
fread(&fi, sizeof(fi),1,bmp_input);
size_t pix_size = fh.bfSize-54;
uint8_t *pixels = malloc(pix_size);
if (!pixels) return 2;
fclose(bmp_input);
if (fread(pixels, 1, pix_size, bmp_input) != pix_size) return 1;
int row_width = (3 * fe.biWidth + 3) & ~3; // round up to multiple of 4
for (int j = 0; j < fi.biHeight; j++) {
for (int i = 0; i < fi.biWidth; i++) {
int index = row_width * j + 3 * i;
printf("pix[%d,%d]=RGB(%02X, %02X, %02X)\n", i, j, pixels[index+2], pixels[index+1], pixels[index]);
}
}
free(pixels);
return 0;
}
Note that from a software-engineering point of view, reading binary file formats by reading in data directly into a struct invites security and portability problems (for example, you probably implicitly depend on integers being 32 bits, and little-endian, and structs being packed a certain way). But I guess that this is just a learning exercise.
Upvotes: 1