测试通过的C代码:平台无关的RGB保存为BMP格式的图片

简介: 测试通过的C代码:平台无关的RGB保存为BMP格式的图片

根据工作要求,得到视频数据。那么怎么证明视频数据是对的?转为BMP最简单了。这样一个想法,折腾了吾很久,找到了快10种代码,结果都不能用。后来终于找到了一个可用的(代码是部分的),看到保存出来的BMP图片,终于松了一口气。


 想直接用的朋友,去这里:https://github.com/quantum6/RgbToBmp


个人发现关键地方有:

  1. 文件头。
  2. 文件头的对齐。
  3. 每行数据的对齐。

 取之于网络,用之于网络,吾将代码公布出来:


1、这里处理的是ARGB,如果是RGB,注意差异。

2、宽度最好是32的倍数。如果不是,注意bytesPerLine对数据区的越界影响。

  • 主代码

看着这么整齐的代码,是不是赏心悦目?这么好的做法,阁下应该学习使用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned int    DWORD;
typedef int     LONG;
#define BITS_PER_PIXCEL 24
#define FORMAT_RGBA 4
#define FORMAT_RGB  3
/** must needed. pack */
#pragma pack(1)
typedef struct
{
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BMP_FILE_HEADER;
typedef struct{
    DWORD      biSize;
    LONG       biWidth;
    LONG       biHeight;
    WORD       biPlanes;
    WORD       biBitCount;
    DWORD      biCompression;
    DWORD      biSizeImage;
    LONG       biXPelsPerMeter;
    LONG       biYPelsPerMeter;
    DWORD      biClrUsed;
    DWORD      biClrImportant;
} BMP_INFO_HEADER;
#pragma pack()
int rgbaToBmpFile(const char *pFileName, const char* pRgbaData, const int nWidth, const int nHeight, const int format)
{
    BMP_FILE_HEADER bmpHeader;
    BMP_INFO_HEADER bmpInfo;
    FILE* fp         = NULL;
    char* pBmpSource = NULL;
    char* pBmpData   = NULL;
    int i = 0, j=0;
    //4 bytes pack. must be 4 times per line。
    int bytesPerLine = (nWidth*BITS_PER_PIXCEL+31)/32*4;
    int pixcelBytes  = bytesPerLine*nHeight;
    bmpHeader.bfType        = 0x4D42;
    bmpHeader.bfReserved1   = 0;
    bmpHeader.bfReserved2   = 0;
    bmpHeader.bfOffBits     = sizeof(BMP_FILE_HEADER) + sizeof(BMP_INFO_HEADER);
    bmpHeader.bfSize        = bmpHeader.bfOffBits     + pixcelBytes;
    bmpInfo.biSize          = sizeof(BMP_INFO_HEADER);
    bmpInfo.biWidth         = nWidth;
    /** 这样图片才不会倒置 */
    bmpInfo.biHeight        = -nHeight; 
    bmpInfo.biPlanes        = 1;
    bmpInfo.biBitCount      = BITS_PER_PIXCEL;
    bmpInfo.biCompression   = 0;
    bmpInfo.biSizeImage     = pixcelBytes;
    bmpInfo.biXPelsPerMeter = 100;
    bmpInfo.biYPelsPerMeter = 100;
    bmpInfo.biClrUsed       = 0;
    bmpInfo.biClrImportant  = 0;
    /** convert in memort, then write to file. */
    pBmpSource = (char*)malloc(pixcelBytes);
    if (!pBmpSource)
    {
        return -1;
    }
    /** open file */
    fp = fopen(pFileName,"wb+");
    if (!fp)
    {
        return -1;
    }
    fwrite(&bmpHeader, sizeof(BMP_FILE_HEADER), 1, fp);
    fwrite(&bmpInfo,   sizeof(BMP_INFO_HEADER), 1, fp);
    /** Here you should consider color format. RGBA ? RGB? BGR?
        Param format is RGBA, format for file is BGR */
    pBmpData = pBmpSource;
    for (i=0; i<nHeight; i++)
    {
        for (j=0; j<nWidth; j++)
        {
           pBmpData[0] = pRgbaData[2];
           pBmpData[1] = pRgbaData[1];
           pBmpData[2] = pRgbaData[0];
           pRgbaData  += format;
           pBmpData   += FORMAT_RGB;
        }
        //pack for 4 bytes
        pBmpData +=(bytesPerLine - nWidth*FORMAT_RGB);
    }
    fwrite(pBmpSource, pixcelBytes, 1, fp);
    /** close and release。 */
    fclose(fp);
    free(pBmpSource);
    return 0;
}
  • 剪裁
int clipRgbaToBmpFile(const char *pFileName, const char* pRgbaData,
    const int nWidth, const int nHeight, const int format,
    const int nClipLeft, const int nClipTop, const int nClipWidth, const int nClipHeight)
{
    char* pClipSource     = NULL;
    char* pClipData       = NULL;
    int pixcelBytes       = nClipWidth*nClipHeight*format;
    int i = 0;
    pClipSource = (char*)malloc(pixcelBytes);
    if (!pClipSource)
    {
        return -1;
    }
    //move to right position
    pRgbaData += nClipTop  * nWidth * format;
    pRgbaData += nClipLeft          * format;
    pClipData = pClipSource;
    for (i=0; i<nClipHeight; i++)
    {
        memcpy(pClipData, pRgbaData, nClipWidth*format);
        pRgbaData += nWidth    * format;
        pClipData += nClipWidth* format;
    }
    rgbaToBmpFile(pFileName, pClipSource, nClipWidth, nClipHeight, format);
    //release
    free(pClipSource);
    return 0;
}
  • 调用范例

  此文貌似是网上第一个正确产生BMP的代码。很多人搜索到了之后,说是不知道怎么用。本来吾以为这是很简单的事情。从评论中看到有的朋友对编程都不是太了解,于是,吾决定加个调用范例。

  以下代码通过测试,可以产生红色BMP图片。各位修改宽高颜色等。

int main(const int argc, const char** argv)
{
    int  width  = 640;
    int  height = 360;
    int  format = FORMAT_RGB;
    char colorR = 0xFF;
    char colorG = 0x00;
    char colorB = 0x00;
    int size=width*height*format;
    char* pRgb=(char*)malloc(size);
    for (int i=0; i<width*height; i++)
    {
        pRgb[i*format]   = colorR;
        pRgb[i*format+1] = colorG;
        pRgb[i*format+2] = colorB;
    }
    rgbaToBmpFile((char*)"test.bmp", pRgb, width, height, format);
    free(pRgb);
}
  • 编译
gcc \
    rgb2bmp.cpp \
    -o rgb2bmp



祝愿大家身体健康,工作顺利。

目录
相关文章
|
9月前
livp图片怎么打开以及怎么转换成jpg格式教程
livp图片怎么打开以及怎么转换成jpg格式教程
|
4月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
32 0
测试通过的C代码:平台无关的RGB保存为BMP格式的图片
测试通过的C代码:平台无关的RGB保存为BMP格式的图片
75 0
|
Java
摄像头NV21格式转RGB的JAVA代码,测试正确
摄像头NV21格式转RGB的JAVA代码,测试正确
175 0
将RGB转换为JPG格式到内存的代码
将RGB转换为JPG格式到内存的代码
126 0
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
|
数据采集 存储 传感器
【Android RTMP】x264 图像数据编码 ( NV21 格式中的 YUV 数据排列 | Y 灰度数据拷贝 | U 色彩值数据拷贝 | V 饱和度数据拷贝 | 图像编码操作 )
【Android RTMP】x264 图像数据编码 ( NV21 格式中的 YUV 数据排列 | Y 灰度数据拷贝 | U 色彩值数据拷贝 | V 饱和度数据拷贝 | 图像编码操作 )
339 0
|
存储 编解码 C语言
C语言代码创建、解析BMP格式图片
BMP格式的图片是众多图片格式中的一种,也称为位图数据,BMP结构也比较简单,不需要依赖任何外部库,直接手撸几十行代码即可完成解码编码,非常方便。
353 0
|
API 语音技术 Python
Python 技术篇-用base64库对音频、图片等文件进行base64编码和解码实例演示
Python 技术篇-用base64库对音频、图片等文件进行base64编码和解码实例演示
892 0
Python 技术篇-用base64库对音频、图片等文件进行base64编码和解码实例演示
|
Python
Python 技术篇-用PIL库修改图片透明度实例演示,改变png图片色道为RGBA、RGB
Python 技术篇-用PIL库修改图片透明度实例演示,改变png图片色道为RGBA、RGB
872 0
Python 技术篇-用PIL库修改图片透明度实例演示,改变png图片色道为RGBA、RGB