Linux&C语言简单实现图片加马赛克-标准IO实现

2023-11-09

1. 基于C语言实现,标准IO练习
2. 图片格式bmp
BMP图片格式详解
(获取图片前54个字节中有用的信息链接)
3. 代码实现

//标准IO实现
#include <stdio.h> // Shift  +  Alt  + F     实现代码的对齐;
// malloc函数的头文件
#include <stdlib.h>

//图片的参数结构体   单位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 = %d\n",
           info->img_size, info->img_width, info->img_high, info->img_bitcount);
}*/

//值传递
void show_image_info(image_info_t info)
{
    //向终端打印图片参数
    printf("大小size = %d,宽width = %d,高high = %d,素点占bitcount = %d\n",
           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};
    /*成功返回读取到的项目的个数,如果是失败或者读取到的文件的结尾返回值是要小于nnemb或者0
 读取到文件的结尾需要通过feof(fp)或者错误通过ferror(fp)来判断*/
    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 again\n");
        fprintf(stderr, "usage:./a.out xxxx.bmp\n");
        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. 非原创

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux&C语言简单实现图片加马赛克-标准IO实现 的相关文章

  • 在内核代码中查找函数的最佳方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我开始浏览内核代码 遇到的一件事是如何跟踪函数调用 结构定义等 有没有一种好的方法可以快速跳转到函数定义并退出 我尝试过 Source N
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud
  • Linux 中 m 标志和 o 标志将存储在哪里

    我想知道最近收到的路由器通告的 m 标志和 o 标志的值 从内核源代码中我知道存储了 m 标志和 o 标志 Remember the managed otherconf flags from most recently received R
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • linux下无法创建僵尸进程

    嗯 我有一个奇怪的问题 我无法在我的项目中创建僵尸进程 但我可以在其他文件中创建僵尸进程 有简单的说明 int main if fork 0 printf Some instructions n else sleep 10 wait 0 r
  • Google BQ:运行参数化查询,其中参数变量是 BQ 表目标

    我正在尝试从 Linux 命令行为 BQ 表目标运行 SQL 此 SQL 脚本将用于多个日期 客户端和 BQ 表目标 因此这需要在我的 BQ API 命令行调用中使用参数 标志 parameter 现在 我已经点击此链接来了解参数化查询 h
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 通过 Visual Studio 2017 使用远程调试时 Linux 控制台输出在哪里?

    我的Visual Studio 2017 VS2017 成功连接Linux系统 代码如下 include
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • C 语言的符号表

    我目前正在开发一种执行模式匹配的静态分析工具 我在用Flex https github com westes flex生成词法分析器 我编写了代码来管理符号表 我不太有经验C 所以我决定将符号表实现为线性链表 include
  • 尽管 if 语句,Visual Studio 仍尝试包含 Linux 标头

    我正在尝试创建一个强大的头文件 无需更改即可在 Windows 和 Linux 上进行编译 为此 我的包含内容中有一个 if 语句 如下所示 if defined WINDOWS include
  • 使用非规范地址检索内存数据会导致 SIGSEGV 而不是 SIGBUS

    我无法使用以下汇编代码产生 总线错误 这里我使用的内存地址不是合法的 规范地址 那么 我怎样才能触发该错误呢 我在带有 NASM 2 14 02 的 Ubuntu 20 04 LTS 下运行这段代码 但它会导致负载出现 SIGSEGV 分段
  • 使用包管理器时如何管理 Perl 模块?

    A 最近的问题 https stackoverflow com questions 397817 unable to find perl modules in intrepid ibex ubuntu这让我开始思考 在我尝试过的大多数 Li
  • 内核的panic()函数是否完全冻结所有其他进程?

    我想确认内核的panic 功能和其他类似kernel halt and machine halt 一旦触发 保证机器完全冻结 那么 所有的内核和用户进程都被冻结了吗 是panic 可以被调度程序中断吗 中断处理程序仍然可以执行吗 用例 如果
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • 如何使用Android获取Linux内核的版本?

    如何在 Android 应用程序中获取 Linux 内核的版本 不是 100 确定 但我认为调用 uname r 需要 root 访问权限 无论如何 有一种不太肮脏的方法可以做到这一点 那就是 System getProperty os v
  • 使用 gdb 调试 Linux 内核模块

    我想知道 API 在内核模块 中返回什么 从几种形式可以知道 这并不是那么简单 我们需要加载符号表来调试内核模块 所以我所做的就是 1 尝试找到内核模块的 text bss和 data段地址 2 在 gdb 中使用 add symbol f
  • 为什么同一个curl命令在windows和linux下输出不同的东西?

    为什么同样的curl o file https www link com 命令输出不同的东西 例如 如果我运行命令curl o source txt https www youtube com playlist list PLIx6Fwnp
  • x86-64 AMD 上 CALL 指令的操作数生成

    以下是示例程序 objdump 的输出 080483b4

随机推荐