This was all for fun, and I enjoyed researching bitmaps. It's not complete by any means but a 24 bit bmp file is advised for now. You'll need to name the file accordingly and modify the macro BMP_FILE in the header below. As always, if there are other things you think I should do better please point them out. I'd like to know what else I can improve on.
main.c
Code:
#include "bmp.h"
int main()
{
FILE * bmp_rd_file, * bmp_wr_file;
unsigned char * bmp_headers;
if(!(bmp_rd_file = fopen(BMP_FILE, "r+b")) || !(bmp_wr_file = fopen("out.bmp", "w+b")))
bmp_err("main: fopen()");
bmp_headers = get_headers(bmp_rd_file);
if(((bmp_file_h *) bmp_headers)->sig != 0x4d42)
bmp_err("main: This is not a valid bitmap image!");
if(!(fwrite(bmp_headers, 1, BMP_FILE_HDR_SIZ + BMP_INFO_HDR_SIZ, bmp_wr_file)))
bmp_err("main: fwrite()");
fseek(bmp_rd_file, ((bmp_file_h *)bmp_headers)->offset, SEEK_SET);
switch(((bmp_info_h *) (bmp_headers + BMP_FILE_HDR_SIZ))->bpp)
{
case 24:
case 32:
bmp_24_32(bmp_rd_file, bmp_wr_file, bmp_headers);
break;
default:
bmp_err("BPP in bitmap image not supported!");
break;
}
free(bmp_headers);
fclose(bmp_rd_file);
fclose(bmp_wr_file);
return 0;
}
bmp_24.c
Code:
#include "bmp.h"
void bmp_24_32(FILE * bmp_rd_file, FILE * bmp_wr_file, unsigned char * bmp_headers)
{
size_t bmp_rd_total = 0,
bmp_pixel_array_size,
bmp_rd_bytes,
bmp_row_index,
bmp_row_size,
pass = 0;
unsigned char * bmp_temp_ptr,
* bmp_rd_ptr;
color_e color = 0;
bmp_info_h * bmp_info_header = (bmp_info_h *)(bmp_headers + BMP_FILE_HDR_SIZ);
bmp_row_size = (((bmp_info_header->bpp * bmp_info_header->bmp_width) + 31) / 32) * 4;
bmp_pixel_array_size = bmp_row_size * bmp_info_header->bmp_height;
bmp_rd_ptr = malloc(sizeof(unsigned char) * bmp_row_size);
char bmp_secret_bits;
char * bmp_secret = BMP_SECRET;
int done = 0, bmp_secret_size, bmp_secret_index = 0;
bmp_secret_size = strlen(BMP_SECRET);
do
{
bmp_temp_ptr = bmp_rd_ptr;
if(!(bmp_rd_bytes = fread(bmp_rd_ptr, 1, bmp_row_size, bmp_rd_file)))
break;
for(bmp_row_index = 0; bmp_row_index < bmp_rd_bytes; bmp_row_index++)
{
switch(color)
{
case BLUE:
if(!(pass++ % 10))
{
if(--bmp_secret_size > 0)
{
*bmp_temp_ptr = bmp_secret[bmp_secret_index++];
}
}
break;
case GREEN:
break;
case RED:
break;
case ALPHA:
break;
}
bmp_info_header->bpp == 32 ? ++color == 4 ? color = 0 : color : ++color == 3 ? color = 0 : color;
bmp_temp_ptr++;
}
fwrite(bmp_rd_ptr, 1,bmp_rd_bytes, bmp_wr_file);
bmp_rd_total += bmp_rd_bytes;
}while(bmp_rd_total <= bmp_pixel_array_size);
if(errno)
bmp_err(strerror(errno));
while((bmp_rd_bytes = fread(bmp_rd_ptr, 1, BMP_BUF_SIZ, bmp_rd_file)))
fwrite(bmp_rd_ptr, 1, bmp_rd_bytes, bmp_wr_file);
}
geat_headers.c
Code:
#include "bmp.h"
unsigned char * get_headers(FILE * bmp_rd_file)
{
unsigned char * bmp_headers;
int bytes;
bmp_file_h temp_file;
bmp_info_h temp_info;
if(!(bmp_headers = malloc(sizeof(unsigned char) * BMP_FILE_HDR_SIZ + BMP_INFO_HDR_SIZ)))
bmp_err("get_headers: malloc()\n");
if(!(bytes = fread(&temp_file, 1, BMP_FILE_HDR_SIZ, bmp_rd_file)))
bmp_err("get_headers: fread()\n");
if(!(bytes = fread(&temp_info, 1, BMP_INFO_HDR_SIZ, bmp_rd_file)))
bmp_err("get_headers: fread()\n");
memcpy(bmp_headers,&temp_file,BMP_FILE_HDR_SIZ);
memcpy(bmp_headers + BMP_FILE_HDR_SIZ,&temp_info,BMP_INFO_HDR_SIZ);
return bmp_headers;
}
bmp_err.c
Code:
#include "bmp.h"
void bmp_err(char * bmp_err_buff)
{
fprintf(stderr, "%s\n", bmp_err_buff);
exit(EXIT_FAILURE);
}
bmp.h
Code:
#ifndef _BMP_H
#define _BMP_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#define BMP_FILE "bmpfun.bmp"
#define BMP_SECRET \
"O friends, no more these sounds!" \
"Let us sing more cheerful songs," \
"more full of joy!" \
"Joy, bright spark of divinity," \
"Daughter of Elysium," \
"Fire-inspired we tread" \
"Thy sanctuary." \
"Thy magic power re-unites" \
"All that custom has divided," \
"All men become brothers" \
"Under the sway of thy gentle wings." \
"Whoever has created " \
"An abiding friendship," \
"Or has won" \
"A true and loving wife," \
"All who can call at least one soul theirs," \
"Join in our song of praise;" \
"But any who cannot must creep tearfully" \
"Away from our circle." \
"All creatures drink of joy" \
"At nature's breast." \
"Just and unjust" \
"Alike taste of her gift;" \
"She gave us kisses and the fruit of the vine," \
"A tried friend to the end." \
"Even the worm can feel contentment," \
"And the cherub stands before God!" \
"Gladly, like the heavenly bodies" \
"Which He set on their courses" \
"Through the splendor of the firmament;" \
"Thus, brothers, you should run your race," \
"As a hero going to conquest." \
"You millions, I embrace you." \
"This kiss is for all the world!" \
"Brothers, above the starry canopy" \
"There must dwell a loving Father." \
"Do you fall in worship, you millions?" \
"World, do you know your creator?" \
"Seek him in the heavens;" \
"Above the stars must He dwell." \
#define BMP_BUF_SIZ 1024
#define BMP_FILE_HDR_SIZ 14
#define BMP_INFO_HDR_SIZ 40
#define BMP_ERR_BUF_SIZ 64
#pragma pack(1)
typedef enum
{
BLUE,
GREEN,
RED,
ALPHA
} color_e;
typedef struct
{
uint16_t sig;
uint32_t filesize;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
}bmp_file_h;
typedef struct
{
uint32_t hdr_size;
uint32_t bmp_width;
uint32_t bmp_height;
uint16_t planes;
uint16_t bpp;
uint32_t compression;
uint32_t image_size;
uint32_t xppm;
uint32_t yppm;
uint32_t no_colors;
uint32_t no_imp_colors;
}bmp_info_h;
void bmp_err(char *);
unsigned char *get_headers(FILE *);
void bmp_24_32(FILE *, FILE *, unsigned char *);
#endif // _BMP_H