在LCD屏的任意位置展示一张任意大小的bmp图片,其余位置用纯色填充

/*********************************************************************************
* @Description  : 在LCD屏的任意位置展示一张任意大小的bmp图片,其余位置用纯色填充
* @Author       : ice_cui
* @Date         : 2025-04-28 22:53:46
* @Email        : Lazypanda_ice@163.com
* @LastEditTime : 2025-04-29 14:52:09
* @Version      : V1.0.3
* @Copyright    : Copyright (c) 2025 Lazypanda_ice@163.com All rights reserved.
**********************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

#define FILL_COLOR 0xFFFFFF
//屏幕的物理尺寸
#define LCD_WIDTH 800
#define LCD_HEIGHT 480
//想要显示图片的起始位置
#define X 100
#define Y 100
//取消字节对齐
#pragma pack(1)

//文件头结构体
typedef struct BITMAP_FILE_HEADER
{
    short        bfType;//文件标识
    int          bfSize;//文件大小
    short        bfReserved1;//保留字
    short        bfReserved2;//保留字
    int          bfOffBits;//文件指示器偏移量相较于文件开头
} bpFile_Header, *PbpFile_Header;
//信息头结构体
typedef struct BITMAP_INFO_HEADER
{
    int          bpSize;//图像描述信息块的大小
    int          bpWidth;//图像宽度
    int          bpHeight;//图像高度
    short        bpPlanes;//图像的plane总数(恒为1)
    short        bpBitCount;//记录颜色的位数取值1(双色),4,6,24,32
    int          bpCompression;//数据压缩方式(0:不压缩;1:8位压缩;2:4位压缩)
    int          bpSizeImage;//图像区数据的大小,必须是4的倍数
    int          bpXPelsPerMeter;//水平每米有多少像素,在设备无关位图中,填写00H
    int          bpYPelsPerMeter;//垂直每米有多少像素,在设备无关位图中,填写00H
    int          bpClrUsed;// 此图像所有的颜色数,不用,固定为0
    int          bpClrImportant;// 重要颜色数,不用,固定为0
} bpInfo_Header, *PbpInfo_Header;

#pragma pack()

int main(int argc, char const *argv[])
{
    //1,打开待显示的bmp图像
    FILE *bmp_fp = fopen("2.bmp","rb");
    if (NULL == bmp_fp)
    {
        perror("无法打开BMP文件");
        return -1;
    }
    
    //2,读取bmp文件的图像信息,获取bmp的宽和高
    bpInfo_Header headerinfo;
    fseek(bmp_fp,14,SEEK_SET);
    fread(&headerinfo,1,40,bmp_fp);
    if (headerinfo.bpBitCount != 24) {
        printf("the bmp is not 24bit\n");  
        fclose(bmp_fp);  
        return -1;
    }
    printf("bmp width = %d,height = %d,bit  = %d\n",headerinfo.bpWidth,
                                                    headerinfo.bpHeight,
                                                    headerinfo.bpBitCount);
    // 计算每行字节数(考虑字节对齐)
    int rowSize = ((headerinfo.bpWidth * headerinfo.bpBitCount + 31) / 32) * 4;

    // 3,动态分配内存读取bmp文件的颜色分量
    char *bmp_buf = (char *)malloc(rowSize * headerinfo.bpHeight);
    if (bmp_buf == NULL)
    {
        perror("内存分配失败");
        fclose(bmp_fp);
        return -1;
    }
    fseek(bmp_fp, 54, SEEK_SET); // 跳过文件头和信息头
    fread(bmp_buf, 1, rowSize * headerinfo.bpHeight, bmp_fp);

    //4,关闭bmp
    fclose(bmp_fp);

    //5,打开LCD
    int lcd_fd = open ("/dev/fb0",O_RDWR);
    if (-1 == lcd_fd)
    {
        perror("open lcd error");
        free(bmp_buf);
        return -1;
    }
    //6,对LCD屏进行内容映射 mmap函数
    int *lcd_mp = (int*)mmap(NULL,
                            LCD_WIDTH * LCD_HEIGHT * 4,
                            PROT_READ|PROT_WRITE,
                            MAP_SHARED,
                            lcd_fd,
                            0);
    if (MAP_FAILED == lcd_mp)
    {
        printf("mmap for lcd is error\n");
        return -1;
    }
    
    // 先填充纯色
    for (int i = 0; i < LCD_HEIGHT; i++)
    {
        for (int j = 0; j < LCD_WIDTH; j++)
        {
            lcd_mp[i * LCD_WIDTH + j] = FILL_COLOR;
        }
    }
    // 显示BMP图片
    for (int i = 0; i < headerinfo.bpHeight; i++)
    {
        for (int j = 0; j < headerinfo.bpWidth; j++)
        {
            int srcIndex = ((headerinfo.bpHeight - i - 1) * rowSize + j * 3);
            int dstX = X + j;
            int dstY = Y + i;
            if (dstX >= 0 && dstX < LCD_WIDTH && dstY >= 0 && dstY < LCD_HEIGHT)
            {
                unsigned char b = bmp_buf[srcIndex];
                unsigned char g = bmp_buf[srcIndex + 1];
                unsigned char r = bmp_buf[srcIndex + 2];
                lcd_mp[dstY * LCD_WIDTH + dstX] = (r << 16) | (g << 8) | b;
            }
        }
    }
    //8,解除映射并关闭LCD
    munmap(lcd_mp,LCD_WIDTH * LCD_HEIGHT * 4);
    close(lcd_fd);
    return 0;
}

posted @ 2025-04-29 14:54  ice_cui  阅读(254)  评论(0)    收藏  举报