彩屏圖像取模,BMP圖像提取程序示例


  由於屏幕的多種類性, 我始終沒有使用市面上的那種取模軟件, 我始終感覺數據可能不對.
因為我的屏幕的要求比例是R:G:B(5:6:5),16位色,一個像素2個字節保存,所以總覺得應該自己寫
一個來做這種轉換工作的軟件.
  今天寫了個小程序,在彩屏上顯示出來的效果很好. 程序是為我的屏幕的數據類型量身生成的,
寫在這里只是保存一下,不然久了,我又不知道代碼之前的版本, 或是又找不到了.
  程序解析BMP圖像數據到點陣字模(僅支持24位位深的BMP位圖,現在大都是這種),生成是數據
是16位的無符號字符型數據數組.直接調用寫進屏幕即可顯示出來.

tfref

  代碼分兩個文件: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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM