C语言,BMP格式解析,生成不同位深的图片。

2023-11-16

0.前言

目录

0.前言

1.BMP格式详解

1.1图片的构成   

1.2BMP格式

1.2.1文件头

1.2.2位图信息头

1.2.3调色板

1.2.4位图数据

2.生成

3.总结


        最近工作任务繁重且对我来说小有难度,但是没有困难的事情做起来怎么有收获呢?

        今天推荐一本书《寻找光的小女孩》,挺感人的。记得是高中借的同学的看的,刚开始看到书名感觉不怎么投我的胃口,果不其然不可“以貌取书”,熬夜看完了。


        最近工作上逐渐步入正轨,研发的工作嘛,对吧,不可以设置限制,这才能体现到研发,才能发挥研发的最大福利。工作也算是小半年了,逐渐慢慢对手里的东西或者说项目有了自己的认识,这或许就是经验。这种感觉我刚刚能觉察到,相信再给我一些时间,可以掌握吧。

        喜欢上了喝无糖可乐。哈。


1.BMP格式详解

        这是最近工作的内容,任务是从csv文件获取数据,将获取到的数据通过算法转为灰度值,然后填充进BMP格式图片,要求图片位深16位。


1.1图片的构成   

        其实我们知道每张图片都是由每个像素组成的,多少的像素也构成图片的大小。每个像素是什么构成的呢?在bmp中就是数值。在此之前,先说明两个概念,位深和色深。(好长时间不写博客,手生了起来,逻辑思路也不如以前,见谅)。

        位深:这个名词是用来描述什么?每个像素的大小,是一个大小的代名词。比如位深是24的图片,就是说这张图片的每个像素的值是由24比特的大小来表示,比如一幅图片是1080*1280的大小,那么位深24的bmp大小就在1080*1280*3字节左右(这里我是在Linux下做的,从虚拟机拷贝到win下大小会不同,大概是因为架构的不同)。

        色深:在bmp中,每个像素的值,其实也就是颜色的值是由三通道RGB组成的,24位的图,每个通道的表示为8比特,即一字节,范围是0-255,三通道(红绿蓝)范围皆是0-255,那这三种通道合成的颜色也就是255*255*255种,这个值就叫做色深,是一个数量的范围,描述颜色的多少。

        这两种概念容易模糊,不知道我写的能不能帮助大家理解。


1.2BMP格式

        参考:bmp格式andbmp格式

        就把这个图片想象成普通的文件就行了,只不过区别就是要有固定的头。


1.2.1文件头

        文件头,顾名思义是描述这个文件的信息,也就是这个图片的信息。这里面的内容包含了文件的大小这一重要信息。此部分大小是14字节。

字节顺序

数据结构

描述

1,2

16比特

高8位位字母‘B,低8位为字母’M‘

3,4,5,6

32

文件尺寸

7,8

16

保留字1

9,10

16

保留字1

11,12,13,14

32

位图数据部分相对于文件的起始偏移量

        数据部分偏移量的存在,说明图像数据部分并不一定要紧随图像参数或调色板之后放置,BMP图片的制作者其实可以在调色板之后、数据部分之前填充任何内容,只要正确地设置偏移量即可。


1.2.2位图信息头

        此部分用来描述图片的信息,比如图像宽高、bpp等。此部分大小是40字节。

字节顺序

数据结构

描述

15,16,17,18

uint

当前结构体的大小,通常是40或56

19,20,21,22

int

图像宽度(像素)

23,24,25,26

int

图像高度(像素)

27,28

word

恒为1

29,30

word

每个像素占用的位数即bpp

31,32,33,34

uint

压缩方式

35,36,37,38

uint

图像的尺寸

39,40,41,42

int

水平分辨率

43,44,45,46

int

垂直分辨率

47,48,49,50

uint

引用色彩数

51,52,53,54

uint

关键色彩数


        31-34字节表示图像数据的压缩方式,参数取值范围是0,1,2,3等。

                0 ----------------RGB方式

                1 --------------- 8bpp的run-length-encoding方式

                2 --------------- 4bpp的run-length-encoding方式

                3 ---------------- bit-fields方式

        只有压缩方式选项被设置为bit-fileds时,当前结构体大小为56字节,否则,为40字节。


1.2.3调色板

        我们一般见到的图像以24位图像为主,即R、G、B三种颜色各用8个bit来表示,这样的图像我们称为真彩色,这种情况下是不需要调色板的,也就是所位图信息头后面紧跟的就是位图数据了。这部分我略过,有兴趣的同学可以自己研究一下。


1.2.4位图数据

        就是每个像素的值,位图数据,每个像素占一个字节。24位数据按照BGR填充,例如一张2个像素的bmp24位图,它的构成就是:14字节文件头信息,40字节位图信息,2个像素,每个像素大小是24位,也就是3字节,第一个像素的blue就是8比特,后面紧跟8比特green,再是8比特red,后一个像素也是如此。一共14+40+2*3=60字节。那这个2个像素的bmp文件就占大小60字节。(不涉及调色板)

        后面以详细代码说明。


2.生成

        代码部分我只给出生成的,完整代码大家可以下载:完整代码。注意,此代码是从csv文件获取数据、分割数据并提取。

int bmp_gen_pic(char *fileName, uint32_t width, uint32_t height, unsigned char *color) 
{
    // width = 2048   height = 512  color = data_pic

#if 1
    FILE *fp;
    uint32_t i, j;
    LITTLE l_width, l_height, l_bfSize, l_biSizeImage;

    uint8_t r = color[0];
    uint8_t g = color[0];
    uint8_t b = color[0];

    uint32_t width_r = (width * 24 / 8 + 3) / 4 * 4; // width_r 此变量代表的是每行的字节数   6144(整形)  这步保证宽度是4的倍数(bmp格式要求)
    // printf("width_r = %ld\n",width_r);
    uint32_t bfSize = width_r * height + 54 + 2; //此变量代表生成的图片的大小 
    uint32_t biSizeImage = width_r * height;     //此变量代表图片的像素大小          
    // printf("hight = %ld\n",height);
    // printf("size = %ld\n",biSizeImage);

    l_width.value = width;             // 2048
    l_height.value = height;           // 512
    l_bfSize.value = bfSize;           // 3145784
    l_biSizeImage.value = biSizeImage; // 3145728

    /* BMP file format: www.cnblogs.com/wainiwann/p/7086844.html */
    // bmp格式头  固定
    uint8_t bmp_head_map[54] = {
        //这个头文件 包含两部分  一是文件头 14  二是位图信息头 40

        /* bmp file header: 14 byte */
        0x42, 0x4d, // 42 代表 B   4d代表M
        // bmp pixel size: width * height * 3 + 54
        l_bfSize.bytes[0], l_bfSize.bytes[1], l_bfSize.bytes[2], l_bfSize.bytes[3], //代表文件的尺寸 
        0, 0, 0, 0,
        54, 0, 0, 0, /* 14+40=54 */ //位图部分相对文件的起始偏移量  就是多少字节后是位图数据(像素值)

        /**************************************************************/

        /* bmp map info: 40 byte */
        40, 0, 0, 0, //当前的大小  就是40  意思后面40都是描述本部分

        // width   图像宽度(像素)
        l_width.bytes[0], l_width.bytes[1], l_width.bytes[2], l_width.bytes[3],

        // height  图像高度(像素)
        l_height.bytes[0], l_height.bytes[1], l_height.bytes[2], l_height.bytes[3],

        1, 0, //恒为1

        24, 0, //每个像素占用的位数(bpp)        /* 24 bit: R[8]/G[8]/B[8] */

        0, 0, 0, 0, // biCompression:0   压缩方式

        //图像的尺寸
        l_biSizeImage.bytes[0], l_biSizeImage.bytes[1], l_biSizeImage.bytes[2], l_biSizeImage.bytes[3],

        0, 0, 0, 0, //水平分辨率     //biXPelsPerMeter: 60 0F 00 00
        0, 0, 0, 0, //垂直分辨率     //biYPelsPerMeter
        0, 0, 0, 0, //引用色彩数     //biClrUsed
        0, 0, 0, 0  //关键色彩数     //biClrImportant
    };

    /* write in binary format */
    fp = fopen(fileName, "wb+"); // wb+代表打开一个读写打开一个二进制文件
    if (fp == NULL)
    {
        printf("%s: file create failed!\n", fileName);
        return -1;
    }

    printf("%s: file create success!\n", fileName);

    fwrite(bmp_head_map, sizeof(bmp_head_map), 1, fp); //写入1个sizeof(头)的大小

    uint8_t databmp[KUAN*GAO*3];
    memset(databmp, 0, sizeof(databmp));
    uint32_t pos = 0;

#if 1
    for (i = 0; i < height; i++)
    {                               // 512
        for (j = 0; j < width; j++) // 2048
        {
            //fprintf(fp, "%c%c%c", color[j + i * width], color[j + i * width], color[j + i * width]); /* BGR */ // FF FF FF 白色    00 00 00  黑色
            databmp[pos++] = color[j + i * width];
            databmp[pos++] = color[j + i * width];
            databmp[pos++] = color[j + i * width];

        }
    }

    fwrite(databmp, sizeof(databmp), 1, fp);

#endif
    fprintf(fp, "%c%c", 0, 0); // PhotoShop two byte "0"

    if (fclose(fp))
    {
        printf("file close failed!\n");
        return -1;
    }
    fp = NULL;

    return 0;
#endif
}

        代码我注解的很清楚,不懂可以留言。

3.总结

        好家伙,写了一个星期,shit.

        工作忙起来对博客是疏忽很多,见谅。

        上班时间消耗完了所有精力,累到不是累,只是想下班后不再想动脑,去获得简单纯粹的娱乐。

        生活需要新鲜,Everything is like this.

        最后再说一点,觉得难不要陷入“想”的境地,要去做。走过来后就会发现,也是如此。

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

C语言,BMP格式解析,生成不同位深的图片。 的相关文章

  • Linux命令列出所有可用命令和别名

    是否有一个 Linux 命令可以列出该终端会话的所有可用命令和别名 就好像您输入 a 并按下 Tab 键一样 但针对的是字母表中的每个字母 或者运行 别名 但也返回命令 为什么 我想运行以下命令并查看命令是否可用 ListAllComman
  • 无关的库链接

    我有一个可能有点愚蠢的问题 因为我很确定我可能已经知道答案了 假设你有静态库A 动态共享库B和你的linux下的程序C 假设库 A 调用库 B 中的函数 并且您的程序调用库 A 中的函数 现在假设 C 在 A 中调用的所有函数都不使用 B
  • 如何确保 numpy BLAS 库可用作动态加载库?

    The theano安装文档 http www deeplearning net software theano install html troubleshooting make sure you have a blas library指
  • 如何从类似于 eclipse 的命令行创建可运行的 jar 文件

    我知道 eclipse 会生成一个可运行的 jar 文件 其中提取并包含在该 jar 文件中的所有库 jar 文件 从命令提示符手动创建 jar 文件时如何执行类似的操作 我需要将所有 lib jar 解压到类文件夹中吗 目前我正在使用 j
  • Linux 上的 Python 3.6 tkinter 窗口图标错误

    我正在从 Python GUI 编程手册 学习 Python GUI 某项任务要求我通过将以下代码添加到我的配方中来更改窗口图标 Change the main windows icon win iconbitmap r C Python3
  • 套接字:监听积压并接受

    listen sock backlog 在我看来 参数backlog限制连接数量 这是我的测试代码 server initialize the sockaddr of server server sin family AF INET ser
  • 如何成功使用RDAP协议代替whois

    我对新的 RDAP 协议有点困惑 也不知道何时进一步追求它有意义 在我看来 每个人都同意它是 whois 的继承者 但他们的数据库似乎是空的 在 ubuntu 上我尝试了 rdapper nicinfo 甚至他们的 RESTful API
  • 如何获取 linux 实用程序 tail 的源代码?

    这个命令确实非常有用 但是我可以在哪里获取源代码以查看内部发生的情况 thanks tail 实用程序是 Linux 上 coreutils 的一部分 源压缩包 ftp ftp gnu org gnu coreutils coreutils
  • 如何在我的 AWS EC2 实例上安装特定字体?

    我有一个在 AWS EC2 Amazon Linux Elastic Beanstalk 实例上运行的 Python 应用程序 该实例需要某些特定字体才能生成输出 并且想知道如何在部署或实例启动过程中安装它们 我的代码在本地计算机 OS X
  • InstaPy:“错误,无法确定 64 位 Linux 的正确文件名”

    有人知道如何解决或解决这个问题吗 来自控制台的堆栈跟踪 执行后报告错误 InstaPy Version 0 6 9 Workspace in use home zanettra InstaPy Error unable to determi
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 在 LINUX 上使用 Python 连接到 OLAP 多维数据集

    我知道如何在 Windows 上使用 Python 连接到 MS OLAP 多维数据集 嗯 至少有一种方法 通常我使用 win32py 包并调用 COM 对象进行连接 import win32com client connection wi
  • 无法执行'x86_64-conda_cos6-linux-gnu-gcc':没有这样的文件或目录(pysam安装)

    我正在尝试安装 pysam 执行后 python path to pysam master setup py build 这个错误的产生是 unable to execute x86 64 conda cos6 linux gnu gcc
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • 在 Ubuntu 16.04 上找不到 printf.c

    我最近切换到Ubuntu 16 04 我在用vscode作为 Ubuntu 上的 IDE 我配置了其他语言 但我无法做到这一点C C 我创建c cpp properties json launch json tasks json 当我开始编
  • 从 TypeScript 运行任何 Linux 终端命令?

    有没有办法直接从 TypeScript 类中执行 Linux 终端命令 这个想法是做类似的事情 let myTerminal new LinuxTerminal let terminalResult myTerminal run sudo
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • diff 文件仅比较每行的前 n 个字符

    我有2个文件 我们将它们称为 md5s1 txt 和 md5s2 txt 两者都包含a的输出 find type f print0 xargs 0 md5sum sort gt md5s txt 不同目录下的命令 许多文件被重命名 但内容保
  • 在 Linux 中禁用历史记录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 要在 Linux 环境中禁用历史记录 我执行了以下命令 export HISTFILESIZE 0 export HISTSIZE 0 u
  • 嵌入式Linux poll()不断返回

    我有一个特别的问题 当我知道没有什么可读时 民意调查不断返回 因此设置如下 我有 2 个文件描述符 它们构成fd设置民意调查监视 一种用于引脚从高到低的变化 GPIO 另一个用于代理输入 代理输入出现问题 处理的顺序是 启动main函数 然

随机推荐

  • 【科普】一文读懂以太网PHY芯片

    物理层器件PHY Physical Layer Interface Devices 是将各网元连接到物理介质上的关键部件 负责完成互连参考模型 OSI 第1层中的功能 即为链路层实体之间进行bit传输提供物理连接所需的机械 电气 光电转换和
  • 嵌入式中锁机制杂谈

    在之前的文章中有提到操作系统中锁机制一般依赖于硬件CPU提供的原子数据操作指令 如SWP TEST AND SET等原子原语实现 基于此 才能真正保证锁机制的有效实现 通过上面原子操作 我们比较容易实现所谓的自旋操作 原子性的原地循环判断条
  • np.random.choice用法

    np random choice a size replace p 其作用是按要求生成一个一维数组 a是生成一维数组的来源 可以是int类型 可以是数组 也可以是list size 为从a中抽取的个数 即生成数组的维度 replace 表示
  • 《数据库系统》课程之实验七 通过ODBC/JDBC转移异构数据库中数据

    注 查看全文请关注作者 或点击前往 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 1 实验目的 学会配置ODBC JDBC数据源 熟悉使用ODBC
  • QueryWrapper方法解释

    继承自 AbstractWrapper 自身的内部属性 entity 也用于生成 where 条件 及 LambdaQueryWrapper 可以通过 new QueryWrapper lambda 方法获取 queryWrapper lt
  • PyTorch实战——搭建PyTorch神经网络进行气温预测

    如果觉得我的分享对您的学习有帮助 可以点赞关注哈 谢谢哈 目录 编辑 一 理论部分 二 代码实战 1 导入模块 1 matplotlib inline 2 warnings filterwarnings ignore 2 读入数据 3 展示
  • 三极管电路共集、共基、共射的区别

    共集 共基 共射指的是电路 是三极管电路的连接状态而不是三极管 所谓 共 就是输入 输出回路共有的部分 其判断是在交流等效电路下进行的 共集电极电路 三极管的集电极接地 集电极是输入与输出的公共极 共基极电路 三极管的基极接地 基极是输入与
  • 安装ubuntu系统时给/home分配空间太小,导致训练模型时数据集无法存放,所以给/home增大100GGB的存储空间

    1 从Windows系统中分配出100GB的存储空间 2 制作gparted的U盘启动项 3 插入U盘 进入bios界面 选择U盘启动项 4 进入gparted软件界面进行存储空间的转移重新分配 5 Exit退出 重新进入linux系统 参
  • 微信小程序 WebSocket 端口号配置

    https blog liuguofeng com p 4630 服务端开启 WebSocket 使用 WorkerMan phpSocket io 开启的端口为 2120 访问为 ws wanaioa unetu net 2120 由于微
  • 基于 java Swing 客户端 和 Spring Boot/Spring Cloud & Alibaba 后台管理系统

    基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统 基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统
  • 【Java JDK的使用方法】

    Java JDK的使用方法 第一步 同时按住窗口键和R键 在弹出的运行框中输入cmd打开编译框 第二步 输入cd 空格 地址 可以查看桌面文本文档的属性 找到桌面地址 第三步 notepad 空格 文件名 java 新建java文件 第四步
  • 何为UNP技术?

    为了解决移动视频监控系统中的这种穿NAT型 宇视科技特意提出了UNP UniversalNetwork Passport 万能网络护照 技术 目前 针对监控系统穿越NAT设备 防火墙和安全网闸时 基本上都是使用引流方案 内部服务器 双网口方
  • C++ 调用tensorflow

    安装protobuf 3 6 安装依赖软件 sudo apt get install autoconf automake libtool curl make g unzip 克隆版本为3 6 0的protobuf源码 git clone b
  • 8.翻转子串

    题目描述 假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串 请将这个算法编写成一个函数 给定两个字符串s1和s2 请编写代码检查s2是否为s1旋转而成 要求只能调用一次检查子串的函数 给定两个字符串s1 s2 请返回bool
  • 1-如何安装ROS

    如何安装ROS 大家好 我是如何 今天尝试在Ubantu下安装ROS Robot Operating System 测试环境 虚拟机VMware Ubantu20 04 准备步骤 添加ROS软件源 sudo sh c echo deb ht
  • C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点

    C 之普通成员函数 虚函数以及纯虚函数的区别与用法要点 作者 luoweifu 字体 增加 减小 类型 转载 时间 2015 07 21 我要评论 本篇文章主要介绍了C 中的普通成员函数 虚函数以及纯虚函数 非常的详细 有需要的朋友可以参考
  • localstorage在uc无痕模式失效问题;

    做项目的时候发现localstorage在uc 无痕模式下失效 但是其他浏览器不会出现此类问题 补充 我的解决方案是使用cookie代替localstorage 但是有大神给出了解决方案我觉得非常nice 附 https www jians
  • Thrift快速入门和简单示例

    文章目录 Thrift介绍 Thrift的架构 Thrift的特性 开发速度快 接口维护简单 学习成本低 多语言 跨语言支持 稳定 广泛使用 快速入门例子 编译安装 创建Thrift IDL文件 通过编译器编译user thrift文件 生
  • 马踏棋盘问题(C-数据结构)

    题目 在8 8的国际象棋棋盘中 给出马的初始位置 求出马踏遍棋盘每个位置的路线图 棋盘中每个位置只能走一次 思路 国际象棋中 马走的规则和中国象棋相似 为斜两格行走 即向任意方向走两格 再向与前面行走方向垂直的方向走一格 每个位置最多可以向
  • C语言,BMP格式解析,生成不同位深的图片。

    0 前言 目录 0 前言 1 BMP格式详解 1 1图片的构成 1 2BMP格式 1 2 1文件头 1 2 2位图信息头 1 2 3调色板 1 2 4位图数据 2 生成 3 总结 最近工作任务繁重且对我来说小有难度 但是没有困难的事情做起来