#include <stdio.h>
#include <stdlib.h>
#include <string.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];
};
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);
void read_bmp_image(const char* file_name, short** array);
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 bilinera_interpolation(short** in_array, short height, short width,
short** out_array, short out_height, short out_width);
// .\scaling.exe a.bmp b.bmp 500 600
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;
short out_width, out_height;
if(argc < 4){
printf("\nusage: bmp scaling_file scaling_width scaling_height\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);
}
out_width = atoi(argv[3]);
out_height = atoi(argv[4]);
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(out_height, out_width);
bmheader.height = out_height;
bmheader.width = out_width;
create_allocate_bmp_file(argv[2], &bmp_file_header, &bmheader);
bilinera_interpolation(in_array, h, w, out_array, out_height, out_width);
write_bmp_image(argv[2], out_array);
// bmheader.height = h;
// bmheader.width = w;
// create_allocate_bmp_file(argv[2], &bmp_file_header, &bmheader);
// write_bmp_image(argv[2], in_array);
free_image_array(in_array, h);
free_image_array(out_array, out_height);
return 0;
}
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;
}
void bilinera_interpolation(short** in_array, short height, short width,
short** out_array, short out_height, short out_width)
{
double h_times = (double)out_height / (double)height,
w_times = (double)out_width / (double)width;
short x1, y1, x2, y2, f11, f12, f21, f22;
double x, y;
for (int i = 0; i < out_height; i++){
for (int j = 0; j < out_width; j++){
x = j / w_times;
y = i / h_times;
/* 仿射变换 逆时针旋转 45度 + 平移 */
// y = i + j - out_width / 2 - (out_height - height) / 2;
// x = i - j + out_width / 2 - (out_height - height) / 2;
/* 仿射变换水平偏移 */
// y = i;
// x = j - i / 2;
x1 = (short)(x - 1);
x2 = (short)(x + 1);
y1 = (short)(y + 1);
y2 = (short)(y - 1);
f11 = is_in_array(x1, y1, height, width) ? in_array[y1][x1] : 0;
f12 = is_in_array(x1, y2, height, width) ? in_array[y2][x1] : 0;
f21 = is_in_array(x2, y1, height, width) ? in_array[y1][x2] : 0;
f22 = is_in_array(x2, y2, height, width) ? in_array[y2][x2] : 0;
out_array[i][j] = (short)(((f11 * (x2 - x) * (y2 - y)) +
(f21 * (x - x1) * (y2 - y)) +
(f12 * (x2 - x) * (y - y1)) +
(f22 * (x - x1) * (y - y1))) / ((x2 - x1) * (y2 - y1)));
}
}
}
void read_color_table(const char* file_name, struct ctstruct* rgb, int size)
{
int i;
char buffer[10];
FILE *fp;
fp = fopen(file_name, "rb");
fseek(fp, 54, SEEK_SET);
for(i=0; i<size; i++){
fread(buffer, 1, 1, fp);
rgb[i].blue = buffer[0];
fread(buffer, 1, 1, fp);
rgb[i].green = buffer[0];
fread(buffer, 1, 1, fp);
rgb[i].red = buffer[0];
fread(buffer, 1, 1, fp);
/* fourth byte nothing */
} /* ends loop over i */
fclose(fp);
} /* ends read_color_table */
void read_bmp_image(const char* file_name, short** array)
{
FILE *fp;
int i, j;
int negative = 0,
pad = 0,
place = 0;
long colors = 0,
height = 0,
//position = 0,
width = 0;
struct bmpfileheader file_header;
struct bitmapheader bmheader;
struct ctstruct rgb[GRAY_LEVELS+1];
unsigned char uc;
read_bmp_file_header(file_name, &file_header);
read_bm_header(file_name, &bmheader);
if(bmheader.bitsperpixel != 8){
printf("\nCannot read image when bits per pixel is not 8");
exit(1);
}
if(bmheader.colorsused == 0)
colors = GRAY_LEVELS + 1;
else
colors = bmheader.colorsused;
read_color_table(file_name, (struct ctstruct*)&rgb, colors);
fp = fopen(file_name, "rb");
fseek(fp, file_header.bitmapoffset, SEEK_SET);
width = bmheader.width;
if(bmheader.height < 0){
height = bmheader.height * (-1);
negative = 1;
}
else
height = bmheader.height;
pad = calculate_pad(width);
for(i=0; i<height; i++){
for(j=0; j<width; j++){
place = fgetc(fp);
uc = (place & 0xff);
place = uc;
array[i][j] = rgb[place].blue;
} /* ends loop over j */
if(pad != 0){
//position = fseek(fp, pad, SEEK_CUR);