/**
// img_convert.c
//
// A small sample program that creates mirror image and rotate image,
// source image must be bmp format
//
// comiple as:
// gcc img_convert.c
//
// Run using:
// ./a.out
//
**/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned long
#pragma pack(2)
typedef struct BMP_Head_t {
uint16_t identifier;
uint32_t file_size;
uint32_t reserved;
uint32_t data_offset;
} BMP_Head_t;
typedef struct BMP_MapInfo_t {
uint32_t header_size;
uint32_t width;
uint32_t height;
uint16_t n_planes;
uint16_t bits_per_pixel;
uint32_t compression;
uint32_t data_size;
uint32_t hresolution;
uint32_t vresolution;
uint32_t n_colors_used;
uint32_t n_important_colors;
} BMP_MapInfo_t;
#pragma pack()
typedef struct BMP_Container_t {
char *file_name;
BMP_Head_t head;
BMP_MapInfo_t map_info;
unsigned char *img_data_buf;
int has_init;
} BMP_Container_t;
int BMP_Rotate(const char *f, BMP_Container_t *c)
{
FILE *fp = NULL;
int row, line_size;
int retval = -1;
if (!f || !c || !c->has_init) return -1;
fp = fopen(f, "wb");
if (!fp) {
fprintf(stderr, "ROTATE: fopen file Error.\n");
goto exit_err;
}
/* fill bitmap head */
if (sizeof(BMP_Head_t) != fwrite(&c->head, 1, sizeof(BMP_Head_t), fp)) {
fprintf(stderr, "ROTATE: fwrite bitmap.head Error.\n");
goto exit_err;
}
/* fill bitmap map information */
if (sizeof(BMP_MapInfo_t) != fwrite(&c->map_info, 1, sizeof(BMP_MapInfo_t), fp)) {
fprintf(stderr, "ROTATE: fwrite bitmap.mapinfo Error.\n");
goto exit_err;
}
/* get bytes of one line */
line_size = c->map_info.width*c->map_info.bits_per_pixel/8;
/* rotate & fill bitmap image data */
for (row = c->map_info.height-1; row >= 0; row--) {
fwrite(&c->img_data_buf[row*line_size], 1, line_size, fp);
}
retval = 0;
exit_err:
if (fp) fclose(fp);
return retval;
}
int BMP_Mirror(const char *f, BMP_Container_t *c)
{
FILE *fp = NULL;
unsigned char *buf = NULL;
int row, n_pixel, n_byte;
int line_size, bytes_per_pixel;
int retval = -1;
if (!f || !c || !c->has_init) return -1;
fp = fopen(f, "wb");
if (!fp) {
fprintf(stderr, "MIRROR: fopen file Error.\n");
goto exit_err;
}
/* fill bitmap head */
if (sizeof(BMP_Head_t) != fwrite(&c->head, 1, sizeof(BMP_Head_t), fp)) {
fprintf(stderr, "MIRROR: fwrite bitmap.head Error.\n");
goto exit_err;
}
/* fill bitmap map information */
if (sizeof(BMP_MapInfo_t) != fwrite(&c->map_info, 1, sizeof(BMP_MapInfo_t), fp)) {
fprintf(stderr, "MIRROR: fwrite bitmap.mapinfo Error.\n");
goto exit_err;
}
/* get bytes of one line */
bytes_per_pixel = c->map_info.bits_per_pixel/8;
line_size = c->map_info.width*bytes_per_pixel;
/* allocate memory for one line data of image */
buf = (unsigned char *)malloc(line_size);
if (!buf) {
fprintf(stderr, "MIRROR: Can't allocate memory for line buffer.\n");
goto exit_err;
}
/* mirror & fill bitmap image data */
for (row = 0; row < c->map_info.height; row++) {
for (n_pixel = 0; n_pixel < c->map_info.width; n_pixel++) {
for (n_byte = 0; n_byte < bytes_per_pixel; n_byte++) {
buf[n_pixel*bytes_per_pixel+n_byte] =
*(unsigned char *)((&c->img_data_buf[row*line_size]) + (c->map_info.width-n_pixel-1)*bytes_per_pixel + n_byte);
}
}
fwrite(buf, 1, line_size, fp);
}
retval = 0;
exit_err:
if (buf) free(buf);
if (fp) fclose(fp);
return retval;
}
int BMP_Gray(const char *f, BMP_Container_t *c)
{
FILE *fp = NULL;
unsigned char *buf = NULL;
int row, n_pixel;
int line_size, bytes_per_pixel;
int retval = -1;
unsigned char blue, red, green, Y;
if (!f || !c || !c->has_init) return -1;
fp = fopen(f, "wb");
if (!fp) {
fprintf(stderr, "MIRROR: fopen file Error.\n");
goto exit_err;
}
/* fill bitmap head */
if (sizeof(BMP_Head_t) != fwrite(&c->head, 1, sizeof(BMP_Head_t), fp)) {
fprintf(stderr, "MIRROR: fwrite bitmap.head Error.\n");
goto exit_err;
}
/* fill bitmap map information */
if (sizeof(BMP_MapInfo_t) != fwrite(&c->map_info, 1, sizeof(BMP_MapInfo_t), fp)) {
fprintf(stderr, "MIRROR: fwrite bitmap.mapinfo Error.\n");
goto exit_err;
}
/* get bytes of one line */
bytes_per_pixel = c->map_info.bits_per_pixel/8;
line_size = c->map_info.width*bytes_per_pixel;
/* allocate memory for one line data of image */
buf = (unsigned char *)malloc(line_size);
if (!buf) {
fprintf(stderr, "MIRROR: Can't allocate memory for line buffer.\n");
goto exit_err;
}
/* gray & fill bitmap image data */
for (row = 0; row < c->map_info.height; row++) {
for (n_pixel = 0; n_pixel < c->map_info.width; n_pixel++) {
/* get blue, red & green */
blue = *(unsigned char *)((&c->img_data_buf[row*line_size]) + n_pixel*bytes_per_pixel + 0);
green = *(unsigned char *)((&c->img_data_buf[row*line_size]) + n_pixel*bytes_per_pixel + 1);
red = *(unsigned char *)((&c->img_data_buf[row*line_size]) + n_pixel*bytes_per_pixel + 2);
/* Y=0.299*R+0.587*G+0.114*B */
Y = (unsigned char)(0.299*red + 0.587*green + 0.114*blue);
buf[n_pixel*bytes_per_pixel+0] = Y;
buf[n_pixel*bytes_per_pixel+1] = Y;
buf[n_pixel*bytes_per_pixel+2] = Y;
}
fwrite(buf, 1, line_size, fp);
}
retval = 0;
exit_err:
if (buf) free(buf);
if (fp) fclose(fp);
return retval;
}
int BMP_Initiate(const char *f, BMP_Container_t *c)
{
FILE *fp = NULL;
int retval = -1;
if (!f || !c || c->has_init) return -1;
fp = fopen(f, "r");
if (!fp) {
fprintf(stderr, "INITIATE: fopen file Error.\n");
goto exit_err;
}
/* acquire bitmap header */
if (sizeof(BMP_Head_t) != fread(&c->head, 1, sizeof(BMP_Head_t), fp)) {
fprintf(stderr, "INITIATE: fread bitmap.head Error.\n");
goto exit_err;
}
/* acquire bitmap map information */
if (sizeof(BMP_MapInfo_t) != fread(&c->map_info, 1, sizeof(BMP_MapInfo_t), fp)) {
fprintf(stderr, "INITIATE: fread bitmap.mapinfo Error.\n");
goto exit_err;
}
/* judge bitmap format */
if (c->head.identifier != ('M'<<8 | 'B')) {
fprintf(stderr, "INITIATE: Is NOT bitmap format.\n");
goto exit_err;
}
/* for now, only 24bits bitmap works well */
if (c->map_info.bits_per_pixel != 24) {
fprintf(stderr, "INITIATE: Is NOT 24-bit bitmap.\n");
goto exit_err;
}
/* allocate buffer for image data */
c->img_data_buf = (unsigned char *)malloc(c->map_info.data_size);
if (!c->img_data_buf) {
fprintf(stderr, "INITIATE: Can't allocate memory for image data buffer.\n");
goto exit_err;
}
/* acquire bitmap data */
if (c->map_info.data_size != fread(c->img_data_buf, 1, c->map_info.data_size, fp)) {
fprintf(stderr, "INITIATE: fread bitmap.img_data Error.\n");
goto exit_err;
}
c->has_init = 1;
retval = 0;
exit_err:
if (fp) fclose(fp);
return retval;
}
int main(int argc, char* argv[])
{
BMP_Container_t img_container;
memset(&img_container, 0x0, sizeof(img_container));
img_container.file_name = "source.bmp";
if (BMP_Initiate(img_container.file_name, &img_container)) {
return -1;
}
BMP_Rotate("rotate.bmp", &img_container);
BMP_Mirror("mirror.bmp", &img_container);
BMP_Gray("gray.bmp", &img_container);
if (img_container.img_data_buf) free(img_container.img_data_buf);
printf("Done.\n");
return 0;
}
|