BMP图片读写实践:rgb转bgr
本实理论上支持24位图和32位图,实际上只测试了24位。原理很简单,就是RGB中的蓝色字节和红色字节交换。
测试代码1:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <string.h>
#include <stdint.h>
#include <jpeglib.h>#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%d -- "format"\n" \
,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif//Gray = 0.30 * R + 0.59 * G + 0.11 * B
uint8_t rgb888_to_gray(uint8_t r,uint8_t g,uint8_t b){return (uint8_t)(0.3 *(float)r + 0.59 * (float)g + 0.11 * (float)b);
}typedef uint16_t WORD;
typedef uint32_t DWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER{WORD bfType;//2DWORD bfSize;//4WORD bfReserved1;//2WORD bfReserved2;//2DWORD bfOffBits;//4
} BITMAPFILEHEADER;
#pragma pack()
typedef int32_t LONG;
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER{DWORD biSize;LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER; int main(int argc, char **argv)
{char *filename = "RGB.bmp";int fd = open(filename , O_RDONLY);if(fd <= 0){perror("open:");return -1;}struct tagBITMAPFILEHEADER * bit_map_file_header = malloc(sizeof(struct tagBITMAPFILEHEADER));struct tagBITMAPINFOHEADER * bit_map_info_header = malloc(sizeof(struct tagBITMAPINFOHEADER));DEBUG_INFO("%d %d",sizeof(struct tagBITMAPFILEHEADER),sizeof(struct tagBITMAPINFOHEADER));if(bit_map_file_header == NULL || bit_map_info_header == NULL){perror("malloc:");return -1;}//读取bmp的头信息read(fd , bit_map_file_header , 14);if(bit_map_file_header->bfType != 0x4D42){DEBUG_INFO("这不是BMP图片");return -1;}DEBUG_INFO("bfOffBits = %d",bit_map_file_header->bfOffBits);read(fd , bit_map_info_header , 40);DEBUG_INFO("width = %d,height = %d,biBitCount = %d\n" , bit_map_info_header->biWidth , bit_map_info_header->biHeight,bit_map_info_header->biBitCount);if(bit_map_info_header->biBitCount < 24){DEBUG_INFO("仅支持24位和32位的BMP图片");return -1;}if(bit_map_info_header->biWidth < 0){bit_map_info_header->biWidth = abs(bit_map_info_header->biWidth);}if(bit_map_info_header->biHeight < 0){bit_map_info_header->biHeight = abs(bit_map_info_header->biHeight);}DEBUG_INFO("width = %d,%d,biBitCount = %d\n" , bit_map_info_header->biWidth , bit_map_info_header->biHeight,bit_map_info_header->biBitCount);// return 0;int bmp_data_len = bit_map_info_header->biWidth * bit_map_info_header->biHeight * bit_map_info_header->biBitCount;DEBUG_INFO("bmp_data_len = %d",bmp_data_len);unsigned char *bmp_buf = malloc(bmp_data_len);if(bmp_buf == NULL){DEBUG_INFO("malloc error");return -1;}int ret = read(fd,bmp_buf,bmp_data_len);if(ret < 0){DEBUG_INFO("read error");return -1;}//把RGB转换成BGR,就是调用R和G的位置int index = 0;unsigned char tmp;while(bmp_data_len > index){tmp = bmp_buf[index + 0];bmp_buf[index + 0] = bmp_buf[index + 2];bmp_buf[index + 2] = tmp;index += (bit_map_info_header->biBitCount >> 3);}int bgr_bmp_fd = open("BGR.bmp",O_WRONLY | O_TRUNC | O_CREAT,0660);if(fd <= 0){perror("open:");return -1;}write(bgr_bmp_fd,bit_map_file_header,sizeof(struct tagBITMAPFILEHEADER));write(bgr_bmp_fd,bit_map_info_header,sizeof(struct tagBITMAPINFOHEADER));write(bgr_bmp_fd,bmp_buf,bmp_data_len);close(bgr_bmp_fd);close(fd);free(bmp_buf);return 0;
}
调试信息:
测试结果:
左边是转换之前,右边是转换之后。
由调试信息可知,选取的图片是720X336,也就是行4字节对齐的。换成721X336的图片,测试结果如下:果然出错了。
测试代码2:
修改后的颜色转换部分如下所示:这里主要解决了行4字节对齐的问题。
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <string.h>
#include <stdint.h>
#include <jpeglib.h>#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%d -- "format"\n" \
,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif//Gray = 0.30 * R + 0.59 * G + 0.11 * B
uint8_t rgb888_to_gray(uint8_t r,uint8_t g,uint8_t b){return (uint8_t)(0.3 *(float)r + 0.59 * (float)g + 0.11 * (float)b);
}typedef uint16_t WORD;
typedef uint32_t DWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER{WORD bfType;//2DWORD bfSize;//4WORD bfReserved1;//2WORD bfReserved2;//2DWORD bfOffBits;//4
} BITMAPFILEHEADER;
#pragma pack()
typedef int32_t LONG;
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER{DWORD biSize;LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER; char *src_file_name = "RGB2.bmp";
char *dst_file_name = "BGR2.bmp";int main(int argc, char **argv)
{int fd = open(src_file_name , O_RDONLY);if(fd <= 0){perror("open:");return -1;}struct tagBITMAPFILEHEADER * bit_map_file_header = malloc(sizeof(struct tagBITMAPFILEHEADER));struct tagBITMAPINFOHEADER * bit_map_info_header = malloc(sizeof(struct tagBITMAPINFOHEADER));DEBUG_INFO("%d %d",sizeof(struct tagBITMAPFILEHEADER),sizeof(struct tagBITMAPINFOHEADER));if(bit_map_file_header == NULL || bit_map_info_header == NULL){perror("malloc:");return -1;}//读取bmp的头信息read(fd , bit_map_file_header , 14);if(bit_map_file_header->bfType != 0x4D42){DEBUG_INFO("这不是BMP图片");return -1;}DEBUG_INFO("biSizebfOffBits = %d,bfSize = %d",bit_map_file_header->bfOffBits,bit_map_file_header->bfSize);read(fd , bit_map_info_header , 40);DEBUG_INFO("biSize = %d,width = %d,height = %d,biBitCount = %d,biPlanes = %d,\n\biCompression = %d,biSizeImage = %d,\n\biXPelsPerMeter = %d,biYPelsPerMeter = %d,\n\biClrUsed = %d,biClrImportant = %d\n" , bit_map_info_header->biSize,bit_map_info_header->biWidth , bit_map_info_header->biHeight,bit_map_info_header->biBitCount,bit_map_info_header->biPlanes,bit_map_info_header->biCompression,bit_map_info_header->biSizeImage,bit_map_info_header->biXPelsPerMeter,bit_map_info_header->biYPelsPerMeter,bit_map_info_header->biClrUsed,bit_map_info_header->biClrImportant);if(bit_map_info_header->biBitCount < 24){DEBUG_INFO("仅支持24位和32位的BMP图片");return -1;}if(bit_map_info_header->biWidth < 0){bit_map_info_header->biWidth = abs(bit_map_info_header->biWidth);}if(bit_map_info_header->biHeight < 0){bit_map_info_header->biHeight = abs(bit_map_info_header->biHeight);}DEBUG_INFO("width = %d,%d,biBitCount = %d\n" , bit_map_info_header->biWidth , bit_map_info_header->biHeight,bit_map_info_header->biBitCount);// return 0;unsigned char *bmp_buf = malloc(bit_map_file_header->bfSize);unsigned char *dst_bmp_buf = malloc(bit_map_file_header->bfSize);if(bmp_buf == NULL){DEBUG_INFO("malloc error");return -1;}int ret = read(fd,bmp_buf,bit_map_file_header->bfSize - 54);if(ret < 0){DEBUG_INFO("read error");return -1;}int w = bit_map_info_header->biWidth;int h = bit_map_info_header->biHeight;int biBitCount = bit_map_info_header->biBitCount;int color_byte = biBitCount/8;int offset_step;if((w * color_byte)%4){offset_step =((w*color_byte)/4+1)*4;}else{offset_step = w*color_byte;}DEBUG_INFO("offset_step = %d",offset_step);//把RGB转换成BGR,就是调用R和G的位置int index = 0;unsigned char tmp;int offset = 0;DEBUG_INFO("color_byte = %d",color_byte);int line=0;for(int i = 0 ; i < h; i++){for(int j = 0 ; j < w ; j++){int index = offset + j * color_byte;tmp = bmp_buf[index + 0 ];bmp_buf[index + 0 ] = bmp_buf[index + 2 ];bmp_buf[index + 2 ] = tmp; }offset += offset_step;}int bgr_bmp_fd = open(dst_file_name,O_WRONLY | O_TRUNC | O_CREAT,0660);if(fd <= 0){perror("open:");return -1;}write(bgr_bmp_fd,bit_map_file_header,sizeof(struct tagBITMAPFILEHEADER));write(bgr_bmp_fd,bit_map_info_header,sizeof(struct tagBITMAPINFOHEADER));write(bgr_bmp_fd,bmp_buf,bit_map_file_header->bfSize - 54);close(bgr_bmp_fd);close(fd);free(bmp_buf);return 0;
}
测试721x336,OK
在测一个571X673的,效果还是不错的。
调试信息:宽571,高673,行宽2284字节。
小结
相关文章:

BMP图片读写实践:rgb转bgr
本实理论上支持24位图和32位图,实际上只测试了24位。原理很简单,就是RGB中的蓝色字节和红色字节交换。 测试代码1: #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <stdlib.h> #include &l…...

交通科技与管理杂志社交通科技与管理编辑部2023年第9期目录
专家论坛 黑龙江省经济高质量发展与生态环境保护耦合协调发展研究 刘降斌;祃玉帅; 1-5142 我国省际数字经济高质量发展水平综合评价研究 耿娟;毕晨曦; 6-8 振兴龙江《交通科技与管理》投稿邮箱:cn7kantougao163.com(注明投稿“《交通科技与管理》”) 数…...

根据源码,模拟实现 RabbitMQ - 网络通讯设计,实现客户端Connection、Channel(完结)
目录 一、客户端代码实现 1.1、需求分析 1.2、具体实现 1)实现 ConnectionFactory 2)实现 Connection 3)实现 Channel 二、编写 Demo 2.1、实例 2.1、实例演示 一、客户端代码实现 1.1、需求分析 RabbitMQ 的客户端设定ÿ…...

The Cube++ Illumination Estimation Dataset 文章总结
The Cube++ Illumination Estimation Dataset 颜色恒常性数据集Cube++ Type: Academic Journal Author: Ershov Link: https://ieeexplore.ieee.org/document/9296220 Select: ⭐️⭐️⭐️⭐️ Status: Done 备注: Cube++数据集 Journal: ACCESS Year: 2020 code: https://g…...

“烧钱”的大模型,如何迈过存储这道坎?
几乎每一个行业都在讨论大模型,每一个行业巨头都在训练大模型,人工智能已然进入了大模型主导的时代。 想要占领大模型应用的高地,数据和算力可以说是不可或缺的基石。和算力相关的讨论已经有很多,以至于英伟达的市值在2023年翻了…...

UNIX网络编程卷一 学习笔记 第二十九章 数据链路访问
目前大多操作系统都为程序提供访问数据链路层的功能,此功能可提供以下能力: 1.能监视由数据链路层接收的分组,使得tcpdump之类的程序能运行,而无需专门的硬件设备来监视分组。如果结合使用网络接口进入混杂模式(promis…...

WebGIS的一些学习笔记
一、简述计算机网络的Internet 概念、网络类型分类、基本特征和功用是什么 计算机网络的Internet 概念 计算机网络是地理上分散的多台独立自主的计算机遵循约定的通讯协议,通过软、硬件互连以实现交互通信、资源共享、信息交换、协同工作以及在线处理等功能的系统…...

java Spring Boot将不同配置拆分入不同文件管理
关于java多环境开发 最后还有一个小点 我们一般会将不同的配置 放在不同的配置文件中 好处肯定就在于 想换的时候非常方便 那么 我们直接看代码 我们将项目中的 application.yml 更改代码如下 spring:profiles:active: dev这里 意思是 我们选择了dev 环境 然后创建一个文件 …...

Docker(三) 创建Docker镜像
一、在Docker中拉取最基本的Ubuntu系统镜像 搜索Ubuntu镜像 Explore Dockers Container Image Repository | Docker Hub 下载镜像 docker pull ubuntu:22.04 二、在镜像中添加自己的内容 使用ubuntu镜像创建容器 docker run -it ubuntu:20.04 /bin/bash 在容器中创建了一个文…...

Linux操作系统--shell编程(正则表达式)
1..正则表达式概述 正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep,sed,awk 等文本处理工具都支持通过正则表达式进行模式匹配。 2.常规的匹配操作 3.…...

k8s的service mesh功能有那些
Kubernetes(K8s)的服务网格(Service Mesh)是一种用于管理微服务架构中服务通信、安全性、可观察性等方面的工具集合。服务网格通过将网络和安全功能从应用程序代码中分离出来,帮助简化了微服务的部署和管理。以下是一些…...

【数据库技术】NineData数据复制,加速实时数仓构建
8 月 30 日,由 NineData 和 SelectDB 共同举办的主题为“实时数据驱动,引领企业智能化数据管理”的线上联合发布会,圆满成功举办!双方聚焦于实时数据仓库技术和数据开发能力,展示如何通过强大的生态开发兼容性…...

Kotlin入门1. 语法基础
Kotlin入门1. 语法基础 一、简介二、在Idea创建一个示例项目三、基本语法1. 第一个程序2. 基本数据类型(1) 数字(2) 类型转换(3) 数学运算位运算 (4)可空类型 3. 函数4. 字符串(1) 字符串拼接(2) 字符串查找(3) 字符串替换(4) 字符串分割 5. null 安全的…...

MVCC简介、工作流程、优缺点
目录 简介 相关概念 工作流程 MVCC优缺点 简介 MVCC(Multi-Version Concurrency Control)即多版本并发控制,是通过维护数据的历史版本,从而解决并发访问情况下的读一致性问题 相关概念 读锁: 也叫共享锁、S锁。若…...

pandas由入门到精通-pandas的数据结构
pandas数据分析-pandas的数据结构 pandas 数据结构Series1. 创建Series数组2. 性质3. 索引4. 运算DataFrame1. 创建Df数组2. 性质3.索引4. 对列进行增删改Index Objects本文介绍pandas中一些常用的属性方法的概述,给读者提供快速学习的架构和思路。表格中提供的一些参数方法没…...

jenkins+ssh+Putty构建windows的IIS服务发布
使用JenkinssshPutty发布windows IIS服务 下面是使用Jenkins、SSH和PuTTY实现Windows IIS服务发布的步骤: 在构建服务器上安装Windows SSH服务、PuTTY和7-Zip软件。在部署服务器上也安装Windows SSH服务和7-Zip软件。在构建服务器上使用批处理命令执行编译&#x…...

服务器和普通电脑有何区别?43.248.189.x
简单来讲,服务器和电脑的功能是一样的,我们也可以把服务器称之为电脑(PC机),只是服务器对稳定性与安全性以及处理器数据能力有更高要求,比如我们每天浏览一个网站,发现这个网站每天24小时都能访…...

Zookeeper的使用
一、Zookeeper简介 分布式协调框架,小型的树形结构数据共享储存系统。 zookeeper的应用场景 集群管理 注册中心 配置中心 发布者将数据发布到ZooKeeper一系列节点上面,订阅者进行数据订阅,当数据有变化时,可及时得到数据的变…...

【实用 Python 库】使用 XPath 与 lxml 模块在 Python 中高效解析 XML 与 HTML
在今天的信息时代,数据无处不在,从网络爬虫到数据挖掘,从文本处理到数据分析,我们时常需要从结构化文档中提取有用的信息。XPath 是一门强大的查询语言,它可以在 XML 与 HTML 等文档中定位特定的元素与数据。而在 Pyth…...

数据库的基本概念
数据库 数据库由表集合组成,它是以一定的组织方式存储的相互有关的数据集合。 表:记录:行,字段(属性):列,以行列的形式就组成了表(数据存储在表中)。 关系数…...

无涯教程-Android - 环境设置
您可以从Oracle的Java网站下载最新版本的Java JDK-Java SE下载,您将在下载的文件中找到有关安装JDK的说明,按照给定的说明安装和配置安装程序。最后,将PATH和JAVA_HOME环境变量设置为引用包含 java 和 javac 的目录,通常分别是java_install_dir/bin和java_install_d…...

将 ChatGPT 与 ReactJS 集成以实现更智能的对话界面
在本博客中,我们将探讨如何使用 Kommunicate 平台将 ChatGPT 与 ReactJS 集成,从而更轻松地在网站上部署和管理聊天机器人。 随着技术世界的不断发展,聊天机器人已成为许多企业不可或缺的一部分,提供高效、个性化的客户交互。在众多可用的人工智能聊天机器人解决方案中,C…...

关于xml中返回string类型代码中用list接收的问题,扫描
1.结论,xml中返回为string的话,在list中只会取出来第一个元素 //根据value查询GetMapping("getTest")public List<HashMap> getTest() {List<HashMap> list dictService.getTest();return list;} <select id"getTest" resultType"jav…...

【前端demo】CSS border-radius可视化 原生实现
文章目录 效果原理代码 前端demo系列目录:https://blog.csdn.net/karshey/article/details/132585901 效果 参考: Fancy Border Radius Generator (9elements.github.io) https://border-radius.com/ CSS border-radius 新玩法(含可视化生成工具) - …...

Qt Creator使用Clang Format方法
Qt Creator使用Clang Format 习惯性的想格式化代码,发现Qt Creator默认居然是没有代码格式化的,只有一个缩进。 Qt Creater中有个插件:beautifier,在"帮助->关于"插件中,开启“Beautifier”即可…...

智慧矿山2.0:煤矿智能化综合管理AI大数据监管平台建设方案设计
一、行业背景 能源与煤矿是我国国民经济的重要物质生产部门和支柱产业之一,同时也是一个安全事故多发的高危行业,施工阶段的现场管理对工程成本、进度、质量及安全等至关重要。煤矿智能化既是未来趋势,更是产业发展需求,建设智慧…...

Linux——(第一章)Linux的入门
VMwear workstations下载及安装 Ubuntu server 18.04安装 VScode下载与安装 使用VS Code连接远程服务器 MobaXterm的下载安装及远程连接 Filezila的下载、安装与使用(向服务器传输文件) 目录 1.概述 2.Linux和Windows的区别 3.VM的安装与使用 1.概述 …...

十六、策略模式
一、什么是策略模式 策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法…...

Python装饰器
什么是python装饰器? 顾名思义,从字面意思就可以理解,它是用来"装饰"Python的工具,使得代码更具有Python简洁的风格。换句话说,它是一种函数的函数,因为装饰器传入的参数就是一个函数࿰…...

【Spring】使用自定义注解方式实现AOP鉴权
AOP,是一种面向切面编程,可以通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 在软件开发中,鉴权(Authentication)是一项非常重要的安全措施,用于验证用户身份和权限。在应用程序中&…...