imx6ull/linux應用編程學習(7)在LCD上顯示文字

????????在linux中,確實可以像裸機一樣自己取模、自己寫函數打點顯示,但是效率很低,不能滿足多文字顯示,在Linux 系統中, 字體文件通常會放在/usr/share/fonts 目錄下,有了字體文件之后,我們就不需要再對字符進行取模了,它們已經編碼進了字體文件中,我們只需要解析字體文件、訪問字體文件,從字體文件中讀取出字符的位圖數據即可。

freetype:

????????FreeType 一個完全免費(開源)的軟件字體引擎庫,FreeType”也稱為“FreeType 2”,以區別于舊的、已棄用的“FreeType 1”庫, Freetype 1庫已經不再維護和支持了。

下載 FreeType 源碼:進入到 https://download.savannah.gnu.org/releases/freetype/鏈接地址

例如下載2.8版本,選擇 freetype-2.8.tar.gz 壓縮文件:

(tips:有很多情況直接點擊會進入網頁亂碼下載不了,可以開個加速器,我開了加速器下載成功了)

將freetype傳到ubuntu,同樣,創一個freetype文件夾作為安裝路徑。

解壓:

tar -xzf freetype-2.8.tar.gz

進入其解壓文件目錄freetype-2.8

執行:

vi include/freetype/config/ftoption.h

這里我們打開以下兩個配置宏:
?

#define FT_CONFIG_OPTION_SYSTEM_ZLIB
#define FT_CONFIG_OPTION_USE_PNG

????????第一個配置宏表示使用系統安裝的 zlib 庫,因為 FreeType 支持 Gzip 壓縮文件,會使用到 zlib 庫, zlib之前我們移植好了;第二個配置宏表示支持 PNG bitmap 位圖,因為 FreeType 可以加載 PNG 格式的彩色位圖字形,需要依賴于 libpng 庫,這個庫前面我們也是移植好了。

????????接著執行如下命令對 FreeType 工程源碼進行配置:

./configure --prefix=/home/book/linux/tool/freetype/ --host=arm-poky-linux-gnueabi --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS="-I/home/book/linux/tool/zlib/include -L/home/book/linux/tool/zlib/lib" ZLIB_LIBS=-lz LIBPNG_CFLAGS="-I/home/book/linux/tool/png/include -L/home/book/linux/tool/libpng/lib" LIBPNG_LIBS=-lpng

--prefix 選項指定 FreeType 庫的安裝目錄; --host 選項設置為交叉編譯器名稱的前綴,

--with-zlib=yes 表示使用 zlib;

--with-bzip2=no 表示不使用 bzip2 庫; --with-png=yes 表示使用 libpng 庫; --with-harfbuzz=no 表示不使用 harfbuzz 庫。

ZLIB_CFLAGS 選項用于指定 zlib 的頭文件路徑和庫文件路徑,根據實際安裝路徑填寫; ZLIB_LIBS 選項指定鏈接的 zlib 庫的名稱;

LIBPNG_CFLAGS 選項用于指定 libpng 的頭文件路徑和庫文件路徑,根據實際安裝路徑填寫; LIBPNG_LIBS 選項用于指定鏈接的 libpng 庫的名稱

接下來編譯安裝:

make
make install

如果出現錯誤,那么有可能是環境沒設置錯誤,如果正確就跳過以下步驟。

1.確保指定的 zlib 和 libpng 庫路徑是正確的,并且庫文件存在:

ls /home/book/linux/tool/zlib/lib/libz.*
ls /home/book/linux/tool/libpng/lib/libpng.*

2.將庫路徑添加到 LDFLAGS 環境變量中,以確保鏈接器可以找到這些庫:

export LDFLAGS="-L/home/book/linux/tool/zlib/lib -L/home/book/linux/tool/libpng/lib"

3.確保 LIBPNG_LIBSZLIB_LIBS 環境變量設置正確:

export ZLIB_LIBS="-lz"
export LIBPNG_LIBS="-lpng"

4.最后程序執行鏈接編譯

./configure --prefix=/home/book/linux/tool/freetype/ --host=arm-poky-linux-gnueabi --with-zlib=yes --with-bzip2=no --with-png=yes --with-harfbuzz=no ZLIB_CFLAGS="-I/home/book/linux/tool/zlib/include -L/home/book/linux/tool/zlib/lib" ZLIB_LIBS="-lz" LIBPNG_CFLAGS="-I/home/book/linux/tool/png/include -L/home/book/linux/tool/libpng/lib" LIBPNG_LIBS="-lpng"

make?

make install

移植到開發板

????????接下來將編譯得到的動態鏈接庫文件拷貝到開發板 Linux 系統/usr/lib 目錄,在拷貝之前,需將/usr/lib 目錄下原有的 FreeType 庫文件刪除掉,執行下面這條命令:

rm -rf /usr/lib/libfreetype.*

????????刪除之后,再將我們編譯得到的庫文件拷貝到開發板/usr/lib 目錄下,也就是 FreeType 安裝目錄 lib 目錄下的所有庫文件,拷貝的時候注意符號鏈接的問題。拷貝完成之后,如下所示:

,建議用nfs。

將文件傳至nfs后

sudo cp -r /mnt/lib/* /usr/lib/

注意:不要忘了*,因為鏈接也要傳過去

如果是scp的話:

sudo mv /home/user/temp_lib/* /usr/lib/

注意后面的鏈接不能丟

基本概念:

????????????????像素點數 = 點數 * dpi / 72

????????譬如,假設某一顯示設備水平方向 dpi 為 300,已知水平方向的點數為 50,那么像素點數的計算方式為:

50 * 300 / 72 = 208 所以可以算出像素點數為 208,

例程:例程這兒引用韋東山老師的源碼

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <sys/ioctl.h>#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_Hint fd_fb;
struct fb_var_screeninfo var;   /* Current var */
struct fb_fix_screeninfo fix;   /* Current fix */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;/* color : 0x00RRGGBB */
void lcd_put_pixel(int x, int y, unsigned int color)
{unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;unsigned short *pen_16; unsigned int *pen_32;   unsigned int red, green, blue;  pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch (var.bits_per_pixel){case 8:{*pen_8 = color;break;}case 16:{/* 565 */red   = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue  = (color >> 0) & 0xff;color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);*pen_16 = color;break;}case 32:{*pen_32 = color;break;}default:{printf("can't surport %dbpp\n", var.bits_per_pixel);break;}}
}/*********************************************************************** 函數名稱: draw_bitmap* 功能描述: 根據bitmap位圖,在LCD指定位置顯示漢字* 輸入參數: x坐標,y坐標,位圖指針* 輸出參數: 無* 返 回 值: 無* 修改日期        版本號     修改人        修改內容* -----------------------------------------------* 2020/05/12        V1.0     zh(angenao)         創建***********************************************************************/ 
void
draw_bitmap( FT_Bitmap*  bitmap,FT_Int      x,FT_Int      y)
{FT_Int  i, j, p, q;FT_Int  x_max = x + bitmap->width;FT_Int  y_max = y + bitmap->rows;//printf("x = %d, y = %d\n", x, y);for ( j = y, q = 0; j < y_max; j++, q++ ){for ( i = x, p = 0; i < x_max; i++, p++ ){if ( i < 0      || j < 0       ||i >= var.xres || j >= var.yres )continue;//image[j][i] |= bitmap->buffer[q * bitmap->width + p];lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);}}
}int compute_string_bbox(FT_Face       face, wchar_t *wstr, FT_BBox  *abbox)
{int i;int error;FT_BBox bbox;FT_BBox glyph_bbox;FT_Vector pen;FT_Glyph  glyph;FT_GlyphSlot slot = face->glyph;/* 初始化 */bbox.xMin = bbox.yMin = 32000;bbox.xMax = bbox.yMax = -32000;/* 指定原點為(0, 0) */pen.x = 0;pen.y = 0;/* 計算每個字符的bounding box *//* 先translate, 再load char, 就可以得到它的外框了 */for (i = 0; i < wcslen(wstr); i++){/* 轉換:transformation */FT_Set_Transform(face, 0, &pen);/* 加載位圖: load glyph image into the slot (erase previous one) */error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}/* 取出glyph */error = FT_Get_Glyph(face->glyph, &glyph);if (error){printf("FT_Get_Glyph error!\n");return -1;}/* 從glyph得到外框: bbox */FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);/* 更新外框 */if ( glyph_bbox.xMin < bbox.xMin )bbox.xMin = glyph_bbox.xMin;if ( glyph_bbox.yMin < bbox.yMin )bbox.yMin = glyph_bbox.yMin;if ( glyph_bbox.xMax > bbox.xMax )bbox.xMax = glyph_bbox.xMax;if ( glyph_bbox.yMax > bbox.yMax )bbox.yMax = glyph_bbox.yMax;/* 計算下一個字符的原點: increment pen position */pen.x += slot->advance.x;pen.y += slot->advance.y;}/* return string bbox */*abbox = bbox;
}int display_string(FT_Face     face, wchar_t *wstr, int lcd_x, int lcd_y)
{int i;int error;FT_BBox bbox;FT_Vector pen;FT_Glyph  glyph;FT_GlyphSlot slot = face->glyph;/* 把LCD坐標轉換為笛卡爾坐標 */int x = lcd_x;int y = var.yres - lcd_y;/* 計算外框 */compute_string_bbox(face, wstr, &bbox);/* 反推原點 */pen.x = (x - bbox.xMin) * 64; /* 單位: 1/64像素 */pen.y = (y - bbox.yMax) * 64; /* 單位: 1/64像素 *//* 處理每個字符 */for (i = 0; i < wcslen(wstr); i++){/* 轉換:transformation */FT_Set_Transform(face, 0, &pen);/* 加載位圖: load glyph image into the slot (erase previous one) */error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}/* 在LCD上繪制: 使用LCD坐標 */draw_bitmap( &slot->bitmap,slot->bitmap_left,var.yres - slot->bitmap_top);/* 計算下一個字符的原點: increment pen position */pen.x += slot->advance.x;pen.y += slot->advance.y;}return 0;
}int main(int argc, char **argv)
{wchar_t *wstr = L"百問網www.100ask.net";FT_Library    library;FT_Face       face;int error;FT_BBox bbox;int font_size = 24;int lcd_x, lcd_y;if (argc < 4){printf("Usage : %s <font_file> <lcd_x> <lcd_y> [font_size]\n", argv[0]);return -1;}lcd_x = strtoul(argv[2], NULL, 0);      lcd_y = strtoul(argv[3], NULL, 0);      if (argc == 5)font_size = strtoul(argv[4], NULL, 0);      fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix)){printf("can't get fix\n");return -1;}line_width  = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fbmem == (unsigned char *)-1){printf("can't mmap\n");return -1;}/* 清屏: 全部設為黑色 */memset(fbmem, 0, screen_size);error = FT_Init_FreeType( &library );              /* initialize library */error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */FT_Set_Pixel_Sizes(face, font_size, 0);display_string(face, wstr, lcd_x, lcd_y);return 0;   
}

編譯:

${CC} -o show_line show_line.c -I/home/book/linux/tool/freetype/include/freetype2 -L/home/book/linux/tool/freetype/lib -lfreetype -L/home/book/linux/tool/zlib/lib -lz -L/home/book/linux/tool/libpng/lib -lpng -lm

后將show_line和simsun.ttc傳過去,運行成功(simsun.ttc是定義的字體文件)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38824.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38824.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38824.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

X86 +PC104+支持WinCE5.0,WinCE6.0,DOS,WinXP, QNX等操作系統,工業控制數據采集核心模塊板卡定制

CPU 模塊 是一款基于RDC 3306的SOM Express模塊。RDC 3306這款X86架構的CPU是一款性能高、穩定性強的處理器。 它是一款靈活精巧的主板&#xff08;尺寸為91.8mm68.6mm&#xff09;&#xff0c;可以靈活的運用于用戶的底板&#xff0c;節約開發成本。模塊的接插件使用插針形式…

人工智能在音樂創作中的雙刃劍:創新與挑戰

AI在創造還是毀掉音樂&#xff1f; 簡介 最近一個月&#xff0c;輪番上線的音樂大模型&#xff0c;一舉將素人生產音樂的門檻降到了最低&#xff0c;并掀起了音樂圈會不會被AI徹底顛覆的討論。短暫的興奮后&#xff0c;AI產品的版權歸屬于誰&#xff0c;創意產業要如何在AI的陰…

pom文件-微服務項目結構

一、微服務項目結構 my-microservices-project/ ├── pom.xml <!-- 父模塊的pom.xml --> ├── ry-system/ │ ├── pom.xml <!-- 子模塊ry-system的pom.xml --> │ └── src/main/java/com/example/rysystem/ │ └── RySystemApplication.…

數據類型

數據類型 注意&#xff1a;每個字段都必須設置數據類型 整數類型 tinyint - 1字節 - 應用場景&#xff1a;存儲狀態碼 int - 4字節 - 應用場景&#xff1a;沒有特殊要求&#xff0c;一般使用int bigint - 8字節 - 應用場景&#xff1a;存儲極大的整數 CREATE TABLE user (use…

Elasticsearch8.x Spring Data and Spring Boot 3 嘗鮮

在本教程中,我們將通過實際操作和實用的方式,探索使用 Spring Boot 進行 Elasticsearch 的基礎知識。我們將學習如何使用 Spring Data Elasticsearch 模塊創建索引、進行 CRUD 操作、搜索和查詢 Elasticsearch 文檔。我們還將看看如何在我們的 Spring 應用程序中記錄 Elastic…

全網最全的TTS模型匯總,電商人、自媒體人狂喜

近日TTS語音模型在AI圈內熱度不小&#xff0c;今天小編就來給大家做了個TTS模型匯總&#xff01; GPT-SoVITS&#xff08;AI 賣貨主播大模型Streamer-Sales銷冠用的TTS模型&#xff09; 模型簡介&#xff1a;支持英語、日語和中文&#xff0c;零樣本文本到語音&#xff08;TT…

【INTEL(ALTERA)】Nios II軟件開發人員手冊中設計位置的錯誤示例

目錄 說明 解決方法 說明 Nios II軟件開發人員手冊正確無誤 請參閱 Nios 中包含的Nios II硬件設計示例 II 嵌入式設計套件 &#xff08;EDS&#xff09;。提供設計示例 設計上 Altera網站的示例頁面。 Nios II軟件開發人員手冊正確無誤 請參閱 創建本應用程序和創建本 bsp …

Python UUID模塊:深入理解與使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:「stormsha的主頁」…

Atom CMS v2.0 SQL 注入漏洞(CVE-2022-25488)

前言 CVE-2022-25488 是一個發現于 Telesquare SDT-CW3B1 設備中的命令注入漏洞。這一漏洞可以被未經認證的遠程攻擊者利用&#xff0c;通過特殊構造的 HTTP 請求在設備上執行任意命令。以下是關于該漏洞的詳細信息&#xff1a; 漏洞詳細信息 漏洞編號: CVE-2022-25488影響范…

沃爾核材:價值重估

當英偉達這個曾經的GPU行業龍頭&#xff0c;伴隨AI的發展成為AI芯片架構的供應商時&#xff0c;他就跳出了原本行業的競爭格局&#xff0c;曾經還能與之一戰的超威半導體被遠遠甩在身后&#xff0c;成為宇宙第一公司。 這說的就是一家公司價值的重估。今天給大家聊的也是這樣一…

LIMS系統在汽車行業中的應用有哪些優勢

LIMS實驗室管理系統在汽車行業中的應用有諸多優勢&#xff0c;這些優勢不僅提升了實驗室的管理效率&#xff0c;還確保了數據的準確性和可靠性&#xff0c;進而促進了汽車行業的整體發展。 一、提升管理效率 自動化數據處理 LIMS系統能夠自動化處理大量數據&#xff0c;顯著減…

Python層次密度聚類算法庫之HDBSCAN使用詳解

概要 HDBSCAN 是一種層次密度聚類算法,它通過密度連接性來構建聚類層次結構。與傳統的 K-Means 算法相比,HDBSCAN 具有以下幾個顯著特點: 自動確定聚類數量:HDBSCAN 能夠根據數據自動確定聚類數量,不需要預先指定。 適應噪聲和異常點:HDBSCAN 在聚類過程中能夠很好地處理…

后端之路(集合項目)——結合案例正式搭建項目

在前面學完java后端的Maven、spring boot、Mysql、Mybatis之后&#xff0c;我們現在就應該集合它們開始搭建一個項目試試手了 這里我還是跟著黑馬程序員的步驟來走好每一步&#xff0c;也給各位講清楚怎么弄 先看一下這個圖&#xff0c;覺得太籠統不明白的話不著急&#xff0c…

Java面試題總結

Redis篇 什么是緩存穿透 ? 怎么解決 ? 緩存穿透是指查詢一個不存在的數據&#xff0c;如果從存儲層查不到數據則不寫入緩存&#xff0c;這將導致這個不存在的數據每次請求都要到 DB 去查詢&#xff0c;可能導致 DB 掛掉。這種情況大概率是遭到了攻擊。 解決方案有兩種&…

Arthas實戰(2)- OOM問題排查

一、 準備測試應用 新建一個 SpringBoot應用&#xff0c;寫一段有 OOM bug 的代碼&#xff1a; RestController RequestMapping public class JvmThreadController {List<TestWrapper> memoryList new ArrayList<>();GetMapping("/test")public Strin…

mov文件怎么轉換成mp4格式?這四種轉換方法超級好用!

mov文件怎么轉換成mp4格式&#xff1f;在數字娛樂的世界中&#xff0c;你是否曾遇到過MOV格式的視頻&#xff1f;也許&#xff0c;對于許多人來說&#xff0c;這并不是一個常見的格式&#xff0c;但這并非偶然&#xff0c;首先&#xff0c;我們來談談MOV的兼容性問題&#xff0…

使用python做飛機大戰

代碼地址: 點擊跳轉

不看測評盲買花了多少冤枉錢..測評希喂、愛立方、帕特看完不踩雷

主食凍在挑選主食凍干時&#xff0c;許多寵物主人都會感到頭疼。盡管主食凍干相較于普通貓糧具有諸多優勢&#xff0c;但其價格也相對高昂。這導致許多寵物主人擔心高價購買的主食凍干可能營養價值并不理想。然而&#xff0c;在選擇時&#xff0c;我們還需要考慮其他重要因素&a…

“穿越時空的機械奇觀:記里鼓車的歷史與科技探秘“

在人類文明的發展歷程中&#xff0c;科技的創新與進步不僅僅推動了社會的進步&#xff0c;也為我們留下了豐富的文化遺產。記里鼓車&#xff0c;作為一種古老的里程計量工具&#xff0c;其歷史地位和技術成就在科技史上具有重要的意義。本文將詳細介紹記里鼓車的起源、結構原理…

0基礎學C++ | 第10天 | 基礎知識 |程序的內存模型 | 4大分區

前言 第9天是一個通訊錄管理系統案例&#xff0c;現在了解程序的內存分區&#xff0c;C程序在執行時&#xff0c;將內存大方向分為了4個區域&#xff0c;分別是代碼區、全局區、棧區、堆區&#xff0c;分區的目的就是為了更加靈活的編程。 代碼區 and 全局區&#xff08;程序…