lcd显示bmp图片应用编程

1.bmp图片格式

一个bmp文件有四部分组成:

其中位图文件头内容如下:

1 WORD    bfType;   
2 DWORD   bfSize;   
3 WORD    bfReserved1;   
4 WORD    bfReserved2;   
5 DWORD   bfOffBits;  

bfType 说明文件的类型,该值必需是0x4D42,也就是字符'BM',否则表示根本不是BMP
bfSize 说明该位图文件的大小,用字节为单位
bfReserved1 保留,必须设置为0
bfReserved2 保留,必须设置为0
bfOffBits 说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。


位图信息段内容如下:

 1     DWORD  biSize;   
 2     LONG   biWidth;   
 3     LONG   biHeight;   
 4     WORD   biPlanes;   
 5     WORD   biBitCount   
 6     DWORD  biCompression;   
 7     DWORD  biSizeImage;   
 8     LONG   biXPelsPerMeter;   
 9     LONG   biYPelsPerMeter;   
10     DWORD  biClrUsed;   
11     DWORD  biClrImportant;   

biSize 说明BITMAPINFOHEADER结构所需要的字节数
biWidth 说明图象的宽度,以象素为单位
biHeight 说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,即:数据的第一行其实是图像的最后一行,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
biPlanes 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1
biBitCount 说明比特数/象素,其值为1、4、8、16、24、或32。
biCompression 说明图象数据压缩的类型,其中:

BI_RGB:没有压缩

BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);

BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成

BI_BITFIELDS:每个象素的比特由指定的掩码决定。

BI_JPEG:JPEG格式
biSizeImage 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
biXPelsPerMeter 说明水平分辨率,用象素/米表示。
biYPelsPerMeter 说明垂直分辨率,用象素/米表示。
biClrUsed 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
biClrImportant 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

 

测试代码:

注意test.bmp图片需要压缩成480x280的bmp图片格式, 可以用xp中附件中的画图软件打开->图像->属性->宽度:480 高度:240

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>
#include <stdlib.h>

static unsigned char *fbp = 0;

/*bmp位图文件头数据结构*/
typedef struct
{
    char cfType[2];
    int cfSize;
    char cfReserved[4];
    int cfoffBits;
}__attribute__((packed)) BITMAPFILEHEADER;

/*bmp位图信息段数据结构*/
typedef struct
{
int ciSize;
int ciWidth;
int ciHeight;
char ciPlanes[2];
short ciBitCount;
char ciCompress[4];
char ciSizeImage[4];
char ciXPelsPerMeter[4];
char ciYPelsPerMeter[4];
char ciClrUsed[4];
char ciClrImportant[4];
}__attribute__((packed)) BITMAPINFOHEADER;


/*屏幕分辨率480x240*/
int show_bmp(char* bmpfile)
{
    int fp_bmp;
    int height;
    int width;
    int bitCount;    //bpp
    int length, offset = 0;
    int i, y1 = 0, x1 = 0;
    BITMAPFILEHEADER file_head;
    BITMAPINFOHEADER info_head;
    int ciWidth, ciHeight, ciBitCount;
    unsigned char* pdata = NULL;
    unsigned char r = 0, g = 0, b = 0;
    unsigned char R = 0, G = 0, B = 0;
    unsigned int color = 0;
    fp_bmp = open(bmpfile, O_RDONLY);//打开图片文件
    if ( fp_bmp < 0 ) {
        printf("can not open file %s\n",bmpfile);
        return 0;
    }
    read( fp_bmp, &file_head, sizeof(file_head) );//读取文件头信息
    printf("bftype=%s, bfsize=%d, bfoffbits=%d\n", file_head.cfType, file_head.cfSize, file_head.cfoffBits);
    /*改变读写指针, 直接跳转到文件开始位置+18的地方进行读写*/
    lseek(fp_bmp, 18, SEEK_SET);
    read(fp_bmp, (void*)&width, sizeof(int));
    read(fp_bmp, (void*)&height, sizeof(int));
    lseek(fp_bmp, 28, SEEK_SET);
    read(fp_bmp, (void*)&bitCount, sizeof(int));
    printf("width = %d, height = %d, bitCount = %d\n", width, height, bitCount);
    /* 申请图片实际数据大小 */
    pdata = malloc(file_head.cfSize - file_head.cfoffBits);
    unsigned char* pdata_tmp = pdata;
    if(pdata == NULL) {
        printf("mem allocate failed\n");
        return 0;
    }
    /*跳转到图片的数据域进行读写*/
    lseek(fp_bmp, file_head.cfoffBits, SEEK_SET);
    /*读取(file_head.cfSize - file_head.cfoffBits)个字节并存放到pdata中*/
    read(fp_bmp, pdata, file_head.cfSize - file_head.cfoffBits);
    for (y1 = 0; y1 < 240; y1 ++) {
        for (x1 = 0; x1 < 480; x1 ++) {
            /* 注意从bmp文件中读出的图像数据连续的三个字节中第一个字节为红色分量 第二个字节为蓝色分量 第三个字节为绿色分量*/
            r = *pdata;
            b = *(pdata + 1);
            g = *(pdata + 2);
            offset = x1 * (ciBitCount/8) + y1 * width * (ciBitCount/8);
            *(fbp + offset + 1) = b;
            *(fbp + offset + 2) = g;
            *(fbp + offset + 3) = r;

#if 0
            /*下面7条语句实现了RGB24转换为RGB565 红色r占5为屏蔽低三位 绿色g占6为屏蔽低两位 蓝色b占5为屏蔽低三位*/
            r = r & (~(0x07));
            g = g & (~(0x03));
            b = b & (~(0x07));
            R = (unsigned short)r << 8;
            G = (unsigned short)g << 3;
            B = (unsigned short)b >> 3;
            color = R | G | B;
            /*计算偏移量 ,注意最先读出的三个字节对应的是图像中的左下角的那个像素,最后三个字节对应图像中右上角的那个像素*/
            offset = (240 - y1 -1)*480*2 + (x1*2);
            /*将颜色数据写入显存*/
            *(unsigned short*)(fbp + offset) = color;
#endif
            pdata += 3;
        }
    }
    close(fp_bmp);
    free(pdata_tmp);
}

int main(int argc, char* argv[])
{
    int fbfd = 0;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    struct fb_cmap cmapinfo;
    long int screensize = 0;
    int x = 0, y = 0;
    long int location = 0;
    int b, g, r;

    /* open /dev/fb0 */
    fbfd = open("/dev/fb0", O_RDWR);
    if (fbfd < 0) {
        printf("ERR: open framebuffer device failed\n");
        return -1;
    }
    printf("open framebuffer device successfully\n");

    /* get fixed screen infomation */
    if (-1 == ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
        printf("ERR: reading fixed screen infomatin failed\n");
        return -1;
    }
    printf("\ntype:0x%x\n", finfo.type);
    printf("visual:%d\n", finfo.visual );                        // 视觉类型:如真彩2,伪彩3
    printf("line_length:%d\n", finfo.line_length );        // 每行长度
    printf("\nsmem_start:0x%x,smem_len:%d\n", finfo.smem_start, finfo.smem_len ); // 映象RAM的参数
    printf("mmio_start:0x%x ,mmio_len:%d\n", finfo.mmio_start, finfo.mmio_len );
    /* get variable screen infomation */
    if (-1 == ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
        printf("ERR: reading variable screen infomatin failed\n");
        return -1;
    }
    printf("R:%d, G:%d, B:%d\n", vinfo.red.length, vinfo.green.length, vinfo.blue.length);
    printf("pixel:%dx%d, bits_per_pixel:%dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
    /* figure out the size of the screen in bytes */
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    /* map the device to memory */
    fbp = (unsigned char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((-1 == (int)fbp)) {
        printf("ERR: failed to map framebuffer device to memory\n");
        return -1;
    }
    printf("success to map framebuffer device to memory\n");
    memset(fbp, 0x0, screensize);
    printf("show bmp\n");
    /*显示test.bmp图片*/
    show_bmp("./test.bmp");
    munmap(fbp, screensize);
    close(fbfd);
    return 0;
}

参考: https://wenku.baidu.com/view/e113bf4233687e21af45a964.html

    http://blog.chinaunix.net/uid-26470931-id-3031310.html

posted @ 2017-07-11 11:43  大海中的一粒沙  阅读(729)  评论(0编辑  收藏  举报