1. 程式人生 > >【嵌入式】利用freetype字型庫(繪製中文)

【嵌入式】利用freetype字型庫(繪製中文)

終極目標:利用freetype開源字型庫,實現在圖片上書寫一行字型大小變化的詩句(比如首字型增大)

目錄

(一) 樹莓派3b+freetype2.4.10

1. 下載

我是在PC上下載好Linux版本,用teamviewer傳到派上的;也可以直接在pi上下載。

官網連結:https://sourceforge.net/projects/freetype/files/freetype2/

注意:Linux系統下需要的版本為:freetype-2.*.*.tar.br2;版本自選。
在這裡插入圖片描述
我選擇的是2.4.10,可任選
在這裡插入圖片描述
用teamviewer直接傳檔案到/home/pi目錄下:
在這裡插入圖片描述

2. 解壓及配置

  • 進入命令模式
  • 解壓(對應版本):
tar -xjf freetype-2.4.10.tar.bz2

在這裡插入圖片描述

  • 進入安裝包:
cd freetype-2.4.10/

在這裡插入圖片描述

  • 配置:
./configure

在這裡插入圖片描述
配置完成如圖:
在這裡插入圖片描述

  • 編譯:(需要幾分鐘時間)
make

在這裡插入圖片描述
編譯完成如圖:
在這裡插入圖片描述

  • 直接將庫安裝到根目錄/usr/local/裡,所以需要加sudo:
sudo make install

在這裡插入圖片描述
完成如圖:
在這裡插入圖片描述

3. 新增字型庫

  • 檢視本地字型庫目錄
樹莓派:/usr/share/fonts
Windows:C:\Windows\Fonts

經檢視,我的pi目錄下沒有宋體(simhei.ttf)、(simsun.ttc)的字型檔案,我從pc上傳了一份過去,注意填寫的接收地址。
在這裡插入圖片描述

4. 一個簡單的Demo

  • 新建資料夾freetype_test
  • 將剛才傳輸的simsun.ttc字型庫樣式複製到freetype_test資料夾下
  • freetype_test資料夾下建立 test.cpp
  • 編寫程式碼(這裡的原始碼我是參照網上的,先直接拖進去試試水)
#include <stdio.h>
#include <string.h>
#include <math.h>
 
#include <ft2build.h>
#include FT_FREETYPE_H
 
 
#define WIDTH   80
#define HEIGHT  80
 
 
/* origin is the upper left corner */
unsigned char image[HEIGHT][WIDTH];
 
 
/* Replace this function with something useful. */
 
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;
 
 
  for ( i = x, p = 0; i < x_max; i++, p++ )
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
      if ( i < 0      || j < 0       ||
           i >= WIDTH || j >= HEIGHT )
        continue;
 
      image[j][i] |= bitmap->buffer[q * bitmap->width + p];
    }
  }
}
 
 
void
show_image( void )
{
  int  i, j;
 
 
  for ( i = 0; i < HEIGHT; i++ )
  {
    for ( j = 0; j < WIDTH; j++ )
      putchar( image[i][j] == 0 ? ' '
                                : image[i][j] < 128 ? '+'
                                                    : '*' );
    putchar( '\n' );
  }
}
 
 
int
main( int     argc,
      char**  argv )
{
  FT_Library    library;
  FT_Face       face;
 
  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;
 
  char*         filename;
  char*         text;
 
  double        angle;
  int           target_height;
  int           n, num_chars;
 
 
  if ( argc != 3 )
  {
    fprintf ( stderr, "usage: %s font sample-text\n", argv[0] );
    exit( 1 );
  }
 
  filename      = argv[1];                           /* first argument     */
  text          = argv[2];                           /* second argument    */
  num_chars     = strlen( text );
  angle         = ( 0.0 / 360 ) * 3.14159 * 2;      /* use 25 degrees     */
  target_height = HEIGHT;
 
  error = FT_Init_FreeType( &library );              /* initialize library */
  /* error handling omitted */
 
  error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
  /* error handling omitted */
 
#if 0
  /* use 50pt at 100dpi */
  error = FT_Set_Char_Size( face, 50 * 64, 0,
                            100, 0 );                /* set character size */
 
	/* pixels = 50 /72 * 100 = 69  */
#else
	FT_Set_Pixel_Sizes(face, 24, 0);
#endif
  /* error handling omitted */
 
  slot = face->glyph;
 
  /* set up matrix */
  matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
  matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
  matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
  matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
 
  /* the pen position in 26.6 cartesian space coordinates; */
  /* start at (0,40) relative to the upper left corner  */
  pen.x = 0 * 64;
  pen.y = ( target_height - 40 ) * 64;
 
  for ( n = 0; n < num_chars; n++ )
  {
    /* set transformation */
    FT_Set_Transform( face, &matrix, &pen );
 
    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
    if ( error )
      continue;                 /* ignore errors */
 
    /* now, draw to our target surface (convert position) */
    draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 target_height - slot->bitmap_top );
 
    /* increment pen position */
    pen.x += slot->advance.x;
    pen.y += slot->advance.y;
  }
 
  show_image();
 
  FT_Done_Face    ( face );
  FT_Done_FreeType( library );
 
  return 0;
}
  • 儲存
  • 回到命令列介面
  • 編譯
gcc -o test test.cpp -I/usr/local/include/freetype2/ -lfreetype -lm
  • 執行
./test ./simsun.ttc  cungu

在這裡插入圖片描述

  • 結果
    在這裡插入圖片描述
    配置成功!

5.freetype2+opencv3在圖片上繪製中文

參考連結:http://lib.csdn.net/article/opencv/53782?tdsourcetag=s_pcqq_aiomsg

  • 新建freetype_test資料夾,把simhei.ttf字型庫和圖片lena.jpg複製進來,新建freetype_test.cpp程式
    在這裡插入圖片描述
  • 執行測試()
g++ -o freetype_test freetype_test.cpp `pkg-config --cflags --libs opencv` -I/usr/local/include/freetype2/ -lfreetype -lm
  • 原始碼

#include <ft2build.h>  
#include FT_FREETYPE_H  
#include <highgui.h>  
#include <wchar.h>  
#include <assert.h>  
#include <locale.h>  
#include <ctype.h>  
#include <opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
class CvText
{


	//================================================================  
	//================================================================  

public:

	/**
	* 裝載字型檔檔案
	*/

	CvText(const char *freeType);
	virtual ~CvText();

	//================================================================  
	//================================================================  

	/**
	* 獲取字型。目前有些引數尚不支援。
	*
	* \param font        字型型別, 目前不支援
	* \param size        字型大小/空白比例/間隔比例/旋轉角度
	* \param underline   下畫線
	* \param diaphaneity 透明度
	*
	* \sa setFont, restoreFont
	*/

	void getFont(int *type,
		CvScalar *size = NULL, bool *underline = NULL, float *diaphaneity = NULL);

	/**
	* 設定字型。目前有些引數尚不支援。
	*
	* \param font        字型型別, 目前不支援
	* \param size        字型大小/空白比例/間隔比例/旋轉角度
	* \param underline   下畫線
	* \param diaphaneity 透明度
	*
	* \sa getFont, restoreFont
	*/

	void setFont(int *type,
		CvScalar *size = NULL, bool *underline = NULL, float *diaphaneity = NULL);

	/**
	* 恢復原始的字型設定。
	*
	* \sa getFont, setFont
	*/

	void restoreFont();

	//================================================================  
	//================================================================  

	/**
	* 輸出漢字(顏色預設為黑色)。遇到不能輸出的字元將停止。
	*
	* \param img  輸出的影象
	* \param text 文字內容
	* \param pos  文字位置
	*
	* \return 返回成功輸出的字元長度,失敗返回-1。
	*/

	int putText(cv::Mat &frame, const char    *text, CvPoint pos);

	/**
	* 輸出漢字(顏色預設為黑色)。遇到不能輸出的字元將停止。
	*
	* \param img  輸出的影象
	* \param text 文字內容
	* \param pos  文字位置
	*
	* \return 返回成功輸出的字元長度,失敗返回-1。
	*/

	int putText(cv::Mat &frame, const wchar_t *text, CvPoint pos);

	/**
	* 輸出漢字。遇到不能輸出的字元將停止。
	*
	* \param img   輸出的影象
	* \param text  文字內容
	* \param pos   文字位置
	* \param color 文字顏色
	*
	* \return 返回成功輸出的字元長度,失敗返回-1。
	*/

	int putText(cv::Mat &frame, const char    *text, CvPoint pos, CvScalar color);

	/**
	* 輸出漢字。遇到不能輸出的字元將停止。
	*
	* \param img   輸出的影象
	* \param text  文字內容
	* \param pos   文字位置
	* \param color 文字顏色
	*
	* \return 返回成功輸出的字元長度,失敗返回-1。
	*/
	int putText(cv::Mat &frame, const wchar_t *text, CvPoint pos, CvScalar color);

	//================================================================  
	//================================================================  

private:

	// 輸出當前字元, 更新m_pos位置  

	void putWChar(cv::Mat &frame, wchar_t wc, CvPoint &pos, CvScalar color);

	//================================================================  
	//================================================================  

private:

	FT_Library   m_library;   // 字型檔  
	FT_Face      m_face;      // 字型  

							  //================================================================  
							  //================================================================  

							  // 預設的字型輸出引數  

	int         m_fontType;
	CvScalar    m_fontSize;
	bool        m_fontUnderline;
	float       m_fontDiaphaneity;

	//================================================================  
	//================================================================  
};
int main()
{

	cv::Mat img = imread("lena.jpg");

	CvText text("simhei.ttf");
	const char *msg = "黑 體freetype";//字型檔要求輸入中文時中間必須有一個間隔
	float p = 0.5;
	text.setFont(NULL, NULL, NULL, &p);   // 透明處理 
	text.putText(img, msg, cvPoint(30, 30), CV_RGB(255, 255, 0));
	imshow("freetype_test", img);
	waitKey(-1);
	return 0;
}

CvText::CvText(const char *freeType)
{
	assert(freeType != NULL);

	// 開啟字型檔檔案, 建立一個字型  

	if (FT_Init_FreeType(&m_library)) throw;
	if (FT_New_Face(m_library, freeType, 0, &m_face)) throw;

	// 設定字型輸出引數  

	restoreFont();

	// 設定C語言的字符集環境  

	setlocale(LC_ALL, "");
}

// 釋放FreeType資源  

CvText::~CvText()
{
	FT_Done_Face(m_face);
	FT_Done_FreeType(m_library);
}

// 設定字型引數:  
//  
// font         - 字型型別, 目前不支援  
// size         - 字型大小/空白比例/間隔比例/旋轉角度  
// underline   - 下畫線  
// diaphaneity   - 透明度  

void CvText::getFont(int *type, CvScalar *size, bool *underline, float *diaphaneity)
{
	if (type) *type = m_fontType;
	if (size) *size = m_fontSize;
	if (underline) *underline = m_fontUnderline;
	if (diaphaneity) *diaphaneity = m_fontDiaphaneity;
}

void CvText::setFont(int *type, CvScalar *size, bool *underline, float *diaphaneity)
{
	// 引數合法性檢查  

	if (type)
	{
		if (type >= 0) m_fontType = *type;
	}
	if (size)
	{
		m_fontSize.val[0] = fabs(size->val[0]);
		m_fontSize.val[1] = fabs(size->val[1]);
		m_fontSize.val[2] = fabs(size->val[2]);
		m_fontSize.val[3] = fabs(size->val[3]);
	}
	if (underline)
	{
		m_fontUnderline = *underline;
	}
	if (diaphaneity)
	{
		m_fontDiaphaneity = *diaphaneity;
	}
	FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);
}

// 恢復原始的字型設定  

void CvText::restoreFont()
{
	m_fontType = 0;            // 字型型別(不支援)  

	m_fontSize.val[0] = 30;      // 字型大小  
	m_fontSize.val[1] = 0.5;   // 空白字元大小比例  
	m_fontSize.val[2] = 0.1;   // 間隔大小比例  
	m_fontSize.val[3] = 0;      // 旋轉角度(不支援)  

	m_fontUnderline = false;   // 下畫線(不支援)  

	m_fontDiaphaneity = 1.0;   // 色彩比例(可產生透明效果)  

							   // 設定字元大小  

	FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);
}

// 輸出函式(顏色預設為黑色)  

int CvText::putText(cv::Mat &frame, const char    *text, CvPoint pos)
{
	return putText(frame, text, pos, CV_RGB(255, 255, 255));
}
int CvText::putText(cv::Mat &frame, const wchar_t *text, CvPoint pos)
{
	return putText(frame, text, pos, CV_RGB(255, 255, 255));
}

//  

int CvText::putText(cv::Mat &frame, const char    *text, CvPoint pos, CvScalar color)
{



	if (frame.empty()) return -1;
	if (text == NULL) return -1;

	//  

	int i;
	for (i = 0; text[i] != '\0'; ++i)
	{
		wchar_t wc = text[i];

		// 解析雙位元組符號  

		if (!isascii(wc)) mbtowc(&wc, &text[i++], 2);

		// 輸出當前的字元  

		putWChar(frame, wc, pos, color);
	}
	return i;
}
int CvText::putText(cv::Mat &frame, const wchar_t *text, CvPoint pos, CvScalar color)
{

	if (frame.empty