Skip to content

Commit

Permalink
Add freetype
Browse files Browse the repository at this point in the history
  • Loading branch information
lz1998 committed Aug 11, 2021
1 parent e118065 commit a0dade1
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 0 deletions.
31 changes: 31 additions & 0 deletions contrib/freetype.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "freetype.h"

FreeType2 FreeType2_CreateFreeType2() {
return new cv::Ptr<cv::freetype::FreeType2>(cv::freetype::createFreeType2());
}

void FreeType2_Close(FreeType2 f) {
delete f;
}

void FreeType2_LoadFontData(FreeType2 f, const char *fontFileName, int id) {
(*f)->loadFontData(fontFileName, id);
}

void FreeType2_SetSplitNumber(FreeType2 f, int num) {
(*f)->setSplitNumber(num);
}

void FreeType2_PutText(FreeType2 f, Mat img, const char *text, Point org,
int fontHeight, Scalar color,
int thickness, int line_type, bool bottomLeftOrigin) {
cv::Point pt(org.x, org.y);
cv::Scalar c = cv::Scalar(color.val1, color.val2, color.val3, color.val4);
(*f)->putText(*img, text, pt, fontHeight, c, thickness, line_type, bottomLeftOrigin);
}

Size FreeType2_GetTextSize(FreeType2 f, const char *text,
int fontHeight, int thickness, int *baseLine) {
cv::Size sz = (*f)->getTextSize(text, fontHeight, thickness, baseLine);
return Size{sz.width, sz.height};
}
103 changes: 103 additions & 0 deletions contrib/freetype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package contrib

/*
#include <stdlib.h>
#include "freetype.h"
*/
import "C"
import (
"image"
"image/color"
"unsafe"

"gocv.io/x/gocv"
)

type FreeType2 struct {
// C.FreeType2
p unsafe.Pointer
}

// NewFreeType2 create instance to draw UTF-8 strings.
//
// For further details, please see:
// https://docs.opencv.org/master/d4/dfc/group__freetype.html#ga0fd8f9c0ae69bb4d95c41af79473a756
//
func NewFreeType2() FreeType2 {
return FreeType2{p: unsafe.Pointer(C.FreeType2_CreateFreeType2())}
}

// Close FreeType2.
func (f *FreeType2) Close() error {
C.FreeType2_Close((C.FreeType2)(f.p))
f.p = nil
return nil
}

// LoadFontData loads font data.
//
// For further details, please see:
// https://docs.opencv.org/master/d9/dfa/classcv_1_1freetype_1_1FreeType2.html#af059d49b806b916ffdd6380b9eb2f59a
//
func (f *FreeType2) LoadFontData(fontFileName string, id int) {
cFontFileName := C.CString(fontFileName)
defer C.free(unsafe.Pointer(cFontFileName))
C.FreeType2_LoadFontData((C.FreeType2)(f.p), cFontFileName, C.int(id))
}

// SetSplitNumber set the number of split points from bezier-curve to line.
// If you want to draw large glyph, large is better.
// If you want to draw small glyph, small is better.
//
// For further details, please see:
// https://docs.opencv.org/master/d9/dfa/classcv_1_1freetype_1_1FreeType2.html#a572143e6c68eab181387d9f4b3366f8b
//
func (f *FreeType2) SetSplitNumber(num int) {
C.FreeType2_SetSplitNumber((C.FreeType2)(f.p), C.int(num))
}

// PutText draws a text string.
// It renders the specified text string in the image.
// Symbols that cannot be rendered using the specified font are replaced by "Tofu" or non-drawn.
//
// For further details, please see:
// https://docs.opencv.org/master/d9/dfa/classcv_1_1freetype_1_1FreeType2.html#aba641f774c47a70eaeb76bf7aa865915
//
func (f *FreeType2) PutText(img *gocv.Mat, text string, org image.Point,
fontHeight int, c color.RGBA, thickness int, lineType gocv.LineType, bottomLeftOrigin bool) {
cText := C.CString(text)
defer C.free(unsafe.Pointer(cText))

sOrg := C.struct_Point{
x: C.int(org.X),
y: C.int(org.Y),
}

sColor := C.struct_Scalar{
val1: C.double(c.B),
val2: C.double(c.G),
val3: C.double(c.R),
val4: C.double(c.A),
}

C.FreeType2_PutText((C.FreeType2)(f.p), (C.Mat)(img.Ptr()), cText, sOrg, C.int(fontHeight), sColor, C.int(thickness), C.int(lineType), C.bool(bottomLeftOrigin))
}

// GetTextSize calculates the width and height of a text string.
// The function getTextSize calculates and returns the approximate size of a box that contains the specified text.
// That is, the following code renders some text, the tight box surrounding it, and the baseline.
//
// For further details, please see:
// https://docs.opencv.org/master/d9/dfa/classcv_1_1freetype_1_1FreeType2.html#af135a132505125bdea74b378dda3bb5d
//
func (f *FreeType2) GetTextSize(text string, fontHeight int, thickness int) (image.Point, int) {
cText := C.CString(text)
defer C.free(unsafe.Pointer(cText))
cBaseLine := C.int(0)

sz := C.FreeType2_GetTextSize((C.FreeType2)(f.p), cText, C.int(fontHeight), C.int(thickness), &cBaseLine)
return image.Point{
X: int(sz.width),
Y: int(sz.height),
}, int(cBaseLine)
}
33 changes: 33 additions & 0 deletions contrib/freetype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef _OPENCV3_FREETYPE2_H_
#define _OPENCV3_FREETYPE2_H_

#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#include <opencv2/freetype.hpp>
extern "C" {
#endif

#include "../core.h"

#ifdef __cplusplus
typedef cv::Ptr<cv::freetype::FreeType2>* FreeType2;
#else
typedef void* FreeType2;
#endif

FreeType2 FreeType2_CreateFreeType2();
void FreeType2_Close(FreeType2 f);
void FreeType2_LoadFontData(FreeType2 f, const char* fontFileName, int id);
void FreeType2_SetSplitNumber(FreeType2 f, int num);
void FreeType2_PutText(FreeType2 f, Mat img, const char* text, Point org,
int fontHeight, Scalar color,
int thickness, int line_type, bool bottomLeftOrigin
);
Size FreeType2_GetTextSize(FreeType2 f, const char* text,
int fontHeight, int thickness, int* baseLine);

#ifdef __cplusplus
}
#endif

#endif //_OPENCV3_FREETYPE2_H_
65 changes: 65 additions & 0 deletions contrib/freetype_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package contrib

import (
"image"
"image/color"
"testing"

"gocv.io/x/gocv"
)

func TestFreeTypeLoadFontData(t *testing.T) {
ft := NewFreeType2()
defer ft.Close()

ft.LoadFontData("../fonts/JetBrainsMono-Regular.ttf", 0)
}

func TestFreeTypeGetTextSize(t *testing.T) {
ft := NewFreeType2()
defer ft.Close()

ft.LoadFontData("../fonts/JetBrainsMono-Regular.ttf", 0)

size, baseLine := ft.GetTextSize("test", 60, 2)

if size.X != 140 {
t.Error("Invalid text size width")
}

if size.Y != 46 {
t.Error("Invalid text size height")
}

if baseLine != 1 {
t.Errorf("invalid base. expected %d, actual %d", 1, baseLine)
}
}

func TestFreeTypePutText(t *testing.T) {
ft := NewFreeType2()
defer ft.Close()

ft.LoadFontData("../fonts/JetBrainsMono-Regular.ttf", 0)

img := gocv.NewMatWithSize(150, 500, gocv.MatTypeCV8UC3)
if img.Empty() {
t.Error("Invalid Mat")
}
defer img.Close()

pt := image.Pt(80, 80)
ft.PutText(&img, "Testing", pt, 60, color.RGBA{R: 255, G: 255, B: 255}, 2, 8, true)

if img.Empty() {
t.Error("Error in PutText test")
}
}

func TestFreeTypeSetSplitNumber(t *testing.T) {
ft := NewFreeType2()
defer ft.Close()

ft.LoadFontData("../fonts/JetBrainsMono-Regular.ttf", 0)
ft.SetSplitNumber(10)
}
Binary file added fonts/JetBrainsMono-Regular.ttf
Binary file not shown.

0 comments on commit a0dade1

Please sign in to comment.