当前位置: 首页 > news >正文

全网首发:OSD字幕时,字体数据、间距的正确处理

比如说:如果是巍宇,这字好处理;如果是一丨,字体数据只有一行,数据如何刷新处理?间距又如何处理?

别担心。我这里有现成的代码。

  • 先看处理结果

https://blog.csdn.net/quantum7/article/details/153679213

  • FreeType字体加载

这个各位想必很熟悉了。

FT_Library m_pFTLib = NULL; FT_Face m_pFTFace = NULL; int m_iFontSize = 16; FT_Init_FreeType(&m_pFTLib); if (FT_New_Face(m_pFTLib, mFontFile, 0, &m_pFTFace)) { WY_LOG_TEXT("FT_New_Face error!"); return; } //FT_ENCODING_GB2312, FT_ENCODING_UNICODE FT_Select_Charmap(m_pFTFace, FT_ENCODING_UNICODE); FT_Set_Char_Size (m_pFTFace, 0, m_iFontSize<<6, 200, 200);
  • 加载字符插槽

使用的是Slot而不是Glyph。

因为代码是用于字幕,字幕字符是固定的,所以使用了一个std::map保存起来。

static FT_GlyphSlot osd_load_char_glyph(const wchar_t wch, const FT_Face& pFTFace) { FT_GlyphSlot wslot = new FT_GlyphSlotRec(); int result = FT_Load_Char( pFTFace, wch, FT_LOAD_RENDER ); FT_GlyphSlot slot = pFTFace->glyph; memcpy(wslot, slot, sizeof(FT_GlyphSlotRec)); FT_Bitmap* bmp = &(slot->bitmap); int size = bmp->rows*bmp->width; wslot->bitmap.buffer = (unsigned char*)malloc(size); memcpy(wslot->bitmap.buffer, bmp->buffer, size); return wglyph; }
  • 正确处理数据及间距
#define COLOR_TO_PIXEL(pixel, color, v, index) {int temp = color.val[index]*v/0xFF; \ if (temp == 0 && color.val[index] != 0) temp = 1; \ pixel[index] = temp; } #define COLOR_R_INDEX 2 #define COLOR_G_INDEX 1 #define COLOR_B_INDEX 0 void refresh(cv::Mat& rgb, cv::Scalar& color, int startX, int startY) { bool isBlack = (color.val[0] == 0 && color.val[1] == 0 && color.val[2] == 0); for (int i=0; i<this->mTextCount; i++) { wchar_t wch = this->mText[i]; std::map<wchar_t, FT_GlyphSlot>::iterator it = mTextGlyphMap.find(wch); FT_GlyphSlot pSlot = it->second; FT_Bitmap* pBmp = &(pSlot->bitmap); int osdW=pBmp->width; int osdH=pBmp->rows; int osdX = startX+pSlot->bitmap_left; //高度是pSlot->metrics.vertAdvance/64,因为要绘制,所以要减去 int osdY = startY+(pSlot->metrics.vertAdvance/64-pSlot->bitmap_top); for (int j=0; j<osdH; j++){ for (int i=0; i<osdW; i++){ unsigned char v = pBmp->buffer[osdW*j+i]; if (v < MIN_FONT_VALUE) { continue; } cv::Vec3b& pixel = rgb.at<cv::Vec3b>(osdY+j, osdX+i); if (isBlack) { v = 0xFF-v; pixel[COLOR_B_INDEX] = v; pixel[COLOR_G_INDEX] = v; pixel[COLOR_R_INDEX] = v; } else { COLOR_TO_PIXEL(pixel, color, v, COLOR_B_INDEX); COLOR_TO_PIXEL(pixel, color, v, COLOR_G_INDEX); COLOR_TO_PIXEL(pixel, color, v, COLOR_R_INDEX); } } } // 这个是正确宽度 startX += pSlot->metrics.horiAdvance/64; } }
http://www.cnnetsun.cn/news/4043904.html

相关文章:

  • RyuSAK 使用教程:3 步搞定 Ryujinx 模拟器的固件、着色器与存档管理
  • 5分钟上手UnrealPakViewer:让Pak文件分析变成一次可视化体检
  • 一个开源免费的 TCP/UDP 调试工具,把网络排错从一小时压缩到一分钟?
  • 3分钟用jsontt完成JSON多语言翻译:免费开源文件翻译工具实战指南
  • 从零上手 League-Toolkit:把游戏客户端的琐碎操作交给自动化
  • JVFloat.js源码深度剖析:JavaScript浮动提示框的实现原理
  • 告别一行行调试代码:Sokit 网络调试工具让 TCP/UDP 数据收发与端口转发一步到位
  • PDF补丁丁:免费开源的书签编辑与PDF批量处理完整教程
  • Git凭证存储机制详解:从原理到实践的安全认证管理
  • Logseq高阶实战:双链、模板与查询构建个人知识管理第二大脑
  • 洛雪音乐音源使用完全指南:免费畅听全网无损音乐的终极方案
  • 零基础把《塞尔达传说:众神的三角力量》用C语言重新编译运行:我的三天折腾笔记
  • 别再到处找下载方法了:res-downloader嗅探神器3步搞定全网资源下载
  • 抖音下载工具douyin-downloader:批量抓取、直播回放与增量去重的一站式方案
  • Elasticsearch与Natlas集成实战:构建高性能扫描数据存储方案
  • 零基础也能玩转的无代码平台:Baserow 数据库、自动化与 AI 应用全攻略
  • 2023最新pidgin-lwqq插件安装教程:从源码编译到功能验证
  • 网盘直链下载助手完整攻略:8大网盘真实下载链接一键获取
  • 微信防撤回补丁RevokeMsgPatcher:Windows消息保护终极指南
  • 学不会机器学习?这个免费浏览器工具让你零代码亲手训练AI模型
  • 老款 Mac 想升级最新 macOS?用 OpenCore Legacy Patcher 免费跑通的全程避坑路线图
  • 微信聊天记录导出终极方案:用WeChatMsg永久保存你的每一句对话
  • 如何用react-native-testing测试登录表单?完整提交流程实战
  • 一台电脑、一个窗口、所有游戏:Playnite游戏库管理工具使用手记
  • douyin-downloader 完整上手教程:开源免费,把抖音视频与直播回放批量存进本地硬盘
  • OpCore-Simplify 快速上手指南:一条命令把黑苹果 OpenCore EFI 配置从数小时压缩到几分钟
  • 图片上传与存储实战:AWS S3在instagram-mern项目中的应用指南
  • IP-Adapter 快速上手指南:22M 参数的图像提示适配器如何驱动扩散模型
  • 免费开源的ERPNext实战记:小公司的账、货、订单,真的能被它管成一条线
  • RAT-retrieval-augmented-thinking进阶技巧:如何优化推理过程提升回答质量