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字节。

 

小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/109916.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pdf.js构建时,报Cannot read property ‘createChildCompiler‘ of undefined #177的解决方法

在本地和CI工具进行构建时&#xff0c;报如下错误。 Cannot read property createChildCompiler of undefined #177解决方法&#xff1a; 找到vue.config.js&#xff0c;在 module.exports {parallel: false, //新增的一行chainWebpack(config) {....config.module.rule(&…

Docker搭建Redis集群

Docker搭建Redis集群 一 、搭建Redis集群的优点 先说说单个redis的缺点&#xff1a; 1、单个redis具有不稳定性。当redis服务死机了或者redis服务被kill掉了&#xff0c;就没有可用的redis服务了。 2、单个redis的读写能力是有限的。 再根据单个redis服务的缺点谈谈redis集群的…

计算机视觉 – Computer Vision | CV

计算机视觉为什么重要&#xff1f; 人的大脑皮层&#xff0c; 有差不多 70% 都是在处理视觉信息。 是人类获取信息最主要的渠道&#xff0c;没有之一。 在网络世界&#xff0c;照片和视频&#xff08;图像的集合&#xff09;也正在发生爆炸式的增长&#xff01; 下图是网络上…

LVS集群 (四十四)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、集群概述 1. 负载均衡技术类型 2. 负载均衡实现方式 二、LVS结构 三、LVS工作模式 四、LVS负载均衡算法 1. 静态负载均衡 2. 动态负载均衡 五、ipvsadm命令详…

【分析绘图】R语言实现一些常见的绘图

微生信-在线绘图网站 线性图 library(ggplot2)x <- rnorm(100, 14, 5) # rnorm(n, mean 0, sd 1) y <- x rnorm(100, 0, 1) ggplot(data NULL, aes(x x, y y)) # 开始绘图geom_point(color "darkred") # 添加点annotate("text",x 13,…

Mybatis小记

目录 Mybatis第一个程序 xml文件 测试类 错误排查 Mybatis第一个程序 1.搭建实验数据库 2.导入MyBatis相关jar包 3.编写MyBatis核心配置文件 4.编写MyBatis工具类 5.创建实体类、 6.编写Mapper接口类 7.编写Mapper.xml配置文件 8.编写测试类 对象传参只引用需要的属性就可…

springcloud3 GateWay章节-Nacos+gateway(跨域,filter过滤等5

一 常用工具类 1.1 结构 1.2 跨域 Configuration public class CorsConfig {Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowe…

lua的函数

1.一个示例实现列表的元素的求和 [root]# more funcAdd.lua function add(a)local sum 0for i 1,#a dosum sum a[i]endreturn sum enda {1,2,3,4,5,6}local sum add(a)print(sum)

Flask入门一 ——虚拟环境及Flask安装

Flask入门一 ——虚拟环境及Flask安装 在大多数标准中&#xff0c;Flask都算是小型框架&#xff0c;小到可以称为“微框架”&#xff0c;但是并不意味着他比其他框架功能少。Flask自开发伊始就被设计为可扩展的框架。Flask具有一个包含基本服务的强健核心&#xff0c;其他功能…

大模型理解之CLIP

前言 2021年2月份&#xff0c;CLIP模型被提出&#xff0c;想法很简单&#xff0c;性能高效&#xff0c;而且具备很好的泛化性。我在这里简单谈论下我对CLIP模型的理解&#xff0c;以及发现的一些问题。 我是在沐神的视频中了解的CLIP, 里面提到CLIP最大的贡献在于打破了固定类…

ELK之LogStash介绍及安装配置

一、logstash简介 集中、转换和存储数据 Logstash 是免费且开放的服务器端数据处理管道&#xff0c;能够从多个来源采集数据&#xff0c;转换数据&#xff0c;然后将数据发送到您最喜欢的“存储库”中。 Logstash 能够动态地采集、转换和传输数据&#xff0c;不受格式或复杂度的…

10.Oracle中decode函数

【函数格式】&#xff1a; decode ( expression, condition_01, result_01, condition_02, result_02, ......, condition_n, result_n, result_default) 【函数说明】&#xff1a; 若表达式expression值与condition_01值匹配&#xff0c;则返回result_01&#xff0c;…

[ DPU / SmartNIC/ 网卡 ]系统级的测试验证

开局一张图&#xff0c;其他慢慢来编 信雅纳DPU测试解决方案荣获第三届DPU峰会的“匠芯技术奖” 看完这张&#xff0c;小编再送一张&#xff1a;&#xff1a;&#xff1a; 网卡进化 更智能的加速卡SmartNIC/DPU 例如&#xff0c;将部分网络协议处理的功能卸载到 DPU 网卡&am…

初试Eureka注册中心

Eureka是spring cloud中的一个负责服务注册与发现的组件。遵循着CAP理论中的A(可用性)P(分区容错性)。一个Eureka中分为eureka server和eureka client。其中eureka server是作为服务的注册与发现中心。 搭建eureka服务 引入eureka依赖 引入SpringCloud为eureka提供的starter依…

Arcgis colorRmap

arcgis中colorRmap对应的名称&#xff1a; 信息来源&#xff1a;https://developers.arcgis.com/documentation/common-data-types/raster-function-objects.htm 在arcpy中使用方法&#xff1a; import arcpy cr arcpy.mp.ColorRamp("Yellow to Red")python中 ma…

Python“牵手”淘宝商品列表数据,关键词搜索淘宝API接口数据,淘宝API接口申请指南

淘宝平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范&#xff0c;淘宝API接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问淘宝平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现淘宝平台…

【面试题】MVC、MVP与MVVM模式是什么?

MVC模式 MVC是应用最广泛的软件架构之一&#xff0c;一般MVC分为&#xff1a; Model&#xff08; 模型 &#xff09;、Controller&#xff08; 控制器 &#xff09;、View&#xff08; 视图 &#xff09;。 这主要是基于分层的目的&#xff0c;让彼此的职责分开。View 一般…

leetcode875. 爱吃香蕉的珂珂(java)

二分查找 爱吃香蕉的珂珂二分查找 上期经典 爱吃香蕉的珂珂 难度 - 中等 LC - 875.爱吃香蕉的珂珂 珂珂喜欢吃香蕉。这里有 n 堆香蕉&#xff0c;第 i 堆中有 piles[i] 根香蕉。警卫已经离开了&#xff0c;将在 h 小时后回来。 珂珂可以决定她吃香蕉的速度 k &#xff08;单位&…

Apache StreamPark系列教程第一篇——安装和体验

一、StreamPark介绍 实时即未来,在实时处理流域 Apache Spark 和 Apache Flink 是一个伟大的进步,尤其是Apache Flink被普遍认为是下一代大数据流计算引擎, 我们在使用 Flink & Spark 时发现从编程模型, 启动配置到运维管理都有很多可以抽象共用的地方, 我们将一些好的经验…

Unity关键概念

Unity是一款跨平台的游戏引擎和开发工具&#xff0c;用于创建2D和3D游戏、交互式内容和应用程序。它提供了一个强大的开发环境&#xff0c;使开发者能够轻松地设计、开发和部署高质量的游戏和应用程序。 以下是Unity的几个关键概念&#xff1a; 游戏对象&#xff08;Game Obj…