
RV1126学习笔记 OSD叠加中文字体时间sdl sdl_tff
SDL
Simple Directmedia Layer
项目地址:https://gitcode.com/gh_mirrors/sd/SDL

·
型号:A191-EB-RV1126 摄像头:gc2053
参考了以下大佬的博文
https://blog.csdn.net/tang200710312333/article/details/105821179
https://blog.csdn.net/u010034969/article/details/112236885
但是都是海思平台的实现方法和RK平台还是多少有点区别
过程就是把用sdl生成bmp图转为位图然后叠加到对应的数据上面去
最主要的地方是 sdl默认生成的是16位 rgb565 格式的图,而rv1126 osd叠加的图只能是32位ARGB888格式的
所以要把对应的图转一下格式才可以显示,因此就需要一位一位像素的处理
安装freetype sdl sdl_tffd 的库文件
首先你需要把以上对应的库按顺序安装好,网上教程也很多,这里不细说,记得编译的时候用RV1126交叉编译工具链,把编译后生成的库文件和头文件都要放到开发板上去,并且把对应的路径也添加上去。安装参考博文如下:
https://blog.csdn.net/whereisdog/article/details/82769222
也可以参考下面这个博文,编写自己的CMake编译工程。(可跳过)
https://blog.csdn.net/m0_50887633/article/details/134446233?spm=1001.2014.3001.5501
SDL API简介
https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlcolor.html
参考rkmedia_venc_osd_test.c
下面贴上核心代码
static void *GetOSDBuffer(void *arg) {
time_t now;
struct tm *ptm;
char timestr[100] = {0};
// 从左上角开始算(bitmap_PosX, bitmap_PosY),(0,0)
// bitmap的长宽要保持 16的倍数的比例
int bitmap_width = 0;
int bitmap_height = 0;
int bitmap_PosX = 0;
int bitmap_PosY = 0;
int wxh_size = 0;
RK_MPI_VENC_RGN_Init(0, NULL);
while (!quit) {
//bitmap的长宽要保持 16的倍数的比例
bitmap_width = 992;
bitmap_height = 144;
bitmap_PosX = 0;
bitmap_PosY = 0;
if (bitmap_width < 64)
bitmap_width = 64;
if (bitmap_height < 64)
bitmap_height = 64;
//像素结构
SDL_PixelFormat *fmt;
//字体结构
TTF_Font *font;
//图面结构
//把文字SDL_Surface 输出到屏幕显示,如果不需它,必须释放它
//文字表面和其他表面一样,可以传输到显示表面显示。
SDL_Surface *text, *temp;
//创建时间
time(&now);
ptm = localtime(&now);
snprintf(timestr,100,"时间%d-%02d-%02d %02d:%02d:%02d",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
if (TTF_Init() < 0 )
{
fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());
SDL_Quit();
}
//打开字库,设字体为80号
font = TTF_OpenFont(FONT_PATH, 80); //FONT_PATH 对应的.ttf文件路径,自行下载
if ( font == NULL )
{
fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",18,"ptsize", SDL_GetError());
}
//设置字体颜色
SDL_Color forecol = { 0x00,0x00, 0x00}; //3个参数分别代表rgb
//SDL显示中文
text = TTF_RenderUTF8_Solid(font,timestr, forecol);
//定义格式
fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
memset(fmt,0,sizeof(SDL_PixelFormat));
fmt->BitsPerPixel = 16; //每像素位数
fmt->BytesPerPixel = 2; //每像素字节数
fmt->colorkey = 0xffffffff;
fmt->alpha = 0xff; //透明度 0<=alpha<=255
//将现有表面复制到一个新的表面,该表面针对指定像素格式的表面进行了优化。
//默认 RGB565格式
temp = SDL_ConvertSurface(text,fmt,0);
BITMAP_S stBitmap;
//将渲染后的Surface转换成Bitmap
// 转成ARGB8888格式
MySample_SurfaceWord_ToBMP(temp,&stBitmap,forecol);
//把文字SDL_Surface释放
SDL_FreeSurface(text);
SDL_FreeSurface(temp);
//关闭TTF_Font字体
TTF_CloseFont(font);
//释放TTF库
TTF_Quit();
//释放 fmt
free(fmt);
fmt = NULL;
//重置时间字符串
memset(timestr,0,100);
OSD_REGION_INFO_S RngInfo;
RngInfo.enRegionId = 5;
RngInfo.u32PosX = bitmap_PosX;
RngInfo.u32PosY = bitmap_PosY;
RngInfo.u32Width = bitmap_width;
RngInfo.u32Height = bitmap_height;
RngInfo.u8Enable = 1;
RngInfo.u8Inverse = 0;
printf("# ENABLE RGN enRegionId[%d]: < u32PosX:%d,u32PosY:%d,u32Width:%d,u32Height:%d> for 100ms...\n",
RngInfo.enRegionId, RngInfo.u32PosX, RngInfo.u32PosY,
RngInfo.u32Width, RngInfo.u32Height);
int ret = RK_MPI_VENC_RGN_SetBitMap(0, &RngInfo, &stBitmap); //
if (ret) {
printf("ERROR: set rgn stBitmap(enable) failed! ret=%d\n", ret);
if (stBitmap.pData)
free(stBitmap.pData);
break;
}
// free stBitmap
free(stBitmap.pData);
stBitmap.pData = NULL;
// usleep(100000);
usleep(1000000);
} //while
}
/将渲染后的Surface转换成Bitmap
void MySample_SurfaceWord_ToBMP(SDL_Surface *surface,BITMAP_S *stBitmap,SDL_Color fntcol)
{
unsigned short words_color = ((fntcol.r >> 3) << 11) + ((fntcol.g >> 2) << 5) + (fntcol.b >> 3);
unsigned short bck_color = 0xffff - words_color;
stBitmap->u32Height = (surface->h); //BITMAP 的宽高向上2对齐
stBitmap->u32Width = (surface->w);
stBitmap->pData = malloc(4*(stBitmap->u32Height)*(stBitmap->u32Width)); //申请空间,ARGB8888=>4Byte/Pixel,总大小为4*w*h
memset(stBitmap->pData,0,4*(stBitmap->u32Height)*(stBitmap->u32Width));
int i,j;
int w = surface->w;
int h = surface->h;
for (i = 0; i < h; ++i)
{
RK_U32 *p_dst = (RK_U32*)stBitmap->pData;
RK_U16 *p_src = (RK_U16*)surface->pixels;
int dis_pos = 0;
if(w % 2 != 0)
dis_pos = i; //处理w为奇数的情况
for(j=0;j<w;j++)
{
int a,r, g , b;
r = (p_src[i*w+dis_pos+j] & 0xF800) >> 8; //原图像是RGB565,RGB各分量提取
g = (p_src[i*w+dis_pos+j] & 0x07e0) >> 3;
b = (p_src[i*w+dis_pos+j] & 0x001f) << 3;
//一致则A位设置为0,透明
if (bck_color == p_src[i*w+dis_pos+j])
a = 0x00;
else a = 0xff;
p_dst[i*stBitmap->u32Width+j] = (a << 24) | (r << 16) | (g << 8) | b; //转换成ARGB888
}
}
stBitmap->enPixelFormat = PIXEL_FORMAT_ARGB_8888;
}
最终效果图
记录下自己的学习过程,希望能对你有帮助




Simple Directmedia Layer
最近提交(Master分支:6 个月前 )
ca29304c - 1 天前
f67c6446 - 1 天前
更多推荐
所有评论(0)