RGB888转RGB666

Posted maxiongying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RGB888转RGB666相关的知识,希望对你有一定的参考价值。

内存中的数据排列高位在左,低位在右

RGB888->RGB666

      高 -------低

        B[3]         B[2]          B[1]         B[0]            B[3]             B[2]

RGB888  RRRRRRRR GGGGGGGG BBBBBBB RRRRRRRR  GGGGGGGG BBBBBBBB 

        A[2]           A[1]               A[0]                   A[2]              A[1]

RGB666 RRRRRRGG     GGGGBBBB     BBRRRRRR           GGGGGGBB    BBBB

 

RGB888->RGB565

             高-----------低

        B[2]          B[1]            B[0]

RGB888   RRRRRRRR GGGGGGGG  BBBBBBBB

        A[1]          A[0]

RGB565  RRRRRGGG   GGGBBBBB

 

代码

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <list>
using namespace std;

#define WIDTHBYTES(bits) (((bits)+31)/32*4)
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;

//位图文件头信息结构定义
//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)
typedef struct HS_tagBITMAPFILEHEADER{
    WORD bfType;//固定为0x4d42
    DWORD bfSize; //文件大小
    WORD bfReserved1; //保留字,不考虑
    WORD bfReserved2; //保留字,同上
    DWORD bfOffBits;//实际位图数据的偏移字节数,即前三个部分长度之和
}HS_BITMAPFILEHEADER;


//信息头BITMAPINFOHEADER,也是一个定义,其定义如下:
typedef struct HS_tagBITMAPINFOHEADER{
    DWORD biSize; //指定此结构体的长度,为40
    LONG biWidth; //位图宽
    LONG biHeight; //位图高
    WORD biPlanes; //平面数,为1
    WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
    DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩
    DWORD biSizeImage; //实际位图数据占用的字节数
    LONG biXPelsPerMeter; //X方向分辨率
    LONG biYPelsPerMeter; //Y方向分辨率
    DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
    DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的
}HS_BITMAPINFOHEADER;

//调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。
//(似乎是调色板结构体个数等于使用的颜色数。)

typedef struct HS_tagRGBQUAD {
    //public:
    BYTE rgbBlue; //该颜色的蓝色分量
    BYTE rgbGreen; //该颜色的绿色分量
    BYTE rgbRed; //该颜色的红色分量
    BYTE rgbReserved; //保留值
} HS_RGBQUAD;

void showBmpHead(HS_BITMAPFILEHEADER* pBmpHead)
{
    printf("位图文件头:\n");
    printf("bmp格式标志bftype:0x%x\n", pBmpHead->bfType);
    printf("文件大小:%d\n", pBmpHead->bfSize);
    printf("保留字1:%d\n", pBmpHead->bfReserved1);
    printf("保留字2:%d\n",pBmpHead->bfReserved2);
    printf("实际位图数据的偏移字节数:%d\n",pBmpHead->bfOffBits);
}

void showBmpInfoHead(HS_tagBITMAPINFOHEADER* pBmpInfoHead)
{
    printf("位图信息头:\n");
    printf("此结构体的长度:%d\n",pBmpInfoHead->biSize);
    printf("位图宽:%d\n",pBmpInfoHead->biWidth);
    printf("位图高:%d\n",pBmpInfoHead->biHeight);
    printf("biPlanes平面数:%d\n",pBmpInfoHead->biPlanes);
    printf("biBitCount采用颜色位数:%d\n",pBmpInfoHead->biBitCount);
    printf("压缩方式:%d\n",pBmpInfoHead->biCompression);
    printf("biSizeImage实际位图数据占用的字节数:%d\n",pBmpInfoHead->biSizeImage);
    printf("X方向分辨率:%d\n",pBmpInfoHead->biXPelsPerMeter);
    printf("Y方向分辨率:%d\n",pBmpInfoHead->biYPelsPerMeter);
    printf("使用的颜色数:%d\n",pBmpInfoHead->biClrUsed);
    printf("重要颜色数:%d\n",pBmpInfoHead->biClrImportant);
}

void showRgbQuan(HS_tagRGBQUAD* pRGB)
{
    printf("(%-3d,%-3d,%-3d) ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);

}

FILE *fp_write;

void writeRgb18Head(HS_tagBITMAPFILEHEADER* pBmpHead){
    fwrite(&pBmpHead->bfType, 1, 2, fp_write);
    fwrite(&pBmpHead->bfSize, 1, 4, fp_write);
    fwrite(&pBmpHead->bfReserved1, 1, 2, fp_write);
    fwrite(&pBmpHead->bfReserved2, 1, 2, fp_write);
    fwrite(&pBmpHead->bfOffBits, 1, 4, fp_write);
//    fwrite(pBmpHead, 1, 14, fp_write);
}

void writeRgb18InfoHead(HS_tagBITMAPINFOHEADER* pBmpInfoHead)
{
    fwrite(pBmpInfoHead, 1, 40, fp_write);
}


void rgb24_to_rgb565(BYTE* rgb24,BYTE* rgb16, int width, int height){
    int i = 0;
    int j = 0;
    for(i = 0; i < width*height; i += 3)
    {
        rgb16[j] = ( rgb24[i]  & 0xF1 ) >> 3;
        rgb16[j] |= ( rgb24[i+1] & 0x1C ) << 3;
        rgb16[j + 1] = rgb24[i+2] & 0xF8;
        rgb16[j + 1] |= (rgb24[i+1] & 0xF0) >> 5;
        j += 2;
    }

}

WORD rgb_24_2_565(int r, int g, int b)
{
    return (WORD)(((unsigned(r) << 8) & 0xF800) | 
        ((unsigned(g) << 3) & 0x7E0)  |
        ((unsigned(b) >> 3)));
}

void rgb24_to_rgb666(BYTE* rgb24,BYTE* rgb18, int width, int height){

    int i = 0;
    int j = 0;
    for(i = 0; i < width*height; i += 4)
    {

             rgb18[j] =  rgb24[i] >> 2;
            rgb18[j] = rgb18[j] | ( ( rgb24[i+1] & 0x0C ) << 4 );
         
             rgb18[j+1] = ( rgb24[i+1] & 0xF0 ) >>  4;
             rgb18[j+1] = rgb18[j+1] | ( ( rgb24[i+2] & 0x3C) << 2 );
        
             rgb18[j+2] = ( rgb24[i+2] & 0xC0 ) >> 6;
             rgb18[j+2] = rgb18[j+2] | rgb24[i+3] & 0xFC;
            j += 3;
    }
}

int find_all_files(const char * lpPath, list<string> *picturePath)
{
    char filePath[100] ;
    char szFind[MAX_PATH];
    WIN32_FIND_DATA FindFileData;
    strcpy(szFind,lpPath);
    strcat(szFind,"\\*.*");
    HANDLE hFind=::FindFirstFile(szFind,&FindFileData);
    if(INVALID_HANDLE_VALUE == hFind)   
        return -1;

    do
    {
        if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            if(strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName, "..")!=0)
            {
                //发现子目录,递归之
                char szFile[MAX_PATH] = {0};
                strcpy(szFile,lpPath);
                strcat(szFile,"\\");
                strcat(szFile,FindFileData.cFileName);
                find_all_files(szFile, picturePath);
            }
        }
        else
        {
            //找到文件,处理之
            string strPicturePath = lpPath;
            strPicturePath += "\\" ;
            strPicturePath += FindFileData.cFileName;
            picturePath->push_back(strPicturePath);
        }
    }while(::FindNextFile(hFind,&FindFileData));

    ::FindClose(hFind);

    return 0;
}

void main()
{
    HS_BITMAPFILEHEADER bitHead;
    HS_BITMAPINFOHEADER bitInfoHead;
    FILE* pfile;
    char filePath[50];
    char *BmpFileHeader;
    WORD *temp_WORD;
    DWORD *temp_DWORD;
    string strPicturePath;
    string strPictureName;

    printf("please input the file path:\n");
    scanf("%s",filePath);

    list<string> picturesPath;
    find_all_files(filePath, &picturesPath);

    BmpFileHeader=(char *)calloc(14,sizeof(char));

    for(list<string>::iterator it = picturesPath.begin(); it != picturesPath.end(); ++it){
        strPicturePath = *it;
        pfile = fopen(strPicturePath.c_str(),"rb");//打开文件

        if(pfile!=NULL)
        {
            memset(BmpFileHeader, 0, 14);
            fread(BmpFileHeader,1,14,pfile);
            temp_WORD=(WORD* )(BmpFileHeader);
            bitHead.bfType=*temp_WORD;
            if(bitHead.bfType != 0x4d42)
            {
                printf("file is not .bmp file!");
                continue;
            }
            temp_DWORD=(DWORD *)(BmpFileHeader+sizeof(bitHead.bfType));
            bitHead.bfSize=*temp_DWORD;
            temp_WORD=(WORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize));
            bitHead.bfReserved1=*temp_WORD;
            temp_WORD=(WORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize)+
                sizeof(bitHead.bfReserved1));
            bitHead.bfReserved2=*temp_WORD;
            temp_DWORD=(DWORD*)(BmpFileHeader+sizeof(bitHead.bfType)+sizeof(bitHead.bfSize)+sizeof(bitHead.bfReserved1)+sizeof(bitHead.bfReserved2));
            bitHead.bfOffBits=*temp_DWORD;
            //showBmpHead(&bitHead);
            //printf("\n\n");

            //写头文
            int indexName = strPicturePath.find_last_of("\\");
            strPictureName = strPicturePath.substr(indexName + 1);
            fp_write = fopen(strPictureName.c_str(), "wb");
            //fp_write = fopen("NC_001_16.bmp", "wb");
            //fp_write = fopen("NC_001_24.bmp", "wb");

            //读取位图信息头信息
            fread(&bitInfoHead,1,sizeof(HS_BITMAPINFOHEADER),pfile);
            bitHead.bfSize =  WIDTHBYTES(bitInfoHead.biWidth*18) * bitInfoHead.biHeight + 54;
            //bitHead.bfSize =  WIDTHBYTES(bitInfoHead.biWidth*16) * bitInfoHead.biHeight + 54;
            //bitHead.bfSize =  WIDTHBYTES(bitInfoHead.biWidth*24) * bitInfoHead.biHeight + 54;
            writeRgb18Head(&bitHead);

            //showBmpInfoHead(&bitInfoHead);
            //printf("\n");
            bitInfoHead.biBitCount = 18;
            //bitInfoHead.biBitCount = 16;
            //bitInfoHead.biBitCount = 24;
            bitInfoHead.biCompression = 0;
            bitInfoHead.biSizeImage = 0;
            bitInfoHead.biXPelsPerMeter = 0;
            bitInfoHead.biYPelsPerMeter = 0;
            bitInfoHead.biClrUsed = 0;
            bitInfoHead.biClrImportant = 0;
            writeRgb18InfoHead(&bitInfoHead);

            int width = bitInfoHead.biWidth;
            int height = bitInfoHead.biHeight;
            int l_width = WIDTHBYTES(width* 24);//计算位图的实际宽度并确保它为32的倍数
            BYTE *pColorData=(BYTE *)malloc(height*l_width);
            memset(pColorData,0,height*l_width);
            long nData = height*l_width;

            //把位图数据信息读到数组里
            fread(pColorData,1,nData,pfile);

            int width16 = WIDTHBYTES(width* bitInfoHead.biBitCount);
            BYTE* rgb16 = (BYTE*)malloc (width16* height);
            //rgb24_to_rgb565(pColorData,rgb16, l_width,height);
            rgb24_to_rgb666(pColorData,rgb16, l_width,height);
            fwrite(rgb16, 1, width16 * height, fp_write);

            fclose(pfile);
            fclose(fp_write);
            free(pColorData);
            free(rgb16);
        }
        else
        {
            printf("file open fail!\n");
        }
    }

    free(BmpFileHeader);

    printf("successed!");
}

 

以上是关于RGB888转RGB666的主要内容,如果未能解决你的问题,请参考以下文章

RGB565 怎么转 RGB888

RGB888 转 RGB565

C语言实现RGB888转BMP格式图片功能

ICN6202/ICN6202:MIPI转LVDS/mipi转RGB

ICN6211:MIPI DSI转RGB视频转换芯片方案介绍 看完涨知识了呢

C语言_数组的查找替换排序拼接