/**
******************************************************************************
* 文件名程: bsp_bmp.c
* 作 者: 硬石嵌入式开发团队
* 版 本: V1.0
* 编写日期: 2015-10-04
* 功 能: bmp图像显示实现
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:http://www.ing10bbs.com
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/
/* 包含头文件 ----------------------------------------------------------------*/
#include "usart/bsp_debug_usart.h"
#include "lcd/bsp_lcd.h"
#include "ff.h"
#include "bmp/bsp_bmp.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* R(8bit) G(8bit) B(8bit) --> RGB565 */
#define RGB24TORGB16(R,G,B) ((R>>3)<<11)|((G>>2)<<5)|(B>>3)
/* 如果不需要打印bmp相关的提示信息,将printf注释掉即可
* 如要用printf(),需将串口驱动文件包含进来
*/
#define BMP_DEBUG_PRINTF(FORMAT,...) //printf(FORMAT,##__VA_ARGS__)
/* 私有变量 ------------------------------------------------------------------*/
uint8_t pColorData[960]; /* 一行真彩色数据缓存 320 * 3 = 960 */
FIL file;
extern FRESULT f_res;
UINT f_num;
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
/**
* 函数功能: 打印BMP文件的头信息,用于调试
* 输入参数: pBmpHead:BMP文件的头信息
* 返 回 值: 无
* 说 明:无
*/
static void showBmpHeader(BMP_FileHeader *pBmpHead)
{
BMP_DEBUG_PRINTF("位图文件头:\n");
BMP_DEBUG_PRINTF("文件类型:%d\n",(*pBmpHead).bfType);
BMP_DEBUG_PRINTF("文件大小:%d\n",(*pBmpHead).bfSize);
BMP_DEBUG_PRINTF("保留字:%d\n",(*pBmpHead).bfReserved1);
BMP_DEBUG_PRINTF("保留字:%d\n",(*pBmpHead).bfReserved2);
BMP_DEBUG_PRINTF("实际位图数据的偏移字节数:%d\n",(*pBmpHead).bfOffBits);
BMP_DEBUG_PRINTF("\n");
}
/**
* 函数功能: 打印BMP文件的头信息,用于调试
* 输入参数: pBmpHead:BMP文件的头信息
* 返 回 值: 无
* 说 明:无
*/
static void showBmpInforHeader(BMP_InfoHeader *pBmpInforHead)
{
BMP_DEBUG_PRINTF("位图信息头:\n");
BMP_DEBUG_PRINTF("结构体的长度:%d\n",(*pBmpInforHead).biSize);
BMP_DEBUG_PRINTF("位图宽:%d\n",(*pBmpInforHead).biWidth);
BMP_DEBUG_PRINTF("位图高:%d\n",(*pBmpInforHead).biHeight);
BMP_DEBUG_PRINTF("biPlanes平面数:%d\n",(*pBmpInforHead).biPlanes);
BMP_DEBUG_PRINTF("biBitCount采用颜色位数:%d\n",(*pBmpInforHead).biBitCount);
BMP_DEBUG_PRINTF("压缩方式:%d\n",(*pBmpInforHead).biCompression);
BMP_DEBUG_PRINTF("biSizeImage实际位图数据占用的字节数:%d\n",(*pBmpInforHead).biSizeImage);
BMP_DEBUG_PRINTF("X方向分辨率:%d\n",(*pBmpInforHead).biXPelsPerMeter);
BMP_DEBUG_PRINTF("Y方向分辨率:%d\n",(*pBmpInforHead).biYPelsPerMeter);
BMP_DEBUG_PRINTF("使用的颜色数:%d\n",(*pBmpInforHead).biClrUsed);
BMP_DEBUG_PRINTF("重要颜色数:%d\n",(*pBmpInforHead).biClrImportant);
BMP_DEBUG_PRINTF("\n");
}
/**
* 函数功能: 显示bmp图片, 24位真彩色
* 输入参数: x:显示图片左上角x轴坐标
* y:显示图片左上角y轴坐标
* pic_name:显示图片文件名称
* 返 回 值: 无
* 说 明:图片宽度和高度根据图片大小而定
*/
void Lcd_show_bmp(uint16_t x, uint16_t y,char *pic_name)
{
uint16_t i, j, k;
int width, height, l_width;
BMP_FileHeader FileHeader;
BMP_InfoHeader InfoHeader;
/*-------------------------------------------------------------------------------------------------------*/
f_res=f_open(&file,pic_name, FA_OPEN_EXISTING|FA_READ);
if(f_res == FR_OK)
{
BMP_DEBUG_PRINTF("Open file success\r\n");
/* 读取文件头信息 两个字节*/
f_res=f_read(&file,&FileHeader,sizeof(BMP_FileHeader),&f_num);
/* 判断是不是bmp文件 "BM"*/
if(FileHeader.bfType!=0x4d42)
{
BMP_DEBUG_PRINTF("file is not .bmp file!\r\n");
return;
}
else
{
BMP_DEBUG_PRINTF("Ok this is .bmp file\r\n");
}
/* 读取BMP文件头信息*/
showBmpHeader(&FileHeader);
/* 读取位图信息头信息 */
f_res=f_read(&file,&InfoHeader,sizeof(BMP_InfoHeader),&f_num);
showBmpInforHeader(&InfoHeader);
}
else
{
BMP_DEBUG_PRINTF("file open fail!\r\n");
return;
}
/*-------------------------------------------------------------------------------------------------------*/
width = InfoHeader.biWidth;
height = InfoHeader.biHeight;
/* 计算位图的实际宽度并确保它为32的倍数 */
l_width = WIDTHBYTES(width* InfoHeader.biBitCount);
if((l_width>960)||(InfoHeader.biBitCount!=24))
{
BMP_DEBUG_PRINTF("\n SORRY, PIC IS TOO BIG (X<=320 and bit!=16)\n");
return;
}
f_lseek(&file,FileHeader.bfOffBits);
if(InfoHeader.biBitCount == 24)
{
for(i=0;i<height;++i)
{
/* 开一个图片大小的窗口*/
LCD_OpenWindow(x, y+height-i-1, width, 1);
LCD_WRITE_CMD(0x2C);
/* 读取一行bmp的数据到数组pColorData里面 */
f_read(&file,pColorData,l_width,&f_num);
for(j=0;j<width;j++) //一行有效信息
{
k = j*3; //一行中第K个像素的起点
LCD_WRITE_DATA(RGB24TORGB16(pColorData[k+2],pColorData[k+1],pColorData[k])); //写入LCD-GRAM
}
}
}
f_close(&file);
}
uint8_t Screen_shot(uint16_t x,uint16_t y,uint16_t Width,uint16_t Height, const char * filename)
{
/* bmp 文件头 54个字节 */
uint8_t header[54] =
{
0x42, 0x4d, 0, 0, 0, 0,
0, 0, 0, 0, 54, 0,
0, 0, 40,0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 24, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0
};
uint16_t i;
uint16_t j;
uint32_t file_size;
uint16_t width;
uint16_t height;
uint8_t r,g,b;
uint16_t read_data;
uint8_t kk[4]={0,0,0,0};
uint8_t ucAlign=Width%4;
/* 宽*高 +补充的字节 + 头部信息 */
file_size = Width * Height * 3 + Height*(Width%4) + 54;
/* 文件大小 4个字节 */
header[2] = file_size&0x000000ff;
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;
/* 位图宽 4个字节 */
width=Width;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;
/* 位图高 4个字节 */
height = Height;
header[22] = height &0x000000ff;
header[23] = (height >> 8) &0x000000ff;
header[24] = (height >> 16) &0x000000ff;
header[25] = (height >> 24) &0x000000ff;
/* 新建一个文件 */
f_res = f_open(&file,filename,FA_CREATE_ALWAYS|FA_WRITE);
if(f_res==FR_OK)
{
/* 将预先定义好的bmp头部信息写进文件里面 */
f_res = f_write(&file, header,54, &f_num);
for(i=0; i<Height; i++)
{
if(!(Width % 4))
{
for(j=Width;j>0;j--)
{
read_data=LCD_GetPointPixel(y+j-1, x+i);
r = GETR_FROM_RGB16(read_data);
g = GETG_FROM_RGB16(read_data);
b = GETB_FROM_RGB16(read_data);
f_res = f_write(&file, &b,1, &f_num);
f_res = f_write(&file, &g,1, &f_num);
f_res = f_write(&file, &r,1, &f_num);
}
}
else
{
for(j=Width;j>0;j--)
{
read_data = LCD_GetPointPixel(y+j-1, x+i);
r = GETR_FROM_RGB16(read_data);
g = GETG_FROM_RGB16(read_data);
b = GETB_FROM_RGB16(read_data);
f_res = f_write(&file, &b,1, &f_num);
f_res = f_write(&file, &g,1, &f_num);
f_res = f_write(&file, &r,1, &f_num);
}
if( ucAlign ) /* 如果不是4字节对齐 */
f_res = f_write ( & file, kk, ucAlign, & f_num );
}
}/* 截屏完毕 */
f_close(&file);
return 1;
}
else if(f_res==FR_EXIST) //如果文件已经存在
return FR_EXIST; //8
else/* 截屏失败 */
return 0;
}
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/