由於屏幕的多種類性, 我始終沒有使用市面上的那種取模軟件, 我始終感覺數據可能不對.
因為我的屏幕的要求比例是R:G:B(5:6:5),16位色,一個像素2個字節保存,所以總覺得應該自己寫
一個來做這種轉換工作的軟件.
今天寫了個小程序,在彩屏上顯示出來的效果很好. 程序是為我的屏幕的數據類型量身生成的,
寫在這里只是保存一下,不然久了,我又不知道代碼之前的版本, 或是又找不到了.
程序解析BMP圖像數據到點陣字模(僅支持24位位深的BMP位圖,現在大都是這種),生成是數據
是16位的無符號字符型數據數組.直接調用寫進屏幕即可顯示出來.
代碼分兩個文件:bmconv.h,bmconv.c
//bmconv.h #ifndef __BMCONV_H__ #define __BMCONV_H__ #pragma pack(push,1) //位圖文件頭數據 typedef struct _BITMAP_FILE_HEADER{ unsigned char signature[2]; //00~01:文件頭簽名字節,僅檢測'BM'序 unsigned long file_size; //02~05:整個文件的大小 unsigned long _reserved1; //06~09:保留4字節,必須為0 unsigned long data_offset; //0A~0D:位圖數據距文件開始的偏移 }BITMAP_FILE_HEADER; //圖像信息頭數據 typedef struct _BITMAP_INFO_HEADER{ unsigned long header_size; //0E~11:位圖信息頭的長度,根據文件判斷 unsigned long width; //12~15:位圖寬度,像素為單位 unsigned long height; //16~19:位圖高度,像素為單位 unsigned short planes; //1A~1B:位圖的面數,該值總是1 unsigned short bpp; //1C~1D:位深:1,4,8,16,24,32 unsigned long compress; //1E~21:壓縮說明 unsigned long data_size; //22~25:數據大小 unsigned long hresolution; //26~29:水平分辨率 unsigned long vresolution; //2A~2D:垂直分辨率 unsigned long colors; //2E:31:使用的顏色數 unsigned long colors_important; //重要的顏色數 }BITMAP_INFO_HEADER; //顏色表 typedef struct _RGBQUAD{ unsigned char blue; unsigned char green; unsigned char red; unsigned char _reserved; }BITMAP_RGB_QUAD; //由圖像信息頭+顏色表組成的圖像信息 typedef struct _BITMAP_INFO{ BITMAP_INFO_HEADER bmih; BITMAP_RGB_QUAD bmcolor; }BITMAP_INFO; #pragma pack(pop) #endif//!__BMCONV_H__
//bmconv.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "bmconv.h" /************************************************************************* 文件名稱:bmconv.c/bmconv.h 文件功能:BMP提取到點陣RGB顯示 創建時間:2013-04-20 文件作者:女孩不哭 文件版本:1.0 文件說明:專用 *************************************************************************/ __inline unsigned int myrgb(int a) { unsigned short b = (a&0xff)>>3; unsigned short g = ((a&0xff00)>>10); unsigned short r = ((a&0xff0000)>>19); unsigned int rgb = (b|(g<<5)|(r<<11)); return rgb; } int main(void) { char file[260]; char file_out[260]; char* pstr = NULL; unsigned char* buffer=NULL; char* outout_data = NULL; BITMAP_FILE_HEADER bmfh={0}; BITMAP_INFO_HEADER bmih={0}; FILE* fpin = NULL; FILE* fpout = NULL; size_t size = 0; size_t file_size; printf("輸入BMP文件打開路徑:"); fgets(file,sizeof(file),stdin); pstr = strrchr(file,'\n'); if(pstr) *pstr = 0; printf("輸入BMP文件保存路徑:"); fgets(file_out,sizeof(file_out),stdin); pstr = strrchr(file_out,'\n'); if(pstr) *pstr = 0; fpin = fopen(file,"rb"); if(fpin==NULL){ fprintf(stderr,"打開輸入文件錯誤!\n"); return 1; } fpout = fopen(file_out,"wb"); if(fpout==NULL){ fprintf(stderr,"打開輸出文件錯誤!\n"); fclose(fpin); return 1; } fseek(fpin,0,SEEK_END); file_size = ftell(fpin); fseek(fpin,0,SEEK_SET); size = fread(&bmfh,1,sizeof(bmfh),fpin); if(size != sizeof(bmfh)){ fclose(fpin); fprintf(stderr,"讀取文件頭時錯誤!\n"); return 1; } if(bmfh.signature[0]!='B' || bmfh.signature[1]!='M'){ fclose(fpin); fprintf(stderr,"不是BMP文件!\n"); return 1; } printf( "文件頭結構體大小:%d\n" "文件頭簽名:\'BM\'\n" "文件大小:%u bytes\n" "保留4字節值:%u\n" "位圖數據距文件開始的偏移:%u\n\n",(long)sizeof(bmfh), bmfh.file_size,bmfh._reserved1,bmfh.data_offset); size = fread(&bmih,1,sizeof(bmih),fpin); if(size != sizeof(bmih)){ fclose(fpin); fprintf(stderr,"讀取圖像信息頭錯誤!\n"); return 1; } printf( "圖像信息頭結構體大小:%d\n" "圖像信息頭大小:%d bytes\n" "位圖寬度: %u 像素\n" "位圖高度: %u 像素\n" "位圖面數: %d 面\n" "位深: %d bpp\n" "壓縮說明: %d\n" "位圖數據大小: %u bytes\n" "水平分辨率: %u 像素/米\n" "垂直分辨率: %u 像素/米\n" "使用的顏色數: %u\n" "重要的顏色數: %u\n\n",(long)sizeof(bmih), bmih.header_size,bmih.width,bmih.height,bmih.planes,bmih.bpp,bmih.compress, bmih.data_size,bmih.hresolution,bmih.vresolution,bmih.colors,bmih.colors_important); //檢測文件數據大小是否符合文件頭 size = bmih.width*3; size += size%4==0?0:4-size%4; size *= bmih.height; if(size != file_size-bmfh.data_offset){ fprintf(stderr,"位圖的數據量與文件頭所標識的數據量的長度不一致!\n"); fclose(fpin); return 1; } if(bmih.bpp != 24){ fprintf(stderr,"不是24位位深的BMP位圖,不被支持!\n"); fclose(fpin); return 1; } buffer=(unsigned char*)malloc(size); //printf("buffer大小:%d\n",size); if(buffer==NULL){ fprintf(stderr,"分配文件緩沖區時出錯!\n"); fclose(fpin); return 1; } if(size != fread(buffer,1,size,fpin)){ fprintf(stderr,"讀取位圖數據時讀取的長度不一致!\n"); free(buffer); fclose(fpin); return 1; } fclose(fpin); //交換上下內存 for(;;){ int bytes_line = size/bmih.height; int rows = bmih.height/2; int it=0; unsigned char* tmp = (unsigned char*)malloc(bytes_line); while(it<rows){ memcpy(tmp,buffer+bytes_line*it,bytes_line); memcpy(buffer+bytes_line*it,buffer+(bmih.height-1-it)*bytes_line,bytes_line); memcpy(buffer+(bmih.height-1-it)*bytes_line,tmp,bytes_line); it++; } free(tmp); break; } //總像素點個數(一個像素3個字節),3個字節轉換成2個字節,2個字節轉成字符串需要7個字節空間(0x0000,) //每行后面1個換行符(每行16個"0x0000,",2個字節),字符串開始的結束的字符串("unsigned char image[] = {" + 換行 + "};" for(;;){ size_t pixels = bmih.width*bmih.height; size_t str_length = pixels*7; size_t crlf_count = pixels/16 + (pixels%16==0?0:1); size_t prefix_length = sizeof("unsigned short image[] = {\r\n")-1 + sizeof("};\r\n")-1; size_t total = str_length+crlf_count*2+prefix_length+1; outout_data = (char*)malloc(total); //printf("str:%d,crlf:%d,prefix:%d,total::%d\n",str_length,crlf_count*2,prefix_length,total); if(outout_data == NULL){ fprintf(stderr,"申請保存數據用的緩沖區失敗!\n"); free(buffer); return 1; } printf("正在生成數據...\n"); for(;;){ char* ptr = outout_data; unsigned char* pbuf = buffer; int count = 0; unsigned long lines; int skip = (bmih.width*3%4)?(4-bmih.width*3%4):0; int len; len=sprintf(ptr,"unsigned short image[] = {\r\n"); ptr += len; for(lines=0;lines<bmih.height;){ len=sprintf(ptr,"0x%04X,",(unsigned short)myrgb(*(int*)pbuf)); ptr += len; count++; if(count == 16){ count = 0; len=sprintf(ptr,"\r\n"); ptr += len; } pbuf += 3; if((unsigned long)pbuf-(unsigned long)buffer-lines*skip == bmih.width*3*(lines+1)){ pbuf += skip; lines++; } } if(count==0){ ptr -= 3; len=sprintf(ptr,"\r\n"); ptr+=len; }else{ --ptr; len=sprintf(ptr,"\r\n"); ptr += len; } len=sprintf(ptr,"};\r\n"); ptr += len; printf("生成成功!\n"); //printf("結尾指針:pbuf-buffer=%d,ptr-outout_data=%d\n",pbuf-buffer,ptr-outout_data); len=fwrite(outout_data,1,(unsigned long)ptr-(unsigned long)outout_data,fpout); if(len != (unsigned long)ptr-(unsigned long)outout_data){ fprintf(stderr,"寫入數據的長度不等於待寫入的要求!\n"); }else{ printf("已全部保存到文件!\n"); } fclose(fpout); free(buffer); free(outout_data); break; } break; } return 0; }
軟件運行過程:
最終生成的數據像這種:
unsigned short image[] = { 0xDF9F,0xC75F,0xA71F,0x7EBF,0x667F,0x4E3F,0x3E1F,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x463F,0x461F,0x3E1F,0x6E7F,0xA6FF,0xCF7F,0xDF9F,0xC75F, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF, 0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF,0x35FF };
源代碼及程序: http://blog.twofei.com/files/512/bmconv.7z
哈哈,自己寫的軟件,用得放心.
女孩不哭 @ 2013-04-21 00:04:14 @ http://www.cnblogs.com/nbsofer