当前位置: 首页 > news >正文

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位图&#xff0c;实际上只测试了24位。原理很简单&#xff0c;就是RGB中的蓝色字节和红色字节交换。 测试代码1&#xff1a; #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <stdlib.h> #include &l…...

交通科技与管理杂志社交通科技与管理编辑部2023年第9期目录

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

根据源码,模拟实现 RabbitMQ - 网络通讯设计,实现客户端Connection、Channel(完结)

目录 一、客户端代码实现 1.1、需求分析 1.2、具体实现 1&#xff09;实现 ConnectionFactory 2&#xff09;实现 Connection 3&#xff09;实现 Channel 二、编写 Demo 2.1、实例 2.1、实例演示 一、客户端代码实现 1.1、需求分析 RabbitMQ 的客户端设定&#xff…...

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…...

“烧钱”的大模型,如何迈过存储这道坎?

几乎每一个行业都在讨论大模型&#xff0c;每一个行业巨头都在训练大模型&#xff0c;人工智能已然进入了大模型主导的时代。 想要占领大模型应用的高地&#xff0c;数据和算力可以说是不可或缺的基石。和算力相关的讨论已经有很多&#xff0c;以至于英伟达的市值在2023年翻了…...

UNIX网络编程卷一 学习笔记 第二十九章 数据链路访问

目前大多操作系统都为程序提供访问数据链路层的功能&#xff0c;此功能可提供以下能力&#xff1a; 1.能监视由数据链路层接收的分组&#xff0c;使得tcpdump之类的程序能运行&#xff0c;而无需专门的硬件设备来监视分组。如果结合使用网络接口进入混杂模式&#xff08;promis…...

WebGIS的一些学习笔记

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

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&#xff08;K8s&#xff09;的服务网格&#xff08;Service Mesh&#xff09;是一种用于管理微服务架构中服务通信、安全性、可观察性等方面的工具集合。服务网格通过将网络和安全功能从应用程序代码中分离出来&#xff0c;帮助简化了微服务的部署和管理。以下是一些…...

【数据库技术】NineData数据复制,加速实时数仓构建

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

Kotlin入门1. 语法基础

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

MVCC简介、工作流程、优缺点

目录 简介 相关概念 工作流程 MVCC优缺点 简介 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;即多版本并发控制&#xff0c;是通过维护数据的历史版本&#xff0c;从而解决并发访问情况下的读一致性问题 相关概念 读锁&#xff1a; 也叫共享锁、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服务发布的步骤&#xff1a; 在构建服务器上安装Windows SSH服务、PuTTY和7-Zip软件。在部署服务器上也安装Windows SSH服务和7-Zip软件。在构建服务器上使用批处理命令执行编译&#x…...

服务器和普通电脑有何区别?43.248.189.x

简单来讲&#xff0c;服务器和电脑的功能是一样的&#xff0c;我们也可以把服务器称之为电脑&#xff08;PC机&#xff09;&#xff0c;只是服务器对稳定性与安全性以及处理器数据能力有更高要求&#xff0c;比如我们每天浏览一个网站&#xff0c;发现这个网站每天24小时都能访…...

Zookeeper的使用

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

【实用 Python 库】使用 XPath 与 lxml 模块在 Python 中高效解析 XML 与 HTML

在今天的信息时代&#xff0c;数据无处不在&#xff0c;从网络爬虫到数据挖掘&#xff0c;从文本处理到数据分析&#xff0c;我们时常需要从结构化文档中提取有用的信息。XPath 是一门强大的查询语言&#xff0c;它可以在 XML 与 HTML 等文档中定位特定的元素与数据。而在 Pyth…...

数据库的基本概念

数据库 数据库由表集合组成&#xff0c;它是以一定的组织方式存储的相互有关的数据集合。 表&#xff1a;记录&#xff1a;行&#xff0c;字段&#xff08;属性&#xff09;&#xff1a;列&#xff0c;以行列的形式就组成了表&#xff08;数据存储在表中&#xff09;。 关系数…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...