BMP图片读写实践:rgb转bgr

这篇具有很好参考价值的文章主要介绍了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;//2
    DWORD bfSize;//4
    WORD bfReserved1;//2
    WORD bfReserved2;//2
    DWORD 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;
}

调试信息:

BMP图片读写实践:rgb转bgr,linux 应用,BMP

测试结果:

左边是转换之前,右边是转换之后。

BMP图片读写实践:rgb转bgr,linux 应用,BMP 

由调试信息可知,选取的图片是720X336,也就是行4字节对齐的。换成721X336的图片,测试结果如下:果然出错了。 

BMP图片读写实践:rgb转bgr,linux 应用,BMP

测试代码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;//2
    DWORD bfSize;//4
    WORD bfReserved1;//2
    WORD bfReserved2;//2
    DWORD 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

BMP图片读写实践:rgb转bgr,linux 应用,BMP

 在测一个571X673的,效果还是不错的。

BMP图片读写实践:rgb转bgr,linux 应用,BMP

调试信息:宽571,高673,行宽2284字节。

BMP图片读写实践:rgb转bgr,linux 应用,BMP

 文章来源地址https://www.toymoban.com/news/detail-669771.html

小结

到了这里,关于BMP图片读写实践:rgb转bgr的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【超直白讲解opencv RGB与BGR】RGB模式与BGR模式有什么不同,如何相互转换?

    一、为什么会有BGR和RGB两种通道? 首先RGB与BGR本质都没有什么区别,OpenCV和PIL读取图片的格式分别是BGR和RGB。 当我们使用OpenCV读取图像时,你应该也会发现读取的数组其实是 BGR 格式,而不是我们听得最多、用得最多的 RGB 格式。那为什么要用BGR通道而不用RGB通道来描述图像

    2024年02月01日
    浏览(31)
  • OpenCV 实现BGR转RGB

    当使用opencv函数imread()读取图片时,颜色的顺序是BGR(blue、green、red),而Pillow的颜色顺序又是RGB,因此我们可能需要将BGR转RGB。 可以通过以下几种方法实现BGR转RGB 本文福利, 莬 费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目,C++语言基础,C++设计模式,Qt编程入

    2024年02月07日
    浏览(32)
  • 【Python OpenCV格式转换:RGB与BGR互转】

    【Python OpenCV格式转换:RGB与BGR互转】 图像处理中颜色空间的转换是一个重要的问题。其中,RGB与BGR是最常见的两种格式,而OpenCV是最流行的图像处理库之一。在OpenCV中,我们可以轻松地将RGB和BGR格式之间进行转换。 下面是如何使用Python OpenCV将RGB格式转换为BGR格式的代码示例

    2024年02月13日
    浏览(35)
  • RGB 与 BGR 颜色深度、像素和字节之间的关系

    在处理图像时,了解 RGB 和 BGR 色彩空间之间的区别非常重要。RGB 和 BGR 都具有三个颜色通道:红色、绿色和蓝色。但是,这些通道在图像文件中的存储顺序可能不同。 RGB 通常用于图像编辑和显示应用程序,顺序为红色、绿色和蓝色。 BGR 通常用于图像处理应用程序,顺序为

    2024年02月08日
    浏览(26)
  • 将一张RGB图像转换为BGR格式可以通过以下步骤实现

    读取图像:使用图像处理库(如OpenCV)读取一张RGB格式的图像,并将其存储为NumPy数组。 转换通道顺序:使用np.transpose函数将图像数组的通道顺序从RGB转换为BGR。 在这里,np.transpose函数的第一个参数是图像数组,第二个参数是元组,表示要交换的维度顺序。由于RGB格式的图像

    2024年02月11日
    浏览(57)
  • OpenCV读取图像时按照BGR的顺序HWC排列,PyTorch按照RGB的顺序CHW排列

    在OpenCV中,读取的图片默认是HWC格式,即按照高度、宽度和通道数的顺序排列图像尺寸的格式。我们看最后一个维度是C,因此最小颗粒度是C。 例如,一张形状为256×256×3的RGB图像,在OpenCV中读取后的格式为[256, 256, 3],其中最后一个维度表示图像的通道数。在OpenCV中,可以通

    2024年02月04日
    浏览(29)
  • 源码分享-golang的BMP文件读写库

    用于读写BMP文件的golang版源码 源码基于源码分享-golang的二进制文件读写库 https://blog.csdn.net/zhyulo/article/details/128890546 BMP文件格式可参考位图文件解析-位图(bmp)、图标(ico)与光标(cur) https://blog.csdn.net/zhyulo/article/details/85934728

    2024年01月22日
    浏览(27)
  • 第四十八章 解读RGB颜色机制,在图像处理中像素值越大意味着什么,OpenCV为什么使用 BGR 颜色格式

    RGB三原色起源于上世纪初1809年Thomas Young提出视觉的三原色学说,随后Helmholtz在1824年也提出了三原色学说:即:视网膜存在三种视锥细胞,分别含有对红、绿、蓝三种光线敏感的视色素,当一定波长的光线作用于视网膜时,以一定的比例使三种视锥细胞分别产生不同程度的兴

    2024年01月21日
    浏览(49)
  • 【opencv&c++编译问题汇总】‘CV_BGR2RGB‘、 “CV_AA“、CV_WINDOW_NORMAL、CV_CAP 报错

    情景一 报错 error: use of undeclared identifier \\\'CV_BGR2RGB\\\' 解决:添加头文件如下 情景二 报错 E0020 未定义标识符 \\\"CV_AA\\\" 解决:添加头文件如下 情形三 CV_CAP 系列报错 解决:由于新版本的opencv标识符发生变化,这类统统去掉“CV_”即可,如下列所示 类似的,可调窗口命令标识符如若

    2024年02月06日
    浏览(34)
  • “Python OpenCV 图像格式转换:RGB与BGR互转“——使用OpenCV库进行图像处理的过程中,经常需要进行不同格式之间的转换。其中最为常见的就是R...

    “Python OpenCV 图像格式转换:RGB与BGR互转”——使用OpenCV库进行图像处理的过程中,经常需要进行不同格式之间的转换。其中最为常见的就是RGB和BGR格式之间的转换。本文将详细介绍如何使用opencv-python库将图像从RGB格式转换为BGR格式以及从BGR格式转换为RGB格式。 要实现图像格

    2024年02月12日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包