內存中的數據排列高位在左,低位在右
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!"); }