Navigation/Scrolling in between the bmp Image in C - c

I have able to read Bmp Header of Image as per below properties.
Image Bit-depth : 1
Image Attributes : 1
I want to scroll/Navigate in between Black and White Image (Bit Depth 1). Without Closing and reopening it (bmp image).
1) Like if input == f or F , Pixel Data goes one by one Forward Direction
Y0,Y1,Y2,Y3,Y4,....Yn
2) Like if input == r or R, Pixel Data goes one by one Backward Direction
Y123,Y122,Y121,Y120,Y119, ......Y0
3) Also I don't want to read pixels from starting (On Every Read) .
I want to read in between (Vertical Only).
Below is my code .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BitMap {
short Type;
long Size;
short Reserve1;
short Reserve2;
long OffBits;
long biSize;
long biWidth;
long biHeight;
short biPlanes;
short biBitCount;
long biCompression;
long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
long biClrUsed;
long biClrImportant; } Header;
unsigned char DummyValueRead ; unsigned char pixelValue =0 ;
int Horizontal= 0 ,Vertical = 0 ;
long myPalette[2]; long HeaderBytes;
unsigned char bPadding ; long wBytesPerRow ; unsigned char
bAdditionalBitsPerRow ; FILE *BMPFile; void SendPixelValues();
unsigned char input ;
int main( void ) {
BMPFile = fopen ("mul.bmp", "r");
if (BMPFile == NULL)
{
printf("Image Not Found !!!!!!");
return -1;
}
fread(&Header.Type, sizeof(Header.Type), 1, BMPFile);
fread(&Header.Size, sizeof(Header.Size), 1, BMPFile);
fread(&Header.Reserve1, sizeof(Header.Reserve1) , 1, BMPFile);
fread(&Header.Reserve2, sizeof(Header.Reserve2) , 1, BMPFile);
fread(&Header.OffBits, sizeof(Header.OffBits), 1, BMPFile);
fread(&Header.biSize, sizeof(Header.biSize), 1, BMPFile);
fread(&Header.biWidth, sizeof(Header.biWidth), 1, BMPFile);
fread(&Header.biHeight, sizeof(Header.biHeight) , 1, BMPFile);
fread(&Header.biPlanes, sizeof(Header.biClrUsed), 1, BMPFile);
fread(&Header.biBitCount, sizeof(Header.biBitCount), 1, BMPFile);
fread(&Header.biCompression, sizeof(Header.biCompression), 1, BMPFile);
fread(&Header.biSizeImage, sizeof(Header.biSizeImage), 1, BMPFile);
fread(&Header.biXPelsPerMeter, sizeof(Header.biXPelsPerMeter), 1, BMPFile);
fread(&Header.biYPelsPerMeter, sizeof(Header.biYPelsPerMeter), 1, BMPFile);
fread(&Header.biClrUsed, sizeof(Header.biClrUsed), 1, BMPFile);
fread(&Header.biClrImportant, sizeof(Header.biClrImportant), 1, BMPFile);
fseek(BMPFile,Header.OffBits,SEEK_SET) ;
printf("\nType:%hd and Type in %x\n", Header.Type,Header.Type);
printf("Size:%ld\n", Header.Size);
printf("Reserve1:%hd\n", Header.Reserve1);
printf("Reserve2:%hd\n", Header.Reserve2);
printf("OffBits:%ld\n", Header.OffBits);
printf("biSize:%ld\n", Header.biSize);
printf("Width: %ld\n", Header.biWidth);
printf("Height: %ld\n", Header.biHeight);
printf("biPlanes:%hd\n", Header.biPlanes);
printf("biBitCount:%hd\n", Header.biBitCount);
printf("biCompression:%ld\n", Header.biCompression);
printf("biSizeImage:%ld\n", Header.biSizeImage);
printf("biXPelsPerMeter:%ld\n", Header.biXPelsPerMeter);
printf("biYPelsPerMeter:%ld\n", Header.biYPelsPerMeter);
printf("biClrUsed:%ld\n", Header.biClrUsed);
printf("biClrImportant:%ld\n\n", Header.biClrImportant);
wBytesPerRow =Header.biWidth/8;
bAdditionalBitsPerRow = Header.biWidth % 8;
bPadding = (4 - ((wBytesPerRow + (bAdditionalBitsPerRow?1:0) ) % 4 ) ) %4;
HeaderBytes = Header.biWidth/8 ;
for(Vertical = 0 ; Vertical < Header.biHeight ; Vertical ++)
{
printf("Sr. No. %d \n",Vertical) ;
scanf("%c",&input) ;
if(input =='r' || input =='R' ) // Reverse Direction
{
// fseek(BMPFile,((4*968) + 3), SEEK_SET );
SendPixelValues() ;
}
if(input =='f' || input =='F' ) // Forward Direction
SendPixelValues() ;
printf("\n") ;
}
fclose(BMPFile);
return 0;
}
unsigned int bAdditionalBitsPerRowCount =
0,bPaddingCount=0; void SendPixelValues() {
for(Horizontal = 0 ; Horizontal < HeaderBytes ; Horizontal++)
{
fread(&pixelValue, sizeof(pixelValue), 1, BMPFile);
printf("0x%x ",pixelValue) ;
}
if(bAdditionalBitsPerRow > 0)
{
fread(&DummyValueRead , sizeof(DummyValueRead ), 1, BMPFile);
bAdditionalBitsPerRow++;
printf("bAdditionalBitsPerRowCount %d",bAdditionalBitsPerRowCount);
}
for(Horizontal = 0 ; Horizontal < bPadding; Horizontal++)
{
fread(&DummyValueRead , sizeof(DummyValueRead ), 1, BMPFile);
bPaddingCount++;
}
printf("bPaddingCount = %d",bPaddingCount) ;
}
Thanks
Karan

1-bit bitmap format has 8 bytes for its palette, you have to read those 8 bytes before reading the pixels.
There are 8 pixels packed in to one byte. You have to separate the bits and write them accordingly. Bitmap can have width padding, you have to calculate the padding for the input file as well as output file.
Make sure to read/write the file in binary (it matters in Windows).
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(push, 1)
struct BITMAPFILEHEADER {
short bfType;
int bfSize;
short bfReserved1;
short bfReserved2;
int bfOffBits;
};
struct BITMAPINFOHEADER {
int biSize;
int biWidth;
int biHeight;
short biPlanes;
short biBitCount;
int biCompression;
int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
int biClrUsed;
int biClrImportant;
};
#pragma pack(pop)
int main(void)
{
//set X and Y offset:
int x0 = 10;
int y0 = 10;
if(sizeof(short) != 2 ||
sizeof(int) != 4 ||
sizeof(struct BITMAPFILEHEADER) != 14 ||
sizeof(struct BITMAPINFOHEADER) != 40)
{
printf("Error, wrong structure size...");
return -1;
}
FILE *fin = fopen("mul.bmp", "rb");
FILE *fout = fopen("output.bmp", "wb");
if(fin == NULL)
{
printf("Image Not Found !!!!!!");
return -1;
}
struct BITMAPFILEHEADER header;
struct BITMAPINFOHEADER info;
fread(&header, sizeof(header), 1, fin);
fread(&info, sizeof(info), 1, fin);
if (info.biBitCount != 1)
{
printf("Error, not 1-bit bitmap\n");
return -1;
}
int old_width = info.biWidth;
int old_height = info.biHeight;
int bitcount = info.biBitCount;
int width_in_bytes = ((old_width * bitcount + 31) / 32) * 4;
char palette[8];
fread(palette, 1, sizeof(palette), fin);
int new_width = old_width - x0;
int new_height = old_height - y0;
//convert to 24-bit bitmap for output file
info.biBitCount = 24;
info.biWidth = new_width;
info.biHeight = new_height;
info.biSizeImage = ((info.biHeight * bitcount + 31) / 32) * info.biWidth;
header.bfSize = 54 + info.biSizeImage;
header.bfOffBits = 54;
fwrite(&header, 1, sizeof(header), fout);
fwrite(&info, 1, sizeof(info), fout);
char *bytes_read = malloc(width_in_bytes);
char black[3] = { 0 };
char white[3] = { 255,255,255 };
for(int y = 0; y < old_height; y++)
{
fread(bytes_read, 1, width_in_bytes, fin);
int width_index = 0;
for(int i = 0; i < width_in_bytes; i++)
{
//8 pixels are packed in to 1 byte
//separate the bits, write them as bytes in 24-bit format
for(int j = 0; j < 8; j++)
{
width_index = i * 8 + j;
if(width_index < x0) continue;
if(width_index - x0 >= new_width) break;
int pixel = (bytes_read[i] & (1 << (8 - j)));
if(pixel)
fwrite(white, 1, 3, fout);
else
fwrite(black, 1, 3, fout);
}
}
//add padding to output file
int m = width_index % 4;
if(m)
fwrite(black, 1, m, fout);
}
fclose(fin);
fclose(fout);
return 0;
}

Related

.BMP files in C - DIB header returns image size 0 even though the BMP header returns the file size

I'm trying to flip a BMP image in C.
I ran into a problem where when I try to read the BMP header everything is alright and the values are correct, but when I try to read the DIB header I get all of the values right except for the image size (raw bitmap data). I get a zero, which is really weird considering I got the file size in the BMP header. I tried debugging the code and looking up the problem online but that didn't help much.
This is my code:
#include <stdlib.h>
typedef unsigned int int32;
typedef unsigned short int int16;
typedef unsigned char char8;
struct BITMAP_header {
char name[2]; // BM
int32 size;
int garbage; // ?
int32 image_offset; //offset from where the image starts in the file
};
struct DIB_header {
int32 header_size;
int32 width;
int32 height;
int16 colorplanes;
int16 bitsperpixel;
int32 compression;
int32 image_size;
int32 temp[4];
};
struct RGB
{
char8 blue;
char8 green;
char8 red;
};
struct Image {
struct RGB** rgb;
int height;
int width;
};
struct Image readImage(FILE *fp, int height, int width) {
struct Image pic;
pic.rgb = (struct RGB**)malloc(height * sizeof(void*)); // pointer to a row of rgb data (pixels)
pic.height = height;
pic.width = width;
for (int i = height-1; i >=0 ; i--)
{
pic.rgb[i] = (struct RGB*)malloc(width * sizeof(struct RGB)); // allocating a row of pixels
fread(pic.rgb[i], width, sizeof(struct RGB), fp);
}
return pic;
}
void freeImage(struct Image pic) {
for (int i = pic.height -1; i>= 0; i--)
{
free(pic.rgb[i]);
}
free(pic.rgb);
}
void createImage(struct BITMAP_header header, struct DIB_header dibheader, struct Image pic) {
FILE* fpw = fopen("new.bmp", "w");
if (fpw == NULL) {
return 1;
}
fwrite(header.name, 2, 1, fpw);
fwrite(&header.size, 3 * sizeof(int), 1, fpw);
fwrite(&dibheader, sizeof(struct DIB_header), 1, fpw);
int count = 0;
for (int i = pic.height - 1; i >= 0; i--) {
fwrite(pic.rgb[count], pic.width, sizeof(struct RGB), fpw);
count++;
}
fclose(fpw);
}
int openbmpfile() {
FILE* fp = fopen("C:\\Users\\User\\Downloads\\MARBLES.BMP", "rb"); // read binary
if (fp == NULL) {
return 1;
}
struct BITMAP_header header;
struct DIB_header dibheader;
fread(header.name, 2, 1, fp); //BM
fread(&header.size, 3 * sizeof(int), 1, fp); // 12 bytes
printf("First two characters: %c%c\n", header.name[0], header.name[1]);
if ((header.name[0] != 'B') || (header.name[1] != 'M')) {
fclose(fp);
return 1;
}
printf("Size: %d\n", header.size);
printf("Offset: %d\n", header.image_offset);
fread(&dibheader.header_size, sizeof(struct DIB_header) , 1, fp);
printf("Header size: %d\nWidth: %d\nHeight: %d\nColor planes: %d\nBits per pixel: %d\nCompression: %d\nImage size: %d\n",
dibheader.header_size, dibheader.width, dibheader.height, dibheader.colorplanes, dibheader.bitsperpixel,
dibheader.compression, dibheader.image_size);
if ((dibheader.header_size != 40) || (dibheader.compression != 0) || (dibheader.bitsperpixel != 24)) {
fclose(fp);
return 1;
}
fseek(fp, header.image_offset, SEEK_SET);
struct Image image = readImage(fp, dibheader.height, dibheader.width);
createImage(header, dibheader, image);
fclose(fp);
freeImage(image);
return 0;
}
int main() {
openbmpfile();
}
I also tried writing the size manually by decreasing the header size by the file size but it didn't work.
thanks in advance!
The format expect the structure size to be 14 and 40 for BITMAP_header and DIB_header. But the compiler aligns the structure and the size will be different. You have to use compiler specific flags to disable structure alignment (it's unclear which compiler you use). It's the same problem with RGB structure.
There is also endian-ness dependence, and the fact that bitmap doesn't store pixels in RGB format, it flips the bytes.
typedef unsigned int int32;
This will hide unsigned as signed. Some of the values in the structure are supposed to be signed. For example, height could be negative, indicating that it's supposed to be flipped.
You can read the integers one by one, using
void readint(FILE *f, int *val, int size)
{
unsigned char buf[4];
fread(buf, size, 1, f);
*val = 0;
for (int i = size - 1; i >= 0; i--)
*val += (buf[i] << (8 * i));
}
void writeint(FILE* f, int val, int size)
{
unsigned char buf[4];
for (int i = size - 1; i >= 0; i--)
buf[i] = (val >> 8 * i) & 0xff;
fwrite(buf, size, 1, f);
}
Then you read a 24-bit bitmap as follows:
fread(header.name, 2, 1, fp); //BM
readint(fp, &header.size, 4);
readint(fp, &header.garbage, 4);
readint(fp, &header.image_offset, 4);
readint(fp, &dibheader.header_size, 4);
readint(fp, &dibheader.width, 4);
readint(fp, &dibheader.height, 4);
readint(fp, &dibheader.colorplanes, 2);
readint(fp, &dibheader.bitsperpixel, 2);
readint(fp, &dibheader.compression, 4);
readint(fp, &dibheader.image_size, 4);
readint(fp, &dibheader.temp[0], 4);
readint(fp, &dibheader.temp[1], 4);
readint(fp, &dibheader.temp[2], 4);
readint(fp, &dibheader.temp[3], 4);
char *buf = malloc(dibheader.image_size);
if (!buf)
return 0;
fread(buf, 1, dibheader.image_size, fp);
There are other issues you have to consider, for example width alignment of bitmap, etc. You want to start with a 24-bit bitmap whose width is multiple of 4.
To write the bitmap, use the binary flag, write in the same order
FILE* fout = fopen("new.bmp", "wb");
if (fout == NULL) return 0;
fwrite(header.name, 1, 2, fout);
writeint(fout, header.size, 4);
writeint(fout, header.reserved, 4);
writeint(fout, header.image_offset, 4);
writeint(fout, info.header_size, 4);
writeint(fout, info.width, 4);
writeint(fout, info.height, 4);
writeint(fout, info.colorplanes, 2);
writeint(fout, info.bitsperpixel, 2);
writeint(fout, info.compression, 4);
writeint(fout, info.image_size, 4);
writeint(fout, info.temp[0], 4);
writeint(fout, info.temp[1], 4);
writeint(fout, info.temp[2], 4);
writeint(fout, info.temp[3], 4);
fwrite(buf, 1, info.image_size, fout);

Sobel Filter in C without structs and with 1D arrays,

I have the following sobel filter code that runs correctly.
I want to transform it in code with 1D arrays and without structs. My attempt runs but the output image is not the right one...
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "Image.h"
RGBQUAD image[2048][2048]; // Image as input
int main(int argc, char *argv[])
{
char *filename = 0;
FILE *fp;
FILE *wp;
int width, height;
int i, j, x, y, T;
BitmapFileHeader bmfh;
BitmapInfoHeader bmih;
unsigned char ee_image[2048][2048];
// Reading inputs: bayer image and threshold
if (argc == 3){
filename = argv[1];
T = atoi(argv[2]);
} else{
printf("Give a bmp image and a threshold as input\n");
exit(0);
}
// Opening the file: using "rb" mode to read this *binary* file
printf("Opening filename: %s\n", filename);
fp = fopen(filename, "rb");
// Reading the file header and any following bitmap information...
fread(&bmfh, sizeof(BitmapFileHeader), 1, fp);
fread(&bmih, sizeof(BitmapInfoHeader), 1, fp);
printf("Header Info\n");
printf("--------------------\n");
printf("Size:%i\n", bmfh.bfSize);
printf("Offset:%i\n", bmfh.bfOffBits);
printf("--------------------\n");
printf("Size:%i\n", bmih.biSize);
printf("biWidth:%i\n", bmih.biWidth);
printf("biHeight:%i\n", bmih.biHeight);
printf("biPlanes:%i\n", bmih.biPlanes);
printf("biBitCount:%i\n", bmih.biBitCount);
printf("biCompression:%i\n", bmih.biCompression);
printf("biSizeImage:%i\n", bmih.biSizeImage);
printf("biXPelsPerMeter:%i\n", bmih.biXPelsPerMeter);
printf("biYPelsPerMeter:%i\n", bmih.biYPelsPerMeter);
printf("biClrUsed:%i\n", bmih.biClrUsed);
printf("biClrImportant:%i\n", bmih.biClrImportant);
printf("--------------------\n");
// Reading the pixels of input image
width = bmih.biWidth; if (width%4 != 0) width += (4-width%4);
height = bmih.biHeight;
for (y=0; y<height; y++)
for (x=0; x<width; x++){
image[x][y].rgbBlue = fgetc(fp);
image[x][y].rgbGreen = fgetc(fp);
image[x][y].rgbRed = fgetc(fp);
}
fclose(fp);
// Converting from RGB to Grayscale
int gray_image[width][height];
memset(gray_image, 0, width*height*sizeof(int));
for (y=0; y<height; y++)
for (x=0; x<width; x++){
gray_image[x][y] = 0.2989*image[x][y].rgbRed + 0.5870*image[x][y].rgbGreen + 0.1140*image[x][y].rgbBlue;
}
// mask for x direction
double S1[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
// mask for y direction
double S2[3][3] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
// Scanning the image
for (x=1; x<width-1; x++)
for (y=1; y<height-1; y++){
double Gx = S1[0][0]*gray_image[x-1][y-1] + S1[0][1]*gray_image[x-1][y] + S1[0][2]*gray_image[x-1][y+1] +
S1[1][0]*gray_image[x][y-1] + S1[1][1]*gray_image[x][y] + S1[1][2]*gray_image[x][y+1] +
S1[2][0]*gray_image[x+1][y-1] + S1[2][1]*gray_image[x+1][y] + S1[2][2]*gray_image[x+1][y+1];
double Gy = S2[0][0]*gray_image[x-1][y-1] + S2[0][1]*gray_image[x-1][y] + S2[0][2]*gray_image[x-1][y+1] +
S2[1][0]*gray_image[x][y-1] + S2[1][1]*gray_image[x][y] + S2[1][2]*gray_image[x][y+1] +
S2[2][0]*gray_image[x+1][y-1] + S2[2][1]*gray_image[x+1][y] + S2[2][2]*gray_image[x+1][y+1];
double e = sqrt(Gx*Gx + Gy*Gy);
// Thresholding
if (e <= T) ee_image[x][y] = 0;
if (e > T) ee_image[x][y] = 255;
} // End of image scanning
// Calculating the border pixels with replication
for (y=1; y<height-1; y++){
ee_image[0][y] = ee_image[1][y];
ee_image[width-1][y] = ee_image[width-2][y];
}
for (x=0; x<width; x++){
ee_image[x][0] = ee_image[x][1];
ee_image[x][height-1] = ee_image[x][height-2];
}
printf("The edges of the image have been detected with Sobel and a Threshold: %d\n", T);
// Constructing output image name
char dst_name[80];
// Converting input threshold to string
char str_T[3];
sprintf(str_T, "%d", T);
strcpy(dst_name, "Sobel_");
strcat(dst_name, str_T);
strcat(dst_name, ".bmp");
// Writing new image
wp = fopen(dst_name, "wb");
fwrite(&bmfh, 1, sizeof(BitmapFileHeader), wp);
fwrite(&bmih, 1, sizeof(BitmapInfoHeader), wp);
for (y=0; y<height; y++)
for (x=0; x<width; x++){
fputc(ee_image[x][y], wp);
fputc(ee_image[x][y], wp);
fputc(ee_image[x][y], wp);
}
fclose(wp);
}
My Code attempt is...
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "Image.h"
image[2048*2048]; // Image as input
int main(int argc, char *argv[])
{
char *filename = 0;
FILE *fp;
FILE *wp;
int width, height;
int i, j, x, y, T;
BitmapFileHeader bmfh;
BitmapInfoHeader bmih;
unsigned char ee_image[2048*2048];
// Reading inputs: bayer image and threshold
if (argc == 3){
filename = argv[1];
T = atoi(argv[2]);
} else{
printf("Give a bmp image and a threshold as input\n");
exit(0);
}
// Opening the file: using "rb" mode to read this *binary* file
printf("Opening filename: %s\n", filename);
fp = fopen(filename, "rb");
// Reading the file header and any following bitmap information...
fread(&bmfh, sizeof(BitmapFileHeader), 1, fp);
fread(&bmih, sizeof(BitmapInfoHeader), 1, fp);
printf("Header Info\n");
printf("--------------------\n");
printf("Size:%i\n", bmfh.bfSize);
printf("Offset:%i\n", bmfh.bfOffBits);
printf("--------------------\n");
printf("Size:%i\n", bmih.biSize);
printf("biWidth:%i\n", bmih.biWidth);
printf("biHeight:%i\n", bmih.biHeight);
printf("biPlanes:%i\n", bmih.biPlanes);
printf("biBitCount:%i\n", bmih.biBitCount);
printf("biCompression:%i\n", bmih.biCompression);
printf("biSizeImage:%i\n", bmih.biSizeImage);
printf("biXPelsPerMeter:%i\n", bmih.biXPelsPerMeter);
printf("biYPelsPerMeter:%i\n", bmih.biYPelsPerMeter);
printf("biClrUsed:%i\n", bmih.biClrUsed);
printf("biClrImportant:%i\n", bmih.biClrImportant);
printf("--------------------\n");
// Reading the pixels of input image
width = bmih.biWidth; if (width%4 != 0) width += (4-width%4);
height = bmih.biHeight;
for (y=0; y<height; y++)
for (x=0; x<width; x++){
image[x + y * width] = fgetc(fp);
image[x + y * width] = fgetc(fp);
image[x + y * width] = fgetc(fp);
}
fclose(fp);
// Converting from RGB to Grayscale
int gray_image[width*height];
memset(gray_image, 0, width*height*sizeof(int));
for (y=0; y<height; y++)
for (x=0; x<width; x++){
gray_image[x + y * width] = 0.2989*image[x + y * width] + 0.5870*image[x + y * width] + 0.1140*image[x + y * width];
}
// Sobel kernels
// mask for x direction
double S1[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
// mask for y direction
double S2[3][3] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
// Scanning the image
for (x=1; x<width-1; x++)
for (y=1; y<height-1; y++){
double Gx = S1[0][0]*gray_image[(x-1)*(y-1)] + S1[0][1]*gray_image[(x-1)*(y)] + S1[0][2]*gray_image[(x-1)*(y+1)] +
S1[1][0]*gray_image[x*(y-1)] + S1[1][1]*gray_image[x + y * width] + S1[1][2]*gray_image[x*(y+1)] +
S1[2][0]*gray_image[(x+1)*(y-1)] + S1[2][1]*gray_image[(x+1)*y] + S1[2][2]*gray_image[(x+1)*(y+1)];
double Gy = S2[0][0]*gray_image[(x-1)*(y-1)] + S2[0][1]*gray_image[(x-1)*(y)] + S2[0][2]*gray_image[(x-1)*(y+1)] +
S2[1][0]*gray_image[x*(y-1)] + S2[1][1]*gray_image[x + y * width] + S2[1][2]*gray_image[x*(y+1)] +
S2[2][0]*gray_image[(x+1)*(y-1)] + S2[2][1]*gray_image[(x+1)*y] + S2[2][2]*gray_image[(x+1)*(y+1)];
double e = sqrt(Gx*Gx + Gy*Gy);
// Thresholding
if (e <= T) ee_image[x + y * width] = 0;
if (e > T) ee_image[x + y * width] = 255;
} // End of image scanning
// Calculating the border pixels with replication
for (y=1; y<height-1; y++){
ee_image[0*y] = ee_image[1*y];
ee_image[(width-1)*y] = ee_image[(width-2)*y];
}
for (x=0; x<width; x++){
ee_image[x*0] = ee_image[x*1];
ee_image[x*(height-1)] = ee_image[x*(height-2)];
}
printf("The edges of the image have been detected with Sobel and a Threshold: %d\n", T);
// Constructing output image name
char dst_name[80];
// Converting input threshold to string
char str_T[3];
sprintf(str_T, "%d", T);
strcpy(dst_name, "Sobel_");
strcat(dst_name, str_T);
strcat(dst_name, ".bmp");
// Writing new image
wp = fopen(dst_name, "wb");
fwrite(&bmfh, 1, sizeof(BitmapFileHeader), wp);
fwrite(&bmih, 1, sizeof(BitmapInfoHeader), wp);
for (y=0; y<height; y++)
for (x=0; x<width; x++){
fputc(ee_image[x + y * width], wp);
fputc(ee_image[x + y * width], wp);
fputc(ee_image[x + y * width], wp);}
fclose(wp);
}
I have understand that sonething is wrong when i reaf the original image...
Any help would be precious.
Regards
"Image.h"
typedef struct tagBitmapFileHeader{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} __attribute__((packed)) BitmapFileHeader;
typedef struct tagBitmapInfoHeader{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} __attribute__((packed)) BitmapInfoHeader;
typedef struct{ /**** Colormap entry structure ****/
unsigned char rgbBlue; /* Blue value */
unsigned char rgbGreen; /* Green value */
unsigned char rgbRed; /* Red value */
unsigned char rgbReserved; /* Reserved */
} RGBQUAD;
typedef struct{ /**** Colormap entry structure ****/
unsigned char yccY; /* Y value */
unsigned char yccCb; /* Cb value */
unsigned char yccCr; /* Cr value */
unsigned char yccReserved; /* Reserved */
} YCCQUAD;

converting 24bpp bmp colour image to 8bpp grayscale bmp image in c

I am trying to convert 24bpp BMP color image to 8bpp grayscale BMP image. I have done something but i am not getting 100% correct output.
I have converted 24bpp to 8bpp. but in result image colour table is also being considered as pixel data. I have tried setting offset byte in header but problem still persists.
#include <stdio.h>
int main()
{
FILE* fIn = fopen("lena_colored_256.bmp","rb");
FILE* fOut = fopen("lena_gray.bmp", "w+");
int i, j, y;
unsigned char byte[54];
unsigned char colorTable[1024];
if (fIn == NULL)// check if the input file has not been opened
{
printf("File does not exist.\n");
}
for (i = 0; i < 54; i++)//read the 54 byte header from fIn
{
byte[i] = getc(fIn);
}
byte[28] = (unsigned char)8; // write code to modify bitDepth to 8
byte[11] = (unsigned char)04;
//write code to add colorTable
for (i = 0; i < 256; i++)
{
colorTable[i * 4 + 0] = i;
colorTable[i * 4 + 1] = i;
colorTable[i * 4 + 2] = i;
colorTable[i * 4 + 3] = i;
}
for (i = 0; i < 54; i++)
{
putc(byte[i], fOut);
}
for (i = 0; i < 1024; i++)
{
putc(colorTable[i], fOut);
}
// extract image height, width and bitDepth from imageHeader
int *height = (int)& byte[18];
int *width = (int)& byte[22];
int *bitDepth = (int)& byte[28];
printf("bitDepth : %d\n", *bitDepth);
printf("width: %d\n", *width);
printf("height: %d\n", *height);
int size = (*height) * (*width)*3; //calculate image size
unsigned char* buffer;
buffer = (unsigned char*)malloc(sizeof(int) * size);
for (i = 0; i < size; i=i+3) //RGB to gray
{
buffer[i+2] = getc(fIn);//blue
buffer[i+1] = getc(fIn);//green
buffer[i+0] = getc(fIn);//red
y = (buffer[i+0] * 0.33) + (buffer[i+1] * 0.33) + (buffer[i+2] * 0.33);
putc(y, fOut);
}
fclose(fOut);
fclose(fIn);
return 0;
}
Colour table data is also being considered as pixel data by image.
i have checked my colour table data entering into BMP file. I have printed out file pointer location, after entering at 94th byte it is increasing by 2 byte instead of 1 byte, this is happening total 4 times and other 1020 time file pointer is increasing by 1 byte. Any explanation regarding this?
Changing 24-bit to 8-bit bitmap is not as simple as changing the bitcount in header file. 24-bit bitmap doesn't have a color table. You have to build a color table for the 8-bit. Fortunately this is relatively easy for gray scale images.
Several values in bitmap header file need to be modified.
Then change the 24-bit to gray scale, and change to 8-bit bitmap. See bitmap file format for additional information. Also read about "padding" where the width of bitmap in bytes should always be a multiple of 4.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#pragma pack(push, 2)
typedef struct {
int16_t bfType;
int32_t bfSize;
int16_t bfReserved1;
int16_t bfReserved2;
int32_t bfOffBits;
} BITMAPFILEHEADER;
typedef struct {
int32_t biSize;
int32_t biWidth;
int32_t biHeight;
int16_t biPlanes;
int16_t biBitCount;
int32_t biCompression;
int32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
int32_t biClrUsed;
int32_t biClrImportant;
} BITMAPINFOHEADER;
#pragma pack(pop)
int main()
{
FILE* fin = fopen("fin.bmp", "rb");
FILE* fout = fopen("fout.bmp", "wb");
if(!fin) { printf("fin error\n"); goto error; }
if(!fout) { printf("fout error\n"); goto error; }
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
fread(&bf, sizeof bf, 1, fin);
fread(&bi, sizeof bi, 1, fin);
if(sizeof bf != 14) { printf("Wrong pragma pack\n"); goto error; }
if(sizeof bi != 40) { printf("Wrong pragma pack\n"); goto error; }
if(bf.bfType != 0x4D42) { printf("not bmp, or not LE system\n"); goto error; }
if(bi.biSize != 40) { printf("Can't handle this bitmap format\n"); goto error; }
if(bi.biBitCount != 24) { printf("not 24-bit\n"); goto error; }
int height = bi.biHeight;
if(height < 0) height = -height;
//width in bytes:
int src_wb = ((bi.biWidth * 24 + 31) / 32) * 4;
int dst_wb = ((bi.biWidth * 8 + 31) / 32) * 4;
int src_size = src_wb * height;
int dst_size = dst_wb * height;
//allocate for source and destination
uint8_t *src = malloc(src_size);
uint8_t *dst = malloc(dst_size);
//read pixels
fread(src, 1, src_size, fin);
//make gray scale color-table
uint8_t clr[1024] = { 0 };
for(int i = 0; i < 256; i++)
clr[i * 4 + 0] = clr[i * 4 + 1] = clr[i * 4 + 2] = (uint8_t)i;
for(int y = height - 1; y >= 0; y--)
{
for(int x = 0; x < bi.biWidth; x++)
{
uint8_t blu = src[y * src_wb + x * 3 + 0];
uint8_t grn = src[y * src_wb + x * 3 + 1];
uint8_t red = src[y * src_wb + x * 3 + 2];
uint8_t gry = (uint8_t)(.33 * red + .34 * grn + .33 * blu);
dst[y * dst_wb + x] = gry; //this will match the index in color-table
}
}
//modify bitmap headers
bf.bfSize = 54 + 1024 + dst_size;
bi.biBitCount = 8;
bi.biSizeImage = dst_size;
fwrite(&bf, sizeof bf, 1, fout);
fwrite(&bi, sizeof bi, 1, fout);
fwrite(clr, 1, 1024, fout);
fwrite(dst, 1, dst_size, fout);
free(src);
free(dst);
error:
fclose(fout);
fclose(fin);
return 0;
}
FILE* fOut = fopen("lena_gray.bmp", "w+");//ERROR
FILE* fOut = fopen("lena_gray.bmp", "wb");//TRUE

Create simple bitmap in C (without external libraries)

For learning purposes, I want to create a single 2x2 bitmap image using C programming language with no external libraries (such as SDL).
I've read that I need to create a header for the bitmap file but failed to understand how to implement it in code and why does the bmp header have those parameters. I can't find any clear tutorial on how I could do it using C.
Could you provide me some guidance on how to implement this by a simple documented example? I'm using Linux.
why does the bmp header have those parameters
The pixel data in bitmap is essentially a one-dimensional array of bytes. It's impossible to interpret this data without header information which reveals width, height, bit-count and other information about the bitmap.
There are different types of bitmaps, including different palette format and non-palette 16, 24, or 32 bits, and different types within some of these groups.
The header also includes other information which are there for historical reasons. This has little value for learning C. You just have to accept it.
The header information is in two structures BITMAPFILEHEADER and BITMAPINFO It's a little more complicated because the structures are expected to be packed.
The pixel data depends on the bitmap format. There is not a single bitmap format as mentioned earlier. The example below shows a 24-bit bitmap.
Other oddities is that the width of each row should always be multiple of 4 bytes. This called padding. Also the bitmap rows start at the bottom, not at the top. This is explained in other resources
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void)
{
//width, height, and bitcount are the key factors:
int32_t width = 2;
int32_t height = 2;
uint16_t bitcount = 24;//<- 24-bit bitmap
//take padding in to account
int width_in_bytes = ((width * bitcount + 31) / 32) * 4;
//total image size in bytes, not including header
uint32_t imagesize = width_in_bytes * height;
//this value is always 40, it's the sizeof(BITMAPINFOHEADER)
const uint32_t biSize = 40;
//bitmap bits start after headerfile,
//this is sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
const uint32_t bfOffBits = 54;
//total file size:
uint32_t filesize = 54 + imagesize;
//number of planes is usually 1
const uint16_t biPlanes = 1;
//create header:
//copy to buffer instead of BITMAPFILEHEADER and BITMAPINFOHEADER
//to avoid problems with structure packing
unsigned char header[54] = { 0 };
memcpy(header, "BM", 2);
memcpy(header + 2 , &filesize, 4);
memcpy(header + 10, &bfOffBits, 4);
memcpy(header + 14, &biSize, 4);
memcpy(header + 18, &width, 4);
memcpy(header + 22, &height, 4);
memcpy(header + 26, &biPlanes, 2);
memcpy(header + 28, &bitcount, 2);
memcpy(header + 34, &imagesize, 4);
//prepare pixel data:
unsigned char* buf = malloc(imagesize);
for(int row = height - 1; row >= 0; row--)
{
for(int col = 0; col < width; col++)
{
buf[row * width_in_bytes + col * 3 + 0] = 255;//blue
buf[row * width_in_bytes + col * 3 + 1] = 0;//green
buf[row * width_in_bytes + col * 3 + 2] = 0;//red
}
}
FILE *fout = fopen("test.bmp", "wb");
fwrite(header, 1, 54, fout);
fwrite((char*)buf, 1, imagesize, fout);
fclose(fout);
free(buf);
return 0;
}
You can rewrite this code using structures. In this code structure is packed with #pragma pack(push, 1) which is compiler dependent. Use this version if #pragma directive works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#pragma pack(push, 1)
struct my_BITMAPFILEHEADER {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
struct my_BITMAPINFOHEADER {
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;
};
#pragma pack(pop)
int main(void)
{
if(sizeof(struct my_BITMAPFILEHEADER) != 14 &&
sizeof(struct my_BITMAPINFOHEADER) != 40)
{
printf("bitmap structures not packed properly\n");
return 0;
}
//only width and height can be changed in this code:
int width = 2;
int height = 2;
int bitcount = 24;//<- 24-bit bitmap
int width_in_bytes = ((width * bitcount + 31) / 32) * 4; //for padding
uint32_t imagesize = width_in_bytes * height; //total image size
struct my_BITMAPFILEHEADER filehdr = { 0 };
struct my_BITMAPINFOHEADER infohdr = { 0 };
memcpy(&filehdr, "BM", 2);//bitmap signature
filehdr.bfSize = 54 + imagesize;//total file size
filehdr.bfOffBits = 54; //sizeof(filehdr) + sizeof(infohdr)
infohdr.biSize = 40; //sizeof(infohdr)
infohdr.biPlanes = 1; //number of planes is usually 1
infohdr.biWidth = width;
infohdr.biHeight = height;
infohdr.biBitCount = bitcount;
infohdr.biSizeImage = imagesize;
//prepare pixel data:
unsigned char* buf = malloc(imagesize);
for(int row = height - 1; row >= 0; row--)
{
for(int col = 0; col < width; col++)
{
buf[row * width_in_bytes + col * 3 + 0] = 255;//blue
buf[row * width_in_bytes + col * 3 + 1] = 0;//red
buf[row * width_in_bytes + col * 3 + 2] = 0;//green
}
}
FILE *fout = fopen("test.bmp", "wb");
fwrite(&filehdr, sizeof(filehdr), 1, fout);
fwrite(&infohdr, sizeof(infohdr), 1, fout);
fwrite((char*)buf, 1, imagesize, fout);
fclose(fout);
free(buf);
return 0;
}
The first version used unsigned char header[54] to achieve the same thing. See the size of each data and its relative position in memory. The structure is 14 bytes long. bfType starts at 0, and is 2 bytes long (16 bits). bfSize starts at position 2, and is 4 bytes long...
struct my_BITMAPFILEHEADER {
uint16_t bfType; //starts at 0, 2 bytes long
uint32_t bfSize; //starts at 2, 4 bytes long
uint16_t bfReserved1; //starts at 6, 2 bytes long
uint16_t bfReserved2; //starts at 8, 2 bytes long
uint32_t bfOffBits; //starts at 10, 4 bytes long
};
Then you have the next structure which is 40 bytes long:
struct my_BITMAPINFOHEADER {
uint32_t biSize;//starts at 14
int32_t biWidth;//starts at 18
int32_t biHeight;//starts at 22
uint16_t biPlanes;//starts at 26
uint16_t biBitCount;//starts at 28
uint32_t biCompression;//starts at 30
uint32_t biSizeImage;//starts at 34
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
biSize starts at 0. But the previous structure was 14 bytes. So biSzie starts at 14. This should reveal the mystery of the numbers used in previous version to copy integers to header
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include <stdint.h>
long asciiToBinary(int n);
long asciiToBinary(int n) {
int remainder;
long binary = 0, i = 1;
while(n != 0) {
remainder = n%2;
n = n/2;
binary= binary + (remainder*i);
i = i*10;
}
return binary;
}
typedef struct
{ //BITMAPFILEHEADER
char bfType[2];
int bfSize;
short bfReserved1;
short bfReserved2;
int bfOffBits;
//BITMAPINFOHEADER
int biSize;
int biWidth;
int biHeight;
short biPlanes;
short biBitCount;
int biCompression;
int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
int biClrUsed;
int biClrImportant;
} BITMAPINFOHEADER;
typedef struct {
unsigned char blue;
unsigned char green;
unsigned char red;
} PIXEL;
int imageInfo(BITMAPINFOHEADER *img)
{
int offset = 0;
printf("------------------------------------------------------------- BITMAPFILEHEADER\n");
printf("0x%08X (%08d) bfType %8c%c (0x%04X)\n", offset, offset, img->bfType[0], img->bfType[1], *(short *)img->bfType);
offset += sizeof img->bfType;
printf("0x%08X (%08d) bfSize %9d (0x%08X)\n", offset, offset, img->bfSize, img->bfSize);
offset += sizeof img->bfSize;
printf("0x%08X (%08d) bfReserved1 %9hd (0x%04hX)\n", offset, offset, img->bfReserved1, img->bfReserved1);
offset += sizeof img->bfReserved1;
printf("0x%08X (%08d) bfReserved2 %9hd (0x%04hX)\n", offset, offset, img->bfReserved2, img->bfReserved2);
offset += sizeof img->bfReserved2;
printf("0x%08X (%08d) bfOffBits %9d (0x%08X)\n", offset, offset, img->bfOffBits, img->bfOffBits);
printf("------------------------------------------------------------- BITMAPINFOHEADER\n");
offset += sizeof img->bfOffBits;
printf("0x%08X (%08d) biSize %9d (0x%08X)\n", offset, offset, img->biSize, img->biSize);
offset += sizeof img->biSize;
printf("0x%08X (%08d) biWidth %9d (0x%08X)\n", offset, offset, img->biWidth, img->biWidth);
offset += sizeof img->biWidth;
printf("0x%08X (%08d) biHeight %9d (0x%08X)\n", offset, offset, img->biHeight, img->biHeight);
offset += sizeof img->biHeight;
printf("0x%08X (%08d) biPlanes %9d (0x%04hX)\n", offset, offset, img->biPlanes, img->biPlanes);
offset += sizeof img->biPlanes;
printf("0x%08X (%08d) biBitCount %9d (0x%04hX)\n", offset, offset, img->biBitCount, img->biBitCount);
offset += sizeof img->biBitCount;
printf("0x%08X (%08d) biCompression %9d (0x%08X)\n", offset, offset, img->biCompression, img->biCompression);
offset += sizeof img->biCompression;
printf("0x%08X (%08d) biSizeImage %9d (0x%08X)\n", offset, offset, img->biSizeImage, img->biSizeImage);
offset += sizeof img->biSizeImage;
printf("0x%08X (%08d) biXPelsPerMeter %9d (0x%08X)\n", offset, offset, img->biXPelsPerMeter, img->biXPelsPerMeter);
offset += sizeof img->biXPelsPerMeter;
printf("0x%08X (%08d) biYPelsPerMeter %9d (0x%08X)\n", offset, offset, img->biYPelsPerMeter, img->biYPelsPerMeter);
offset += sizeof img->biYPelsPerMeter;
printf("0x%08X (%08d) biClrUsed %9d (0x%08X)\n", offset, offset, img->biClrUsed, img->biClrUsed);
offset += sizeof img->biClrUsed;
printf("0x%08X (%08d) biClrImportant %9d (0x%08X)\n", offset, offset, img->biClrImportant, img->biClrImportant);
return offset;
}
int main(){
uint32_t RGB565ColorTable[] = {
0x7E00000, 0xF8000000, 0x001F0000, 0
};
uint16_t myData[64];
for(int i = 0; i<64; i++)
{
myData[i] = 0x241B; //Random Color
}
FILE *image;
const char filename[] = "full.bmp";
FILE *fichier = fopen(filename, "rb");
FILE *fptr = fopen("tth.bmp","w+");
if(!fichier)
printf ("Erreur a l'ouverture du fichier [%s]\n", filename);
else
{
BITMAPINFOHEADER *img = malloc(sizeof *img);
char fpath[1000],mydata[100];
BITMAPINFOHEADER bih;
int i=0,b[8],g[8],r[8];
double asciiTobinary;
image=fopen("full.bmp","rb");
fseek(image,2,SEEK_SET); //reading the height and width
fread(&bih.biSize,4,1,image);
printf("\n \n Size of the image=%d\n",bih.biSize);
fseek(image,18,SEEK_SET);
fread(&bih.biWidth,4,1,image);
fseek(image,22,SEEK_SET);
fread(&bih.biHeight,4,1,image);
printf("\n \n Width of the image =%d \n Height of the image =%d \n pixel = b | g | r \n \n",bih.biWidth,bih.biHeight);
PIXEL pic[bih.biWidth*bih.biHeight*2],p;
while(!feof(image)){ //reading the pixels rgb values
fread(&p.blue,sizeof(p.blue),1,image);
fread(&p.green,sizeof(p.green),1,image);
fread(&p.red,sizeof(p.red),1,image);
pic[i]=p;
printf(" %d= %u | %u | %u ",i+54,pic[i].blue,pic[i].green,pic[i].red);
i++; }
fclose(image);
if(img)
{
int i, tmp, offset;
printf("\n[%s]\n", filename);
fread(img, sizeof(BITMAPINFOHEADER), 1, fichier);
if(img->bfType[0] == 'B' && img->bfType[1] == 'M')
{
offset = imageInfo(img);
if(img->biBitCount == 1)
{
printf("---------------------------------------------------------------------- RGBQUAD\n");
fread(&tmp, sizeof tmp, 1, fichier);
offset += sizeof img->biClrImportant;
printf("0x%08X (%08d) %9d (0x%08X)\n", offset, offset, tmp, tmp);
fread(&tmp, sizeof tmp, 1, fichier);
offset += sizeof tmp;
printf("0x%08X (%08d) %9d (0x%08X)\n", offset, offset, tmp, tmp);
printf("------------------------------------------------------------------------- BITS\n");
for(i = 0; i < img->biSizeImage / (int)sizeof tmp; i++)
{
char bin[33];
fread(&tmp, sizeof tmp, 1, fichier);
offset += sizeof tmp;
printf("0x%08X (%08d) %8d (0x%08X) (%s)\n", offset, offset, tmp, tmp, itoa(tmp, bin, 2));
}
}
}
free(img);
}
fclose(fichier);
}
if(fptr == NULL) {
printf("Error!");
exit(1);
}
fwrite(&filename, sizeof(filename), 1, fptr);
//fwrite(&myInfoHeader, sizeof(myInfoHeader), 1, fptr);
fwrite(&RGB565ColorTable, sizeof(RGB565ColorTable), 1, fptr);
fwrite(&myData, sizeof(myData), 1, fptr);
fclose(fptr);
return 0;
}

Color changing bmp in c

I have a pixel information array who has the biSizeImage size and contains triplets of the form (blue, green, red) with values ​​between 0 and 255. I must change my bmp color from red, to white, but i have a problem, as can be seen in picture.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
BITMAPFILEHEADER file;
BITMAPINFOHEADER info;
FILE* f=fopen("imagine.bmp","rb");
fread(&file,sizeof(BITMAPFILEHEADER),1,f);
fread(&info,sizeof(BITMAPINFOHEADER),1,f);
RGBQUAD *a=malloc(info.biSizeImage*sizeof(RGBQUAD));
fread(a,sizeof(RGBQUAD),info.biSizeImage,f);
for(int i=0;i<info.biSizeImage;i++)
{
a[i].rgbBlue=255;
a[i].rgbGreen=255;
a[i].rgbRed=255;
}
FILE* f2=fopen("imagine2.bmp","wb");
if(f2==NULL)
printf("Error");
fwrite(&file,sizeof(BITMAPFILEHEADER),1,f2);
fwrite(&info,sizeof(BITMAPINFOHEADER),1,f2);
fwrite(a,sizeof(RGBQUAD),info.biSizeImage,f2);
return 0;
Output
Original image
info.biSizeImage can be zero. Check to make sure it is not zero, or calculate it based on stride. Width, height, and bitcount values are always set.
As noted in comments, 24 bit image has 3 bytes (24 bit) per pixel. RGBQUA is for 32-bit image. You have to iterate through the height, and then width 3 bytes at a time.
int main(void)
{
BITMAPFILEHEADER file;
BITMAPINFOHEADER info;
FILE* f = fopen("imagine.bmp", "rb");
fread(&file, sizeof(BITMAPFILEHEADER), 1, f);
fread(&info, sizeof(BITMAPINFOHEADER), 1, f);
if(info.biBitCount != 24)
return 0;
int stride = ((info.biWidth * info.biBitCount + 31) / 32) * 4;
int size = stride * info.biHeight;
BYTE *a = malloc(stride * info.biHeight);
fread(a, 1, size, f);
for(int y = info.biHeight - 1; y >= 0; y--)
{
for(int x = 0; x < stride; x += 3)
{
int i = y * stride + x;
a[i + 0] = 255;
a[i + 1] = 255;
a[i + 2] = 255;
}
}
FILE* f2 = fopen("imagine2", "wb");
if(f2 == NULL)
printf("Error");
fwrite(&file, sizeof(BITMAPFILEHEADER), 1, f2);
fwrite(&info, sizeof(BITMAPINFOHEADER), 1, f2);
fwrite(a, 1, size, f2);
return 0;
}

Resources