1. 基于C语言实现,标准IO练习
2. 图片格式bmp
BMP图片格式详解(获取图片前54个字节中有用的信息链接)
3. 代码实现
//标准IO实现 #include// Shift + Alt + F 实现代码的对齐; // malloc函数的头文件 #include //图片的参数结构体 单位Bytes typedef struct { unsigned int img_size; //图片的大小 unsigned int img_width; //图片的宽 unsigned int img_high; //图片的高 unsigned short img_bitcount; //一个像素点占用的bit(24bit)当biBitCount=24时,1个像素占3个字节; } image_info_t; // RGB颜色参数 typedef struct { unsigned char b; // B unsigned char g; // G unsigned char r; // R } point_t; //值传递 void show_image_info(image_info_t info) { //向终端打印图片参数 printf("大小size = %d,宽width = %d,高high = %d,素点占bitcount = %dn", info.img_size, info.img_width, info.img_high, info.img_bitcount); } void get_image_info(FILE *fp, image_info_t *info) { //修改光标的位置 fseek(fp, 2, SEEK_SET); //从文件的开头向后偏移2个字节 fread(&info->img_size, 1, 4, fp); //图片的大小 fseek(fp, 18, SEEK_SET); // biWidth = biSize:002h+4Bytes + 012h fread(&info->img_width, 1, 4, fp); //图片的宽 // biHeight = biSize:002h+4Bytes + biWidth:012h+4Bytes = 22 // fseek(fp, 22, SEEK_SET);//紧接着,无需修改光标的位置也可继续读 fread(&info->img_high, 1, 4, fp); //读取图片的高 // biSizeImage=biSize:002h+4Bytes + 022h= 28 此时上面执行完后在 26 (从文件的开头向后偏移26个字节) //还需要 从光标当前位置向后偏移2个字节 fseek(fp, 2, SEEK_CUR); //<==>fseek(fp, 28, SEEK_SET); 从文件的开头向后偏移28个字节 fread(&info->img_bitcount, 1, 2, fp); //像素点占用的bit } void copy_image_file(FILE *sfp, FILE *dfp) { int ret; char buf[1024] = {0}; while (!(feof(sfp) || ferror(sfp))) { // fread(保存读取到数据的首地址,每一项的大小, 项的个数,文件指针);成功返回读取到的项目的个数 ret = fread(buf, 1, sizeof(buf), sfp); // fwrite(数据的首地址,每一项的大小, 项的个数,文件指针);成功返回写入的项目的个数 fwrite(buf, 1, ret, dfp); } return; } void set_image_mosaic(FILE *fp, image_info_t *info, int x, int y) { int i, j, k, w; point_t color = {0, 0, 0xff}; //{B,G,R} //保存读取到的数据 char *buffer = (char *)malloc((info->img_width) * (info->img_high) * 3); // 1.将图像读取回来 (跳过图片的文件头、信息头)54Byte fseek(fp, 54, SEEK_SET); fread(buffer, 1, (info->img_size - 54), fp); // 2.修改buffer //传入 x y // i:整体的高/10 (共有行数) for (i = 0; i < info->img_high / y; i++) { // j:整体的宽除以10 (共有列数) for (j = 0; j < info->img_width / x; j++) { //读取小方块中最左上角的像素点 //当biBitCount=24时,1个像素占3个字节; color = *(point_t *)(buffer + (j * 3 * x) + (i * y * info->img_width * 3)); // k:小方块的高(行) for (k = 0; k < y; k++) { // w:小方块的宽(列) for (w = 0; w < x; w++) { //将小方块的各个像素赋值==最左上角的像素点//当biBitCount=24时,1个像素占3个字节; *(point_t *)(buffer + w * 3 + (k * info->img_width * 3) + (j * 3 * x) + (i * y * info->img_width * 3)) = color; } } } } // 3.重新将图像写回去 fseek(fp, 54, SEEK_SET); //修改光标的位置回到原位 fwrite(buffer, 1, (info->img_size - 54), fp); //释放地址空间的 free(buffer); } int main(int argc, char const *argv[]) { FILE *sfp, *dfp; int size; image_info_t info; //图片的参数结构体 char new_name[20] = {0}; if (argc != 2) { //命令行输入./a.out xxxx.bmp fprintf(stderr, "input error,try againn"); fprintf(stderr, "usage:./a.out xxxx.bmpn"); return -1; } // 1.打开文件并拷贝文件 milaoshu.bmp if ((sfp = fopen(argv[1], "r")) == NULL) { perror("open error"); return -1; } //构造一个新图片的字符串 new_milaoshu.bmp snprintf(new_name, sizeof(new_name), "new_%s", argv[1]); //存放首地址 格式化的控制格式 //打开新图片,如果不存在就创建,如果存在就清空 if ((dfp = fopen(new_name, "w+")) == NULL) // w+ 读写 { perror("open error"); return -1; } //图片的拷贝,将milaoshu.bmp-->new_milaoshu.bmp copy_image_file(sfp, dfp); // 2.获取图片前54个字节中有用的信息 get_image_info(dfp, &info); //传地址直接修改赋值 // show_image_info(&info);//地址传递 show_image_info(info); //值传递 // 3.尝试打马赛克 // 10,10:代表的是打马赛克每个小方块的大小 // 10*3= 30 // 10 = 10行 set_image_mosaic(dfp, &info, 10, 10); // 4.关闭源文件和目标文件 fclose(sfp); fclose(dfp); return 0; }
4. 执行
5. 对比
6. 非原创



