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.hqwc.cn/news/91499.html

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

相关文章

Apipost:为什么是开发者首选的API调试工具

文章目录 前言正文接口调试接口公共参数、环境全局参数的使用快速生成并导出接口文档研发协作接口压测和自动化测试结论 前言 Apipost是一款支持 RESTful API、SOAP API、GraphQL API等多种API类型&#xff0c;支持 HTTPS、WebSocket、gRPC多种通信协议的API调试工具。除此之外…

C# Linq源码分析之Take(四)

概要 本文主要对Take的优化方法进行源码分析&#xff0c;分析Take在配合Select&#xff0c;Where等常用的Linq扩展方法使用时候&#xff0c;如何实现优化处理。 本文涉及到Select, Where和Take和三个方法的源码分析&#xff0c;其中Select, Where, Take更详尽的源码分析&…

uniapp 微信小程序仿抖音评论区功能,支持展开收起

最近需要写一个评论区功能&#xff0c;所以打算仿照抖音做一个评论功能&#xff0c;支持展开和收起&#xff0c; 首先我们需要对功能做一个拆解&#xff0c;评论区功能&#xff0c;两个模块&#xff0c;一个是发表评论模块&#xff0c;一个是评论展示区。接下来对这两个模块进行…

13.108.Spark 优化、Spark优化与hive的区别、SparkSQL启动参数调优、四川任务优化实践:执行效率提升50%以上

13.108.Spark 优化 1.1.25.Spark优化与hive的区别 1.1.26.SparkSQL启动参数调优 1.1.27.四川任务优化实践&#xff1a;执行效率提升50%以上 13.108.Spark 优化&#xff1a; 1.1.25.Spark优化与hive的区别 先理解spark与mapreduce的本质区别&#xff0c;算子之间&#xff08;…

报文信息转换器

HttpMessageConverter HttpMessageConverter:报文信息转换器&#xff0c;将请求报文转换为Java对象&#xff0c;或将Java对象转换为响应报文。它提供了两个注解和两个类型&#xff1a; RequestBody, ResponseBody, RequestEntity, ResponseEntity(响应用的较多) 准备 创建模块并…

【无标题】8.31在华清

可以登录但是不能跳转

区块链金融项目怎么做?

区块链技术的兴起引发了金融领域的变革&#xff0c;为金融行业带来了前所未有的机遇与挑战。在这个快速发展的领域中&#xff0c;如何在区块链金融领域做出卓越的表现&#xff1f;本文将从专业性和思考深度两个方面&#xff0c;探讨区块链金融的发展路径&#xff0c;并为读者提…

5分钟看懂物料清单(BOM)的用途、类型及管理

管理物料可以提高制造和供应链流程的效率&#xff0c;例如生产、物流、调度、产品成本核算和库存计划。企业通常使用物料清单作为制造产品的组件、材料和流程的中央记录。 物料清单&#xff08;BOM&#xff09;是构建、制造或维修产品或服务所需的原材料、组件和说明的详细列表…

centos安装MySQL 解压版完整教程(按步骤傻瓜式安装

一、卸载系统自带的 Mariadb 查看&#xff1a; rpm -qa|grep mariadb 卸载&#xff1a; rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64 二、卸载 etc 目录下的 my.cnf 文件 rm -rf /etc/my.cnf 三、检查MySQL是否存在 有则先删除 #卸载mysql服务以及删除所有mysql目录 #没…

如何在不重新安装的情况下将操作系统迁移到新硬盘?

通常情况下&#xff0c;当你的硬盘损坏或文件过多时&#xff0c;电脑会变得缓慢且卡顿。这时&#xff0c;你可能会被建议更换为一块更好的新硬盘。 ​ 在比较HDD和SSD之后&#xff0c;许多用户更愿意选择SSD作为他们的新硬盘&#xff0c;因为SSD比HDD更稳定且运行更安…

ELK安装、部署、调试(五)filebeat的安装与配置

1.介绍 logstash 也可以收集日志&#xff0c;但是数据量大时太消耗系统新能。而filebeat是轻量级的&#xff0c;占用系统资源极少。 Filebeat 由两个主要组件组成&#xff1a;harvester 和 prospector。 采集器 harvester 的主要职责是读取单个文件的内容。读取每个文件&…

基于SpringBoot+Vue的旅游系统

摘 要 随着旅游业的发展&#xff0c;越来越多的人选择旅游作为自己的出行方式。在旅游规划过程中&#xff0c;旅游景点选择是至关重要的环节。本文提出了一种基于协同过滤推荐算法的旅游平台系统。该系统采用前后端分离的设计&#xff0c;主要使用了SpringBoot、Vue等技术&…