'Reading pattern from file and create a bmp image of that in C
I want to read an text file Using C Language.Here's the file:-
You see there is some pattern in the text content on the file. 0 means nothing. 9 means black. so there is coloring scheme from 0 to 9.
I have to create a bitmap image of this and the color are according to the values in the pattern. You have to adjust it with the 0-256 color scheme. And the final output for this is shown below
Now see the pattern in the content of the text file is opposite to the final output bitmap file (not necessary). The darkness of the colors in bitmap image is according to the values in the pattern of the text content.
Anyone will tell me how I achieve this in C language.
I am able to create a BMP file but not according to the pattern in text file.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char bitmap[1900];
// -- FILE HEADER -- //
// bitmap signature
bitmap[0] = 0x42;
bitmap[1] = 0x4d;
// file size
bitmap[2] = 58; // 40 + 14 + 12
bitmap[3] = 0;
bitmap[4] = 0;
bitmap[5] = 0;
int i=0;
// reserved field (in hex. 00 00 00 00)
for(i = 6; i < 10; i++) bitmap[i] = 0;
// offset of pixel data inside the image
for(i = 10; i < 14; i++) bitmap[i] = 0;
// -- BITMAP HEADER -- //
// header size
bitmap[14] = 40;
for(i = 15; i < 18; i++) bitmap[i] = 0;
// width of the image
bitmap[18] = 4;
for(i = 19; i < 22; i++) bitmap[i] = 0;
// height of the image
bitmap[22] = 1;
for(i = 23; i < 26; i++) bitmap[i] = 0;
// reserved field
bitmap[26] = 1;
bitmap[27] = 0;
// number of bits per pixel
bitmap[28] = 24; // 3 byte
bitmap[29] = 0;
// compression method (no compression here)
for(i = 30; i < 34; i++) bitmap[i] = 0;
// size of pixel data
bitmap[34] = 12; // 12 bits => 4 pixels
bitmap[35] = 0;
bitmap[36] = 0;
bitmap[37] = 0;
// horizontal resolution of the image - pixels per meter (2835)
bitmap[38] = 0;
bitmap[39] = 0;
bitmap[40] = 0b00110000;
bitmap[41] = 0b10110001;
// vertical resolution of the image - pixels per meter (2835)
bitmap[42] = 0;
bitmap[43] = 0;
bitmap[44] = 0b00110000;
bitmap[45] = 0b10110001;
// color pallette information
for(i = 46; i < 50; i++) bitmap[i] = 0;
// number of important colors
for(i = 50; i < 54; i++) bitmap[i] = 0;
// -- PIXEL DATA -- //
for(i = 54; i < 66; i++) bitmap[i] = 255;
FILE *file;
file = fopen("bitmap.bmp", "w+");
for(i = 0; i < 66; i++)
{
fputc(bitmap[i], file);
}
fclose(file);
return 0;
}
Solution 1:[1]
Here is a working code. I do not check some case of error (input file badly formatted, for example). I put some commentaries, though the code itself is not difficult to understand.
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <ctype.h>
#define BMP_ASSERT(condition, message) \
do { \
if (! (condition)) { \
fprintf(stderr, __FILE__ ":%d: %s: Assertion `" #condition \
"` failed.\n\t: %s\n", __LINE__, __func__, message); \
exit(EXIT_FAILURE); \
} \
} while (false)
#define BMP_COLORMAP_SIZE 10
////////////////////////////////////////////////////////////////////////////////
// STRUCTS
typedef struct __attribute__((__packed__))
bmp_color
{
uint8_t r,
g,
b;
uint8_t :8;
} bmp_color_t;
typedef struct __attribute__((__packed__))
bmp_header_infos
{
uint32_t const info_size;
uint32_t width;
uint32_t height;
uint16_t const planes;
uint16_t const bpp;
uint32_t const compression;
uint32_t img_size;
uint32_t const horz_resolution;
uint32_t const vert_resolution;
uint32_t const n_colors;
uint32_t const n_important_colors;
} bmp_header_infos_t;
typedef struct __attribute__((__packed__))
bmp_header
{
/* Header */
char const signature[2];
uint32_t file_size;
uint32_t const :32; // reserved
uint32_t const img_offset;
/* Infos */
bmp_header_infos_t infos;
/* Color map */
bmp_color_t colormap[BMP_COLORMAP_SIZE];
} bmp_header_t;
typedef struct bmp_file_datas
{
size_t width;
size_t height;
/* Bit map */
uint8_t *bitmap;
} bmp_file_datas_t;
////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/* Give a header with the right magic values */
bmp_header_t *
bmp_get_header(void)
{
static bmp_header_t _header = {
{'B', 'M'},
0u,
sizeof(_header),
{ // struct info
sizeof(_header.infos),
0u, 0u, // width, height
1u, // planes
8u, // bpp
0u, // no compression
0u, // img size
0u, 0u, // resolution
BMP_COLORMAP_SIZE,
BMP_COLORMAP_SIZE, // important colors
},
{{0u}}
};
bmp_header_t *header = malloc(sizeof(_header));
size_t i,
color;
assert(header != NULL);
memcpy(header, &_header, sizeof(*header));
// setting the scale of greys
for (i = 0 ; i < BMP_COLORMAP_SIZE ; ++i)
{
color = (i * 255) / BMP_COLORMAP_SIZE;
header->colormap[i] = (bmp_color_t){color, color, color};
}
return header;
}
/* Take all the file content and store it in a buffer */
char *
get_file_content(char const *filename)
{
FILE *file_handler = fopen(filename, "r");
size_t file_len;
char *buff;
BMP_ASSERT(file_handler != NULL, strerror(errno));
fseek(file_handler, 0, SEEK_END);
file_len = ftell(file_handler);
fseek(file_handler, 0, SEEK_SET);
buff = malloc(file_len + 1);
assert(buff != NULL);
fread(buff, file_len, 1, file_handler);
buff[file_len] = '\0';
fclose(file_handler);
return buff;
}
/* Get the greatest multiple of 4 that is >= size */
static inline size_t
multiple_of_four(size_t size)
{
while (size % 4)
++size;
return size;
}
/* Get the informations from buffer: size of line, number of lines */
void
get_file_infos(char *buff, bmp_header_t *header, bmp_file_datas_t *datas)
{
/* width & height */
header->infos.width = strchr(buff, '\n') - buff;
header->infos.height = strlen(buff) / (header->infos.width + 1);
// + 1 for the terminating '\n'
datas->width = multiple_of_four(header->infos.width);
datas->height = header->infos.height;
printf("File size: %u, %u\n", header->infos.width, header->infos.height);
/* image size & bitmap allocation */
header->infos.img_size = datas->width * datas->height;
datas->bitmap = malloc(header->infos.img_size * sizeof(*datas->bitmap));
assert(datas->bitmap != NULL);
header->file_size = header->img_offset + header->infos.img_size;
}
/* Take the informations from the buffer and store them in the bitmap */
void
write_bitmap(char *buff, bmp_file_datas_t *datas)
{
size_t ibuff,
iline = 0,
ibitmap = 0;
for (ibuff = 0 ; buff[ibuff] ; ++ibuff)
{
if (isdigit(buff[ibuff]))
{
datas->bitmap[ibitmap] = BMP_COLORMAP_SIZE - 1 - (buff[ibuff] - '0');
++ibitmap;
}
else if (buff[ibuff] == '\n')
{
++iline;
ibitmap = iline * datas->width;
}
}
}
/* Write the datas in the file: the header and the bitmap */
void
write_in_file(bmp_header_t *header,
bmp_file_datas_t *datas,
char const *filename)
{
FILE *file_handler = fopen(filename, "w");
BMP_ASSERT(file_handler != NULL, strerror(errno));
fwrite(header, sizeof(*header), 1, file_handler);
fwrite(datas->bitmap, header->infos.img_size, 1, file_handler);
fclose(file_handler);
}
int main(int argc, char **argv)
{
char *buff;
bmp_header_t *header;
bmp_file_datas_t datas;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <input filename> <output filename>\n",
argv[0]);
return EXIT_FAILURE;
}
buff = get_file_content(argv[1]);
header = bmp_get_header();
get_file_infos(buff, header, &datas);
write_bitmap(buff, &datas);
write_in_file(header, &datas, argv[2]);
free(buff), free(header), free(datas.bitmap);
return EXIT_SUCCESS;
}
Solution 2:[2]
A crude method to achieve the required functionality would be: (Not really C, but then it is your homework not mine)
WIDTH = 0, HEIGHT = 0
if(LINE=READ_LINE(fin))
WIDTH = strlen(LINE)
++HEIGHT
else
ERROR!!!
PUSH(LINE)
while(LINE=READ_LINE(fin))
if(WIDTH != strlen(LINE))
ERROR!!!
else
++HEIGHT
PUSH(LINE)
WRITE_BMP_HEADER(WIDTH, HEIGHT)
for(h = 0; h < HEIGHT; ++h)
LINE = POP()
for(w = 0; w < WIDTH; ++w)
COLOR = (LINE[w] - '0') * 255 / 9;
WRITE_BMP_COLOR(COLOR)
WRITE_BMP_PADDING(W)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |