MinGW的配置就不提了
- 创建四个文件如下,已加入部分注释
hdr.c
#include <stdio.h>
#include <memory.h>
#include "hdr.h"
struct bmphdr *get_header(char filename[])
{
FILE *fp;
struct bmphdr *hdr;
fp = fopen(filename, "rb");
if (!fp) {
printf("File open error or such file does not exist!\n");
return NULL;
}
hdr = (struct bmphdr *)malloc(sizeof(struct bmphdr));//分配空间
fread(hdr->signature, 2, 1, fp);
if (hdr->signature[0] != 'B' || hdr->signature[1] != 'M') {//如果打开文件的扩展名不是.bmp
printf("Not a bmp file!\n");
return NULL;
}
//读位图头文件信息
fread(&hdr->size, 4, 1, fp);
fread(hdr->reserved, 4, 1, fp);
fread(&hdr->offset, 4, 1, fp);
fread(&hdr->hdr_size, 4, 1, fp);
fread(&hdr->width, 4, 1, fp);
fread(&hdr->height, 4, 1, fp);
fread(&hdr->nr_planes, 2, 1, fp);
fread(&hdr->bits_per_pixel, 2, 1, fp);
fread(&hdr->compress_type, 4, 1, fp);
fread(&hdr->data_size, 4, 1, fp);
fread(&hdr->resol_hori, 4, 1, fp);
fread(&hdr->resol_vert, 4, 1, fp);
fread(&hdr->nr_colors, 4, 1, fp);
fread(&hdr->important_color, 4, 1, fp);
if (hdr->offset > 54)//获得位图有效信息,偏移量为54的时候读的才是位图第一个像素
fread(&hdr->info, 1024, 1, fp);
fclose(fp);//关闭文件
return hdr;
}
hdr.h
#ifndef __HDR_H__
#define __HDR_H__
struct bmphdr {
char signature[2];//文件类型
int size;//位图大小
short reserved[2];//两个保留字
int offset;//位图偏移位置
int hdr_size;//头文件大小
int width;//位图宽度
int height;//位图高度
short nr_planes;//位平面数
short bits_per_pixel;//每像素的位数
int compress_type;//压缩类型
int data_size;//数据大小
int resol_hori;//水平
int resol_vert;//垂直
int nr_colors;
int important_color;
char info[1024];
};
struct bmphdr *get_header(char filename[]);//获取位图头文件信息
#endif
bmphdr.c
#include <stdio.h>
struct bmphdr {
char signature[2];//文件类型
int size;//位图大小
short reserved[2];//两个保留字
int offset;//位图偏移位置
int hdr_size;//头文件大小
int width;//位图宽度
int height;//位图高度
short nr_planes;//位平面数
short bits_per_pixel;//每像素的位数
int compress_type;//压缩类型
int data_size;//数据大小
int resol_hori;//水平
int resol_vert;//垂直
int nr_colors;
int important_color;
} header;
int main(int argc, char *argv[])
{
FILE *fp;
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
printf("File open error or such file does not exist!\n");
exit(1);
}
fread(header.signature, 2, 1, fp);
if (header.signature[0] != 'B' || header.signature[1] != 'M') {
printf("Not a bmp file!\n");
exit(1);
}
//均为位图头信息
fread(&header.size, 4, 1, fp);//图像大小
fread(header.reserved, 4, 1, fp);
fread(&header.offset, 4, 1, fp);//偏移量
fread(&header.hdr_size, 4, 1, fp);//图像信息头大小,识别不同版本bmp文件
fread(&header.width, 4, 1, fp);//图像宽度
fread(&header.height, 4, 1, fp);//图像高度
fread(&header.nr_planes, 2, 1, fp);
fread(&header.bits_per_pixel, 2, 1, fp);
fread(&header.compress_type, 4, 1, fp);
fread(&header.data_size, 4, 1, fp);
fread(&header.resol_hori, 4, 1, fp);
fread(&header.resol_vert, 4, 1, fp);
fread(&header.nr_colors, 4, 1, fp);
fread(&header.important_color, 4, 1, fp);
fclose(fp);
printf("signature %c%c\n", header.signature[0], header.signature[1]);
printf("size %d\n", header.size);
printf("offset %d\n", header.offset);
printf("hdr_size %d\n", header.hdr_size);
printf("width %d\n", header.width);
printf("height %d\n", header.height);
printf("nr_planes %d\n", header.nr_planes);
printf("bits_per_pixel %d\n", header.bits_per_pixel);
printf("compress_type %d\n", header.compress_type);
printf("data_size %d\n", header.data_size);
printf("resol_hori %d\n", header.resol_hori);
printf("resol_vert %d\n", header.resol_vert);
printf("nr_colors %d\n", header.nr_colors);
printf("important_color %d\n", header.important_color);
printf("\n");
return 0;
}
ez.c
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "hdr.h"
struct bmphdr *hdr;
unsigned char *bitmap, *to;
char buf[2048];
int main(int argc, char *argv[])
{
int i, j, k, nr_pixels;
FILE *fp, *fpnew;
unsigned g;
if (argc != 4) {
printf("Usage: %s <file_from> <file_to> <threshold>\n", argv[0]);
exit(1);
}
hdr = get_header(argv[1]);
if (!hdr) exit(1);
fp = fopen(argv[1], "rb");//打开位图文件
if (!fp) {//如果打开错误,给出提示
printf("File open error!\n");
exit(1);
}
fseek(fp, hdr->offset, SEEK_SET);
nr_pixels = hdr->width * hdr->height;
bitmap = malloc(nr_pixels);
fread(bitmap, nr_pixels, 1, fp);
fclose(fp);
k = atoi(argv[3]);
to = malloc(nr_pixels);
memset(to, 0, nr_pixels);
for (i = 0; i < nr_pixels; i++)
to[i] = bitmap[i] > (unsigned char)k ? 255 : 0;
fpnew = fopen(argv[2], "wb+");
if (!fpnew) {
printf("File create error!\n");
exit(1);
}
//位图头信息
fwrite(hdr->signature, 2, 1, fpnew);
fwrite(&hdr->size, 4, 1, fpnew);
fwrite(hdr->reserved, 4, 1, fpnew);
fwrite(&hdr->offset, 4, 1, fpnew);
fwrite(&hdr->hdr_size, 4, 1, fpnew);
fwrite(&hdr->width, 4, 1, fpnew);
fwrite(&hdr->height, 4, 1, fpnew);
fwrite(&hdr->nr_planes, 2, 1, fpnew);
fwrite(&hdr->bits_per_pixel, 2, 1, fpnew);
fwrite(&hdr->compress_type, 4, 1, fpnew);
fwrite(&hdr->data_size, 4, 1, fpnew);
fwrite(&hdr->resol_hori, 4, 1, fpnew);
fwrite(&hdr->resol_vert, 4, 1, fpnew);
fwrite(&hdr->nr_colors, 4, 1, fpnew);
fwrite(&hdr->important_color, 4, 1, fpnew);
if (hdr->offset > 54)
fwrite(hdr->info, hdr->offset - 54, 1, fpnew);
fwrite(to, nr_pixels, 1, fpnew);
fclose(fpnew);
free(hdr);
free(bitmap);
return 0;
}
然后,在控制台下分别使用
gcc -c hdr.c
gcc -c bmphdr.c
gcc -c ez.c
gcc -o ez.exe ez.c hdr.c
编译链接出ez.exe程序,在控制台下使用ez.exe 输入文件 输出文件 阈值
即可输出二值化之后的图片,阈值可选108
- 这个实验的大致目的就是给你一张图片,然后你需要把它变成黑白图,如下所示
原图
二值化后
- 上面的程序不难理解,这里提一下main函数的参数问题,argc表示参数个数,数组argv存储参数,如果不传参,默认第一个参数为程序名,也就是说argv是从1开始的,可以写程序在控制台测试一下看看