Linux應用開發基礎知識——LInux學習FreeType編程(七)

目錄

一、使用freetype 顯示一個文字

二、使用 freetype 顯示一行文字

1. 了解笛卡爾坐標系

2. 每個字符的大小可能不同

3. 怎么在指定位置顯示一行文字

4. freetype 的幾個重要數據結構

4.1、FT_Library結構體

4.2、FT_Face結構體

4.3、FT_GlyphSlot結構體

4.4、FT_Glyph結構體

4.5、FT_BBox結構體

5.讀懂顯示一行字體的代碼

draw函數

第一步

第二步:計算外框

第三步:調整坐標

第四步: 轉換、加載位圖、繪制

第五步:上機實驗


一、使用freetype 顯示一個文字

之前學習Framebuffer的時候,把它和Framebuffer寫在了一起,可以看看我寫的這個文章:Framebuffer應用編程

二、使用 freetype 顯示一行文字

1. 了解笛卡爾坐標系

在 LCD 的坐標系中,原點在屏幕的左上角。對于笛卡爾坐標系,原點在左下角。freetype 使用笛卡爾坐標系,在顯示時需要轉換為 LCD 坐標系。
在這里插入圖片描述

V:縱向總像素個數
從圖可知,X 方向坐標值是一樣的。
在 Y 方向坐標值需要換算,假設 LCD 的高度是 V。
在 LCD 坐標系中坐標是(x, y),那么它在笛卡爾坐標系中的坐標值為(x, V-y)。
反過來也是一樣的,在笛卡爾坐標系中坐標是(x, y),那么它在 LCD 坐標系中坐標值為(x, V-y)。

2. 每個字符的大小可能不同

在使用?FT_Set_Pixel_Sizes?函數設置字體大小時,這只是“期望值”。比如“百問網 www.100ask.net”,如果把“.”顯示得跟其他漢字一樣大,不好看。
所以在顯示一行文字時,后面文字的位置會受到前面文字的影響。
例:
在這里插入圖片描述幸好,freetype 幫我們考慮到了這些影響。
對于?freetype?字體的尺寸(freetype?Metrics),需要參考圖:
在這里插入圖片描述
在顯示一行文字時,這些文字會基于同一個基線來繪制位圖:baseline
在?baseline?上,每一個字符都有它的原點(origin),比如上圖中?baseline左邊的黑色圓點就是字母“g”的原點。當前?origin?加上?advance?就可以得到下一個字符的?origin,比如上圖中?baseline?右邊的黑色圓點。在顯示一行中多個文件字時,后一個文字的原點依賴于前一個文字的原點及?advance

有圖可得:
origin + advance = origin(下一個字的)

字符的位圖是有可能越過?baseline?的,比如上圖中字母“g”在?baseline下方還有像。
上圖中紅色方框內就是字母“g”所點據的位圖,它的四個角落不一定與原點
重合。
上圖中那些?xMin 、 xMax 、 yMin 、 yMax?如 何 獲 得 ? 可 以 使 用
FT_Glyph_Get_CBox?函數獲得一個字體的這些參數,將會保存在一個 FT_BBox結構體中,以后想計算一行文字的外框時要用到圖這些信息:
在這里插入圖片描述
更多結構體后面會詳細說明!!

3. 怎么在指定位置顯示一行文字

要顯示一行文字時,每一個字符都有自己外框:xMin、xMax、yMin、yMax。把這些字符的?xMin、yMin?中的最小值取出來,把這些字符的?xMax、yMax?中的最大值取出來,就可以確定這行文字的外框了。

要想在指定位置(x, y)顯示一行文字,步驟如圖所示:
在這里插入圖片描述

第1步 先指定第 1 個字符的原點 pen 坐標為(0, 0),計算出它的外框
第2步 再計算右邊字符的原點,也計算出它的外框
把所有字符都處理完后就可以得到一行文字的整體外框:假設外框左上角坐標為(x’, y’)。
第3步 想在(x, y)處顯示這行文字,調整一下 pen 坐標即可。怎么調整?
pen 為(0, 0)時對應左上角(x’, y’);那么左上角為(x, y)時就可以算出pen 為(x-x’, y-y’)。

4. freetype 的幾個重要數據結構

4.1、FT_Library結構體

對應 freetype 庫,使用 freetype 之前要先調用以下代碼:

FT_Library library; /* 對應 freetype 庫 */
error = FT_Init_FreeType( &library ); /* 初始化 freetype 庫 */

4.2、FT_Face結構體

它對應一個矢量字體文件,在源碼中使用?FT_New_Face?函數打開字體文件后,就可以得到一個?FT_Face結構體face
為什么稱之為 face?
估計是文字都是寫在二維平面上的吧,正對著人臉?不用管原因了,總之認為它對應一個字體文件就可以。
代碼如下:

error = FT_New_Face(library, font_file, 0, &face ); /* 加載字體文件 */

4.3、FT_GlyphSlot結構體

插槽?用來保存字符的處理結果:比如轉換后的 glyph、位圖,如圖:
在這里插入圖片描述

上一個說的FT_Face結構體里面成員有一個FT_GlyphSlot結構體,里面保存的是字符的處理結果(含有變換后的glyph、位圖、advance等信息)
一個 face 中有很多字符,生成一個字符的點陣位圖時,位圖保存在哪里?
保存在插槽中:face->glyph
生成第 1 個字符位圖時,它保存在 face->glyph 中;生成第 2 個字符位圖時,也會保存在 face->glyph 中,會覆蓋第 1 個字符的位圖。
所以我們生成后要及時取走,防止覆蓋!
使用當中我們通常會定義一個變量來保存:
FT_GlyphSlot slot = face->glyph; /?插槽: 字體的處理結果保存在這里?/

4.4、FT_Glyph結構體

字體文件中保存有字符的原始關鍵點信息,使用 freetype 的函數可以放大、縮小、旋轉,這些新的關鍵點保存在插槽中(注意:位圖也是保存在插槽中)。
新的關鍵點使用?FT_Glyph?來表示,可以使用這樣的代碼從 slot 中獲得glyph:

error = FT_Get_Glyph(slot , &glyph);

4.5、FT_BBox結構體

FT_BBox?結構體定義如下,它表示一個字符的外框,即新?glyph?的外框:
在這里插入圖片描述
可以使用以下代碼從 glyph 中獲得這些信息:

FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox );

5.讀懂顯示一行字體的代碼

學習了上面的一堆基礎知識,我們就懂了步驟:
第1步 先指定第 1 個字符的原點 pen 坐標為(0, 0),計算出它的外框
第2步 再計算右邊字符的原點,也計算出它的外框
把所有字符都處理完后就可以得到一行文字的整體外框:假設外框左上角坐標為(x’, y’)。
第3步 想在(x, y)處顯示這行文字,調整一下 pen 坐標即可。怎么調整?
pen 為(0, 0)時對應左上角(x’, y’);那么左上角為(x, y)時就可以算出pen 為(x-x’, y-y’)。
第4步 轉換、加載位圖、繪制一個字符,計算下一個字符origin,繼續繪制下一個字符…依次循環

完整的代碼如下:

#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)         創建***********************************************************************/ /* 在LCD上繪制: 使用LCD坐標 */
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)
{/* FT_Face face :   對應一個字體文件 */int i;             //用于for循環計算次數int error;         //用于保存函數返回值FT_BBox bbox;      //初始外框FT_BBox glyph_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);/* 加載位圖: 一個字一個字得去加載位圖 會保存在face里面 */error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}/* 在face結構體里面取出新的關鍵點保存在變量glyph里(從 slot 中獲得glyph) */error = FT_Get_Glyph(face->glyph, &glyph);if (error){printf("FT_Get_Glyph error!\n");return -1;}/* 從glyph得到外框: bbox,然后保存在變量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);//將輸入的X坐標轉換成想要的形式      lcd_y = strtoul(argv[3], NULL, 0);//將輸入的Y坐標轉換成想要的形式      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 );               /* 初始化 freetype 庫 */error = FT_New_Face( library, argv[1], 0, &face ); /* 加載字體文件 */FT_Set_Pixel_Sizes(face, font_size, 0);            /* 設置字體大小 */display_string(face, wstr, lcd_x, lcd_y);          /*  */return 0;   
}

draw函數

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)
{/* FT_Face face :   對應一個字體文件 */int i;             //用于for循環計算次數int error;         //用于保存函數返回值FT_BBox bbox;      //初始外框FT_BBox glyph_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);/* 加載位圖: 一個字一個字得去加載位圖 會保存在face里面 */error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}/* 在face結構體里面取出新的關鍵點保存在變量glyph里(從 slot 中獲得glyph) */error = FT_Get_Glyph(face->glyph, &glyph);if (error){printf("FT_Get_Glyph error!\n");return -1;}/* 從glyph得到外框: bbox,然后保存在變量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;
}

第五步:上機實驗

在這里插入圖片描述

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

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

相關文章

Kotlin中Flow

Kotlin Flow 深度解析&#xff1a;從原理到實戰一、Flow 核心概念體系1. Flow 的本質與架構Flow 是 Kotlin 協程庫中的異步數據流處理框架&#xff0c;核心特點&#xff1a;響應式編程&#xff1a;基于觀察者模式的數據處理協程集成&#xff1a;無縫融入 Kotlin 協程生態背壓支…

Java程序員學從0學AI(七)

一、前言 上一篇文章圍繞 Spring AI 的 Chat Memory&#xff08;聊天記憶&#xff09;功能展開&#xff0c;先是通過代碼演示了不使用 Chat Memory 時&#xff0c;大模型因無狀態無法記住上下文&#xff08;如用戶姓名&#xff09;的情況&#xff0c;隨后展示了使用基于內存的 …

ESP32S3 防貓逃脫監測系統

在辦公室里&#xff0c;兩只可愛的貓咪給大家帶來了不少歡樂&#xff0c;但其中一只總愛趁人不注意溜出房間&#xff0c;有時下班后還會被鄰居告知它被鎖在了外面。為了解決這個問題&#xff0c;我開發了一個基于 SeeedStudio XIAO ESP32S3 Sense 的貓咪逃脫監測預警系統&#…

Python|OpenCV-實現快速處理圖像的方法(23)

前言 本文是該專欄的第25篇,后面將持續分享OpenCV計算機視覺的干貨知識,記得關注。 在視覺算法落地流程中,數據預處理往往占用 60 % 以上的工程時間。以某沿海城市智慧旅游項目為例,我們從無人機錄制的 4K 海灘視頻中抽幀得到 10 000 張 PNG 原圖,分辨率 38402160,單張體…

Redis四種GetShell方式完整教程

Redis作為高性能內存數據庫&#xff0c;若未正確配置認證和訪問控制&#xff0c;可能被攻擊者利用實現遠程代碼執行&#xff08;GetShell&#xff09;。本文詳細講解四種常見的Redis GetShell方式&#xff0c;涵蓋原理、操作步驟及防御建議。方式一&#xff1a;直接寫入Shell腳…

clock_nanosleep系統調用及示例

41. clock_nanosleep - 高精度睡眠 函數介紹 clock_nanosleep系統調用提供納秒級精度的睡眠功能&#xff0c;支持絕對時間和相對時間兩種模式&#xff0c;比傳統的nanosleep更加靈活。 函數原型 #include <time.h>int clock_nanosleep(clockid_t clock_id, int flags,con…

用了Flutter包體積增大就棄用Flutter嗎?包體積與開發效率,這兩者之間如何權衡?

是否因包體積增大而棄用 Flutter&#xff0c;本質上是 “短期成本&#xff08;包體積&#xff09;” 與 “長期價值&#xff08;跨平臺效率、體驗一致性等&#xff09;” 的權衡 。這一決策沒有絕對答案&#xff0c;需結合項目階段、用戶群體、業務需求等具體場景分析。以下從核…

80道面試經典題目

1.OSI參考模型七層網絡協議? 物理層:定義計算機、網絡設備、以及直接連接的介質、接口類型的標準,建立比特流的傳輸,用來組件物理網絡的連接。 數據鏈路層:建立邏輯連接、進行硬件地址尋址,差錯校驗、差錯恢復等功能。 網絡層:進行邏輯地址尋址,實現不同網絡之間的通…

本周大模型新動向:KV緩存壓縮、低成本高性能推理框架、多智能體協作

點擊藍字關注我們AI TIME歡迎每一位AI愛好者的加入&#xff01;01Compress Any Segment Anything Model (SAM)受SAM在零樣本分割任務上卓越表現的驅動&#xff0c;其各類變體已被廣泛應用于醫療、智能制造等場景。然而&#xff0c;SAM系列模型體量巨大&#xff0c;嚴重限制了在…

利用frp實現內網穿透功能(服務器)Linux、(內網)Windows

適用于&#xff1a; 本地電腦&#xff08;windows&#xff09;或者Linux(本篇未介紹&#xff09; 工具&#xff1a;FRP&#xff08;fast reverse proxy&#xff09; 系統&#xff1a;Linux、Windows 架構&#xff1a;x86、amd Frp版本&#xff1a;frp_0.62.1_windows_amd64準備…

結合二八定律安排整塊時間

你是不是常常感覺一天到晚忙忙碌碌&#xff0c;卻總覺得沒干成幾件“要緊事”&#xff1f;時間仿佛從指縫間溜走&#xff0c;成就感卻遲遲不來&#xff1f;其實&#xff0c;高效能人士的秘訣往往藏在最簡單的原則里。今天&#xff0c;我們就來聊聊如何巧妙運用“二八定律”&…

波形發生器AWG硬件設計方案

目錄 簡介 設計需求 設計方案 核心原理圖展示 簡介 波形發生器是一種數據信號發生器&#xff0c;在調試硬件時&#xff0c;常常需要加入一些信號&#xff0c;以觀察電路工作是否正常。用一般的信號發生器&#xff0c;不但笨重&#xff0c;而且只發一些簡單的波形&#xff…

11.Dockerfile簡介

1.是什么&#xff1f; dockerfile是用來構建鏡像的文本文件&#xff0c;是由一條條構建鏡像所需的指令和參數構成的腳本。 構建三步驟 編寫dockerfile文件docker build命令構建鏡像docker run依鏡像運行的容器實列 2.dockerfile構建過程解析 1)dockerfile內容的基礎知識 …

C# 接口(interface 定義接口的關鍵字)

目錄 使用接口案例 接口繼承 練習 定義一個接口&#xff0c;在語法中與定義一個抽象類是沒有區別的&#xff0c;但是不允許提供接口中任意成員的實現方式&#xff0c;一般接口只會包含方法 、索引器和事件的聲明&#xff0c; 不允許聲明成員的修飾符&#xff0c; public都不…

5190 - 提高:DFS序和歐拉序:樹上操作(區域修改1)

題目傳送門 時間限制 : 2 秒 內存限制 : 256 MB 有一棵點數為 N 的樹&#xff0c;以點 1 為根&#xff0c;且樹點有邊權。然后有 M 個 操作&#xff0c;分為三種&#xff1a; 操作 1 &#xff1a;把某個節點 x 的點權增加 a 。 操作 2 &#xff1a;把某個節點 x 為根的子樹中…

【Oracle】數據泵

ORACLE數據庫 數據泵 核心參數全解析 ORACLE expdp 命令使用詳解 1.ATTACH[schema_name.]job_name Schema_name 用于指定方案名,job_name 用于指定導出作業名.注意,如果使用 ATTACH 選項,在命令行除了連接字符串和 ATTACH 選項外,不能指定任何其他選項,示例如下: expdp hr/hr A…

機器學習的算法有哪些?

&#x1f31f; 歡迎來到AI奇妙世界&#xff01; &#x1f31f; 親愛的開發者朋友們&#xff0c;大家好&#xff01;&#x1f44b; 我是人工智能領域的探索者與分享者&#xff0c;很高興在CSDN與你們相遇&#xff01;&#x1f389; 在這里&#xff0c;我將持續輸出AI前沿技術、實…

【計算機網絡】OSI七層模型

OSI七層模型為什么需要OSI七層模型&#xff1f;OSI七層模型具體是什么&#xff1f;Layer7&#xff1a;應用層&#xff08;Application Layer&#xff09;Layer6&#xff1a;表示層&#xff08;Presentation Layer&#xff09;Layer5&#xff1a;會話層&#xff08;Session Laye…

RS485轉Profinet網關配置指南:高效啟動JRT激光測距傳感器測量模式

RS485轉Profinet網關配置指南&#xff1a;高效啟動JRT激光測距傳感器測量模式RS485轉Profinet網關&#xff1a;讓JRT激光測距傳感器高效開啟測量模式在工業自動化場景中&#xff0c;設備間的高效通信是實現精準控制的關鍵。RS485轉Profinet網關作為連接傳統RS485設備與現代Prof…

「日拱一碼」040 機器學習-不同模型可解釋方法

目錄 K最近鄰(KNN) - 基于距離的模型 決策邊界可視化 查看特定樣本的最近鄰 ?隨機森林(RF) - 樹模型 feature_importances_ SHAP值分析 可視化單棵樹 多層感知器(MLP) - 神經網絡 部分依賴圖 LIME解釋器 權重可視化 支持向量回歸(SVR) - 核方法 支持向量可視化 部…