Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add freetype #873

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.