diff --git a/contrib/freetype.cpp b/contrib/freetype.cpp new file mode 100644 index 00000000..aad43b4e --- /dev/null +++ b/contrib/freetype.cpp @@ -0,0 +1,31 @@ +#include "freetype.h" + +FreeType2 FreeType2_CreateFreeType2() { + return new cv::Ptr(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}; +} \ No newline at end of file diff --git a/contrib/freetype.go b/contrib/freetype.go new file mode 100644 index 00000000..ca2ee7df --- /dev/null +++ b/contrib/freetype.go @@ -0,0 +1,103 @@ +package contrib + +/* +#include +#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) +} diff --git a/contrib/freetype.h b/contrib/freetype.h new file mode 100644 index 00000000..8d2fd60b --- /dev/null +++ b/contrib/freetype.h @@ -0,0 +1,33 @@ +#ifndef _OPENCV3_FREETYPE2_H_ +#define _OPENCV3_FREETYPE2_H_ + +#ifdef __cplusplus +#include +#include +extern "C" { +#endif + +#include "../core.h" + +#ifdef __cplusplus +typedef cv::Ptr* 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_ diff --git a/contrib/freetype_test.go b/contrib/freetype_test.go new file mode 100644 index 00000000..cc072c00 --- /dev/null +++ b/contrib/freetype_test.go @@ -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) +} diff --git a/fonts/JetBrainsMono-Regular.ttf b/fonts/JetBrainsMono-Regular.ttf new file mode 100644 index 00000000..7db854fd Binary files /dev/null and b/fonts/JetBrainsMono-Regular.ttf differ