通信原理课设(gec6818) 003:LCD显示bmp

1、BMP

普通文件一般分为两种
文本文件:按照ASCII码去解析的文件(.txt .c .h .cpp .hpp.....) 
二进制文件:存储二进制,直接通过ASCII去解析出现的就乱码,必须通过程序的开发者发布的格式去完成这个解析格式,必须要按照这个规则走你才能解析出这个文件( .mp3 .mp4 .jpg .bmp......)

图片文件分为很多种格式:
无压缩的:以bmp为代表,每一个像素点都完整的保存下来。
有压缩的:jpeg为代表,将它的数据进行压缩,用更小的存储空间表示更多的内容。

以下就是BMP文件的格式:

2、练习

  在屏幕上面循环刷新图片注意:各种不同的像素都要能刷新,并且将其居中,图片没有覆盖到的地方用一个什么颜色的底色去补齐。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <math.h>

int lcd_fd = -1;  // Global LCD file descriptor
unsigned int *plcd = NULL;  // Global mapping base address

void LcdInit(void) {
    lcd_fd = open("/dev/fb0", O_RDWR);
    if (-1 == lcd_fd) {
        perror("open fb0 error");
        exit(1);
    }
    plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (MAP_FAILED == plcd) {
        perror("mmap lcd error");
        exit(2);
    }
}

void LcdDestory(void) {
    munmap(plcd, 800 * 480 * 4);
    close(lcd_fd);
}

//绘制一个点
void Display(int x, int y, unsigned int color) {
    if (x >= 0 && x < 800 && y >= 0 && y < 480) {
        *(plcd + y * 800 + x) = color;
    }
}

//绘制一个方块
void Displaysql(int w, int h, int x0, int y0, unsigned int color) {
    int x, y;
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            Display(x + x0, y + y0, color);
        }
    }
}



//居中显示
void DisplayBmpPic(const char* pic)
{
    //1、打开文件
    int fd = open(pic , O_RDONLY);
    if( fd == -1)
    {
        perror("open bmp error");
        return;
    }

    //2、判断这个文件是不是真的bmp图片
    //暂时省略

    //读取bmp文件头相关信息:
    int width,height,depth=0;
    //读取宽度、高度
    lseek(fd,0x12,SEEK_SET);
    read(fd,&width,4);
    read(fd,&height,4); //高度和宽度连在一起
    //读取色深
    lseek(fd,0x1c,SEEK_SET);
    read(fd,&depth,2);
    printf("width= %d  height= %d  depth= %d\n",width,height,depth);

    //为了凑4的倍数,需要在每一行的后面加1/2/3/0个字节
    int n =(4 - width * (depth / 8) % 4) % 4;
    //计算像素数组 w*h*(depth/8) 由于数组较大,故采用动态内存分配
    unsigned char *coclorbuf = malloc((width*(depth/8)+n)*height);
    //读取像素数组,偏移过头部
    lseek(fd,0x36,SEEK_SET);
    read(fd,coclorbuf,(width*(depth/8)+n)*height);

    //拿到每一个像素点的rgb
    unsigned char c_a,c_r,c_g,c_b;
    unsigned int color;
    int i=0;//coclorbuf的下标
    int x=400-(width/2),y=240+(height/2);//坐标
    for(y=240+(height/2)-1 ; y>=240-(height/2) ; y--)//列
    {
        for(x=400-(width/2) ; x<width+400-(width/2) ; x++)//行
        {
            c_b = coclorbuf[i++];
            c_g = coclorbuf[i++];
            c_r = coclorbuf[i++];
            if( 32 == depth)  // 32/8=4 说明存储的是argb
            {
                c_a = coclorbuf[i++];
            }
            color = c_a<<24 | c_r<<16 | c_g<<8 | c_b;
            Display(x,y,color);
        }
        i += n;//每走完一行都要跳过后面补的没用的n个字节
    }
    //释放动态分配内存 free只能释放动态内存空间
    free(coclorbuf);
    //3、关闭文件
    close(fd);
}

int main() {

    LcdInit();

    //显示白色
    Displaysql(800, 480, 0, 0, 0xffffff);
    //显示图片
    DisplayBmpPic("1.bmp");

    LcdDestory();
    return 0;
}
posted @ 2023-12-23 15:39  Flying3080  Views(60)  Comments(0Edit  收藏  举报  来源