#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define GRAY_LEVELS 255
struct bmpfileheader{
unsigned short filetype;
unsigned long filesize;
short reserved1;
short reserved2;
unsigned long bitmapoffset;
};
struct bitmapheader{
unsigned long size;
long width;
long height;
unsigned short planes;
unsigned short bitsperpixel;
unsigned long compression;
unsigned long sizeofbitmap;
unsigned long horzres;
unsigned long vertres;
unsigned long colorsused;
unsigned long colorsimp;
};
struct ctstruct{
unsigned char blue;
unsigned char green;
unsigned char red;
};
union short_char_union{
short s_num;
char s_alpha[2];
};
union int_char_union{
int i_num;
char i_alpha[2];
};
union long_char_union{
long l_num;
char l_alpha[4];
};
union float_char_union{
float f_num;
char f_alpha[4];
};
union ushort_char_union{
short s_num;
char s_alpha[2];
};
union uint_char_union{
int i_num;
char i_alpha[2];
};
union ulong_char_union{
long l_num;
char l_alpha[4];
};
short average[3][3] = {{1, 2, 1},
{2, 4, 2},
{1, 2, 1}};
short sharpen[3][3] = {{-1, -1, -1},
{-1, 8, -1},
{-1, -1, -1}};
short soble1[3][3] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
short soble2[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
#define ARRAY_SIZE 3
int get_image_size(const char* file_name, long* rows, long* cols);
void extract_long_from_buffer(char buffer[], int lsb, int start, long* number);
void extract_ulong_from_buffer(char buffer[], int lsb, int start,unsigned long* number);
void extract_short_from_buffer(char buffer[], int lsb, int start, short* number);
void extract_ushort_from_buffer(char buffer[], int lsb, int start, unsigned short* number);
void insert_short_into_buffer(char buffer[], int start, short number);
void insert_ushort_into_buffer(char buffer[], int start, unsigned short number);
void insert_long_into_buffer(char buffer[], int start, long number);
void insert_ulong_into_buffer(char buffer[], int start, unsigned long number);
short **allocate_image_array(long length, long width);
int free_image_array(short **the_array, long length);
void create_allocate_bmp_file(const char* file_name, struct bmpfileheader* file_header, struct bitmapheader* bmheader);
void read_bmp_file_header(const char* file_name, struct bmpfileheader* file_header);
void read_bm_header(const char* file_name, struct bitmapheader* bmheader);
int calculate_pad(long width);
void write_bmp_image(const char* file_name, short **array);
int does_not_exist(const char* file_name);
void flip_image_array(short** the_image, long rows, long cols);
void read_color_table(const char* file_name, struct ctstruct* rgb, int size);
void read_bmp_image(const char* file_name, short** array);
void filtering(short** in_array, short** out_array, long height, long width);
// .\gray_trans.exe test.bmp out.bmp
int main(int argc, char const *argv[])
{
char* cc;
long h, w;
short **in_array, **out_array;
struct bmpfileheader bmp_file_header;
struct bitmapheader bmheader;
if(argc < 2){
printf("\nusage: in_bmp_file_name out_bmp_file_nam\n");
exit(-1);
}
if(does_not_exist(argv[1])){
printf("\nERROR input file %s does not exist", argv[1]);
exit(0);
}
cc = strstr(argv[1], ".bmp");
if(cc == NULL){
printf("\nERROR %s must be a bmp file", argv[1]);
exit(0);
}
cc = strstr(argv[2], ".bmp");
if(cc == NULL){ /* create a bmp */
printf("\nERROR %s must be a bmp file name", argv[2]);
exit(0);
}
get_image_size(argv[1], &h, &w);
in_array = allocate_image_array(h, w);
read_bmp_image(argv[1], in_array);
out_array = allocate_image_array(h, w);
bmheader.height = h;
bmheader.width = w;
create_allocate_bmp_file(argv[2], &bmp_file_header, &bmheader);
filtering(in_array, out_array, h, w);
write_bmp_image(argv[2], out_array);
free_image_array(in_array, h);
free_image_array(out_array, h);
return 0;
}
short mid_val(short* a, short num)
{
short temp;
for (int i = 0; i < num; i++)
{
temp = a[i];
int j = i;
for (; j > 0 && a[j - 1] > temp; j--)
a[j] = a[j - 1];
a[j] = temp;
}
return a[num/2];
}
int is_in_array(short x, short y, short height, short width)
{
if (x >= 0 && x < width && y >= 0 && y < height)
return 1;
else
return 0;
}
/*
* element
* v0 v1 v2
* v3 v4 v5
* v6 v7 v8
*
*/
void filtering(short** in_array, short** out_array, long height, long width)
{
short value[9];
/* linear filtering */
short sum;
for (int i = 0; i < ARRAY_SIZE; i++)
for (int j = 0; j < ARRAY_SIZE; j++)
sum += average[i][j];
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++){
value[0] = is_in_array(j-1, i-1, height, width) ? in_array[i-1][j-1] : 0;
value[1] = is_in_array(j, i-1, height, width) ? in_array[i-1][j] : 0;
value[2] = is_in_array(j+1, i-1, height, width) ? in_array[i-1][j+1] : 0;
value[3] = is_in_array(j-1, i, height, width) ? in_array[i][j-1] : 0;
value[4] = in_array[i][j];
value[5] = is_in_array(j+1, i, height, width) ? in_array[i][j+1] : 0;
value[6] = is_in_array(j-1, i+1, height, width) ? in_array[i+1][j-1] : 0;
value[7] = is_in_array(j, i+1, height, width) ? in_array[i+1][j] : 0;
value[8] = is_in_array(j+1, i+1, height, width) ? in_array[i+1][j+1] : 0;
/* linear filtering */
out_array[i][j] = (value[0] * average[0][0] + value[1] * average[0][1] + value[2] * average[0][2] +
value[3] * average[1][0] + value[4] * average[1][1] + value[5] * average[1][2] +
value[6] * average[2][0] + value[7] * average[2][1] + value[8] * average[2][2]) / sum;
/* median filtering */
// out_array[i][j] = mid_val(value, 9);
/* sharpening filtering */
// out_array[i][j] = value[0] * sharpen[0][0] + value[1] * sharpen[0][1] + value[2] * sharpen[0][2] +
// value[3] * sharpen[1][0] + value[4] * sharpen[1][1] + value[5] * sharpen[1][2] +
// value[6] * sharpen[2][0] + value[7] * sharpen[2][1] + value[8] * sharpen[2][2];
// out_array[i][j] += in_array[i][j];
// if (out_array[i][j] < 0)
// out_array[i][j] = 0;
// else if (out_array[i][j] > 0xff)
// out_array[i][j] = 0xff;
/* sharpening using grad */
// out_array[i][j] = (short)abs(value[0] * soble1[0][0] + value[1] * soble1[0][1] + value[2] * soble1[0][2] +
// value[3] * soble1[1][0] + value[4] * soble1[1][1] + value[5] * soble1[1][2] +
// value[6] * soble1[2][0] + value[7] * soble1[2][1] + value[8] * soble1[2][2]) +
// (short)abs(value[0] * soble2[0][0] + value[1] * soble2[0][1] + value[2] * soble2[0][2] +
// value[3] * soble2[1][0] + value[4] * soble2[1][1] + value[5] * soble2[1][2] +
// value[6] * soble2[2][0] + value[7] * soble2[2][1] + value[8] * soble2[2][2]);
// /* edge enhancement */
// if (out_array[i][j] < 0)
// out_array[i][j] = 0;
// else if (out_array[i][j] > 0xff)
// out_array[i][j] = 0xff;
// else if (out_array[i][j] > 200)
/