• 彩屏图像取模,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

  • 相关阅读:
    XSS练习小游戏和答案参考
    nxlog以syslog方式发送日志
    Hydra—密码爆破神器
    syslog服务器配置笔记
    信息安全工具汇总整理
    nmap使用指南
    Cleaner, more elegant, and harder to recognize (msdn blog)
    Golang 中的坑 一
    Concurrency Is Not Parallelism (Rob pike)
    golang sql database drivers
  • 原文地址:https://www.cnblogs.com/memset/p/3033336.html
Copyright © 2020-2023  润新知