diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed2c28d5..aa2330fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,6 +66,7 @@ jobs: patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-fix-windows-arm-arch.patch patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-minimal-install.patch cp ../patches/draw_text.h ../patches/mono_font_data.h modules/core/src/ + cp ../patches/fontface.html ./ patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-drawing-mono-font.patch rm -rf modules/highgui cp -r ../highgui modules/ @@ -140,6 +141,7 @@ jobs: patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-fix-windows-arm-arch.patch patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-minimal-install.patch cp ../patches/draw_text.h ../patches/mono_font_data.h modules/imgproc/src/ + cp ../patches/fontface.html ./ patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-drawing-mono-font.patch rm -rf modules/highgui cp -r ../highgui modules/ @@ -211,6 +213,7 @@ jobs: patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-fix-windows-arm-arch.patch patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-minimal-install.patch cp ../patches/draw_text.h ../patches/mono_font_data.h modules/imgproc/src/ + cp ../patches/fontface.html ./ patch -p1 -i ../patches/opencv-${{ env.opencv-version }}-drawing-mono-font.patch rm -rf modules/highgui cp -r ../highgui modules/ @@ -249,6 +252,7 @@ jobs: opencv-version: [2.4.13.7, 3.4.20, 4.10.0] env: COMMON_CMAKE_OPTIONS: | + -DCMAKE_POLICY_DEFAULT_CMP0057=NEW \ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_LATEST_HOME/build/cmake/android.toolchain.cmake \ -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=False \ -DANDROID_PLATFORM=android-21 \ diff --git a/patches/draw_text.h b/patches/draw_text.h index aab1f810..a37da00f 100644 --- a/patches/draw_text.h +++ b/patches/draw_text.h @@ -33,17 +33,79 @@ namespace cv { -static void get_text_drawing_size(const char* text, int fontpixelsize, int* w, int* h) +static int utf8_to_unicode(const char* utf8, std::vector& unicode) +{ + const int n = strlen(utf8); + + int i = 0; + while (i < n) + { + unsigned char ch = utf8[i++]; + + unsigned int uni = 0; + int todo = 0; + if (ch <= 0x7F) + { + uni = ch; + } + else if (ch <= 0xBF) + { + return -1; + } + else if (ch <= 0xDF) + { + uni = ch & 0x1F; + todo = 1; + } + else if (ch <= 0xEF) + { + uni = ch & 0x0F; + todo = 2; + } + else if (ch <= 0xF7) + { + uni = ch & 0x07; + todo = 3; + } + + for (int j = 0; j < todo; j++) + { + if (i == n) + return -1; + + unsigned char ch2 = utf8[i++]; + + if (ch2 < 0x80 || ch2 > 0xBF) + return -1; + + uni <<= 6; + uni += ch2 & 0x3F; + } + if (uni >= 0xD800 && uni <= 0xDFFF) + return -1; + if (uni > 0x10FFFF) + return -1; + + unicode.push_back(uni); + } + + return 0; +} + +static void get_text_drawing_size(const char* text, int fontpixelsize, int* w, int* h, const FontFace& ff = FontFace()) { *w = 0; *h = 0; - const int n = strlen(text); + std::vector unicode; + utf8_to_unicode(text, unicode); + + const int n = (int)unicode.size(); int line_w = 0; for (int i = 0; i < n; i++) { - char ch = text[i]; + unsigned int ch = unicode[i]; if (ch == '\n') { @@ -53,24 +115,28 @@ static void get_text_drawing_size(const char* text, int fontpixelsize, int* w, i line_w = 0; } - if (isprint(ch) != 0) + if (ch < 128 && isprint(ch) != 0) { line_w += fontpixelsize; } + else if (ff.d->get_glyph_bitmap(ch)) + { + line_w += fontpixelsize * 2; + } } *w = std::max(*w, line_w); *h += fontpixelsize * 2; } -static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char* resized_font_bitmap, int fontpixelsize) +static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char* resized_font_bitmap, int fontpixelsize, int fullwidth = 0) { const int INTER_RESIZE_COEF_BITS = 11; const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS; - const int srcw = 20; + const int srcw = fullwidth ? 40 : 20; const int srch = 40; - const int w = fontpixelsize; + const int w = fullwidth ? fontpixelsize * 2 : fontpixelsize; const int h = fontpixelsize * 2; double scale = (double)srcw / w; @@ -152,7 +218,7 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char short* rows0_old = rows0; rows0 = rows1; rows1 = rows0_old; - const unsigned char* S1 = font_bitmap + 10 * (sy + 1); + const unsigned char* S1 = font_bitmap + (fullwidth ? 20 : 10) * (sy + 1); if (sy >= srch - 1) { @@ -182,7 +248,7 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char } else if (sx >= srcw - 1) { - S1p0 = (S1[9] & 0xf0) >> 4; + S1p0 = (S1[fullwidth ? 19 : 9] & 0xf0) >> 4; S1p1 = 0; } else @@ -199,8 +265,8 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char else { // hresize two rows - const unsigned char* S0 = font_bitmap + 10 * (sy); - const unsigned char* S1 = font_bitmap + 10 * (sy + 1); + const unsigned char* S0 = font_bitmap + (fullwidth ? 20 : 10) * (sy); + const unsigned char* S1 = font_bitmap + (fullwidth ? 20 : 10) * (sy + 1); if (sy >= srch - 1) { @@ -223,7 +289,7 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char } else if (sx >= srcw - 1) { - S0p0 = (S0[9] & 0xf0) >> 4; + S0p0 = (S0[fullwidth ? 19 : 9] & 0xf0) >> 4; S0p1 = 0; } else @@ -262,9 +328,9 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char } else if (sx >= srcw - 1) { - S0p0 = (S0[9] & 0xf0) >> 4; + S0p0 = (S0[fullwidth ? 19 : 9] & 0xf0) >> 4; S0p1 = 0; - S1p0 = (S1[9] & 0xf0) >> 4; + S1p0 = (S1[fullwidth ? 19 : 9] & 0xf0) >> 4; S1p1 = 0; } else @@ -485,19 +551,22 @@ static void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char delete[] buf; } -static void draw_text_c1(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c1(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff) { const unsigned char* pen_color = (const unsigned char*)&color; - unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2]; + unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 4]; - const int n = strlen(text); + std::vector unicode; + utf8_to_unicode(text, unicode); + + const int n = (int)unicode.size(); int cursor_x = x; int cursor_y = y; for (int i = 0; i < n; i++) { - char ch = text[i]; + unsigned int ch = unicode[i]; if (ch == '\n') { @@ -513,7 +582,7 @@ static void draw_text_c1(unsigned char* pixels, int w, int h, int stride, const continue; } - if (isprint(ch) != 0) + if (ch < 128 && isprint(ch) != 0) { const unsigned char* font_bitmap = mono_font_data[ch - '!']; @@ -541,24 +610,57 @@ static void draw_text_c1(unsigned char* pixels, int w, int h, int stride, const cursor_x += fontpixelsize; } + else + { + const unsigned char* font_bitmap = ff.d->get_glyph_bitmap(ch); + if (font_bitmap) + { + // draw resized character + resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize, 1); + + const int ystart = std::max(cursor_y, 0); + const int yend = std::min(cursor_y + fontpixelsize * 2, h); + const int xstart = std::max(cursor_x, 0); + const int xend = std::min(cursor_x + fontpixelsize * 2, w); + + for (int j = ystart; j < yend; j++) + { + const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize * 2 + xstart - cursor_x; + unsigned char* p = pixels + stride * j + xstart; + + for (int k = xstart; k < xend; k++) + { + unsigned char alpha = *palpha++; + + p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255; + p += 1; + } + } + + cursor_x += fontpixelsize * 2; + } + } } delete[] resized_font_bitmap; } -static void draw_text_c3(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c3(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff) { const unsigned char* pen_color = (const unsigned char*)&color; - unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2]; + unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 4]; + + std::vector unicode; + utf8_to_unicode(text, unicode); - const int n = strlen(text); + const int n = (int)unicode.size(); int cursor_x = x; int cursor_y = y; for (int i = 0; i < n; i++) { - char ch = text[i]; + unsigned int ch = unicode[i]; if (ch == '\n') { @@ -574,7 +676,7 @@ static void draw_text_c3(unsigned char* pixels, int w, int h, int stride, const continue; } - if (isprint(ch) != 0) + if (ch < 128 && isprint(ch) != 0) { const unsigned char* font_bitmap = mono_font_data[ch - '!']; @@ -604,24 +706,59 @@ static void draw_text_c3(unsigned char* pixels, int w, int h, int stride, const cursor_x += fontpixelsize; } + else + { + const unsigned char* font_bitmap = ff.d->get_glyph_bitmap(ch); + if (font_bitmap) + { + // draw resized character + resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize, 1); + + const int ystart = std::max(cursor_y, 0); + const int yend = std::min(cursor_y + fontpixelsize * 2, h); + const int xstart = std::max(cursor_x, 0); + const int xend = std::min(cursor_x + fontpixelsize * 2, w); + + for (int j = ystart; j < yend; j++) + { + const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize * 2 + xstart - cursor_x; + unsigned char* p = pixels + stride * j + xstart * 3; + + for (int k = xstart; k < xend; k++) + { + unsigned char alpha = *palpha++; + + p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255; + p[1] = (p[1] * (255 - alpha) + pen_color[1] * alpha) / 255; + p[2] = (p[2] * (255 - alpha) + pen_color[2] * alpha) / 255; + p += 3; + } + } + + cursor_x += fontpixelsize * 2; + } + } } delete[] resized_font_bitmap; } -static void draw_text_c4(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c4(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff) { const unsigned char* pen_color = (const unsigned char*)&color; - unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2]; + unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 4]; - const int n = strlen(text); + std::vector unicode; + utf8_to_unicode(text, unicode); + + const int n = (int)unicode.size(); int cursor_x = x; int cursor_y = y; for (int i = 0; i < n; i++) { - char ch = text[i]; + unsigned int ch = unicode[i]; if (ch == '\n') { @@ -637,7 +774,7 @@ static void draw_text_c4(unsigned char* pixels, int w, int h, int stride, const continue; } - if (isprint(ch) != 0) + if (ch < 128 && isprint(ch) != 0) { const unsigned char* font_bitmap = mono_font_data[ch - '!']; @@ -668,24 +805,57 @@ static void draw_text_c4(unsigned char* pixels, int w, int h, int stride, const cursor_x += fontpixelsize; } + else + { + const unsigned char* font_bitmap = ff.d->get_glyph_bitmap(ch); + if (font_bitmap) + { + // draw resized character + resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize, 1); + + const int ystart = std::max(cursor_y, 0); + const int yend = std::min(cursor_y + fontpixelsize * 2, h); + const int xstart = std::max(cursor_x, 0); + const int xend = std::min(cursor_x + fontpixelsize * 2, w); + + for (int j = ystart; j < yend; j++) + { + const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize * 2 + xstart - cursor_x; + unsigned char* p = pixels + stride * j + xstart * 4; + + for (int k = xstart; k < xend; k++) + { + unsigned char alpha = *palpha++; + + p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255; + p[1] = (p[1] * (255 - alpha) + pen_color[1] * alpha) / 255; + p[2] = (p[2] * (255 - alpha) + pen_color[2] * alpha) / 255; + p[3] = (p[3] * (255 - alpha) + pen_color[3] * alpha) / 255; + p += 4; + } + } + + cursor_x += fontpixelsize * 2; + } + } } delete[] resized_font_bitmap; } -static void draw_text_c1(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c1(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff = FontFace()) { - return draw_text_c1(pixels, w, h, w, text, x, y, fontpixelsize, color); + return draw_text_c1(pixels, w, h, w, text, x, y, fontpixelsize, color, ff); } -static void draw_text_c3(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c3(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff = FontFace()) { - return draw_text_c3(pixels, w, h, w * 3, text, x, y, fontpixelsize, color); + return draw_text_c3(pixels, w, h, w * 3, text, x, y, fontpixelsize, color, ff); } -static void draw_text_c4(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color) +static void draw_text_c4(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color, const FontFace& ff = FontFace()) { - return draw_text_c4(pixels, w, h, w * 4, text, x, y, fontpixelsize, color); + return draw_text_c4(pixels, w, h, w * 4, text, x, y, fontpixelsize, color, ff); } } diff --git a/patches/fontface.html b/patches/fontface.html new file mode 100644 index 00000000..46cd0d35 --- /dev/null +++ b/patches/fontface.html @@ -0,0 +1,208 @@ + + + + +Text to Font Header + + + +
+ + + + + + + diff --git a/patches/opencv-2.4.13.7-drawing-mono-font.patch b/patches/opencv-2.4.13.7-drawing-mono-font.patch index a8c0fdff..da395304 100644 --- a/patches/opencv-2.4.13.7-drawing-mono-font.patch +++ b/patches/opencv-2.4.13.7-drawing-mono-font.patch @@ -1,16 +1,74 @@ -diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/modules/core/src/drawing.cpp ---- opencv-2.4.13.7.orig/modules/core/src/drawing.cpp 2018-07-02 20:41:56.000000000 +0800 -+++ opencv-2.4.13.7/modules/core/src/drawing.cpp 2023-12-09 15:52:28.808104579 +0800 -@@ -40,6 +40,8 @@ - //M*/ - #include "precomp.hpp" +diff -Nuarp opencv-2.4.13.7.orig/modules/core/include/opencv2/core/core.hpp opencv-2.4.13.7/modules/core/include/opencv2/core/core.hpp +--- opencv-2.4.13.7.orig/modules/core/include/opencv2/core/core.hpp 2024-08-03 13:33:29.646494334 +0800 ++++ opencv-2.4.13.7/modules/core/include/opencv2/core/core.hpp 2024-08-03 13:35:12.013094855 +0800 +@@ -2732,6 +2732,37 @@ CV_EXPORTS_W Size getTextSize(const stri + double fontScale, int thickness, + CV_OUT int* baseLine); -+#include "draw_text.h" ++class FontFaceImpl; ++class CV_EXPORTS_W FontFace ++{ ++public: ++ FontFace(); ++ FontFace(const String& fontPath); ++ ++ ~FontFace(); ++ ++protected: ++ void set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps); ++ ++public: ++ FontFaceImpl* const d; ++}; ++ ++enum PutTextFlags ++{ ++ PUT_TEXT_ALIGN_LEFT=0, // put the text to the right from the origin ++ PUT_TEXT_ALIGN_CENTER=1,// center the text at the origin; not implemented yet ++ PUT_TEXT_ALIGN_RIGHT=2, // put the text to the left of the origin ++ PUT_TEXT_ALIGN_MASK=3, // alignment mask ++ PUT_TEXT_ORIGIN_TL=0, ++ PUT_TEXT_ORIGIN_BL=32, // treat the target image as having bottom-left origin ++ PUT_TEXT_WRAP=128 // wrap text to the next line if it does not fit ++}; ++ ++CV_EXPORTS_W Point putText(InputOutputArray img, const String &text, Point org, Scalar color, const FontFace &fface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); ++ ++CV_EXPORTS_W Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); + + ///////////////////////////////// Mat_<_Tp> //////////////////////////////////// + + /*! +diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/modules/core/src/drawing.cpp +--- opencv-2.4.13.7.orig/modules/core/src/drawing.cpp 2024-08-03 13:33:29.648494328 +0800 ++++ opencv-2.4.13.7/modules/core/src/drawing.cpp 2024-08-03 14:19:07.916992598 +0800 +@@ -42,6 +42,25 @@ + namespace cv { ++class FontFaceImpl ++{ ++public: ++ FontFaceImpl(); ++ ++public: ++ int glyph_count; ++ const unsigned int* glyph_unicode; ++ const unsigned char* glyph_bitmaps; ++ ++public: ++ const unsigned char* get_glyph_bitmap(unsigned int ch) const; ++}; ++} ++ ++#include "draw_text.h" ++ ++namespace cv ++{ + + enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 }; -@@ -1992,6 +1994,7 @@ void polylines( Mat& img, const Point** +@@ -1992,6 +2011,7 @@ void polylines( Mat& img, const Point** } @@ -18,7 +76,7 @@ diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/mo enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8), FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8), FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8), -@@ -2204,12 +2207,41 @@ inline void readCheck(int &c, int &i, co +@@ -2204,12 +2224,41 @@ inline void readCheck(int &c, int &i, co if(c >= rightBoundary || c < leftBoundary) c = '?'; } @@ -60,7 +118,7 @@ diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/mo const int* ascii = getFontData(fontFace); double buf[4]; -@@ -2264,10 +2296,21 @@ void putText( Mat& img, const string& te +@@ -2264,10 +2313,21 @@ void putText( Mat& img, const string& te } view_x += dx; } @@ -82,15 +140,102 @@ diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/mo Size size; double view_x = 0; const char **faces = cv::g_HersheyGlyphs; -@@ -2294,6 +2337,7 @@ Size getTextSize( const string& text, in +@@ -2294,6 +2354,94 @@ Size getTextSize( const string& text, in if( _base_line ) *_base_line = cvRound(base_line*fontScale + thickness*0.5); return size; +#endif ++} ++ ++FontFaceImpl::FontFaceImpl() ++{ ++ glyph_count = 0; ++ glyph_unicode = 0; ++ glyph_bitmaps = 0; ++} ++ ++const unsigned char* FontFaceImpl::get_glyph_bitmap(unsigned int ch) const ++{ ++ if (!glyph_count || !glyph_unicode || !glyph_bitmaps) ++ return 0; ++ ++ for (int i = 0; i < glyph_count; i++) ++ { ++ if (glyph_unicode[i] == ch) ++ return glyph_bitmaps + i * 40 * 20; ++ } ++ ++ return 0; ++} ++ ++FontFace::FontFace() : d(new FontFaceImpl) ++{ ++} ++ ++FontFace::~FontFace() ++{ ++ delete d; ++} ++ ++void FontFace::set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps) ++{ ++ d->glyph_count = count; ++ d->glyph_unicode = unicode; ++ d->glyph_bitmaps = bitmaps; ++} ++ ++Point putText(InputOutputArray _img, const String& text, Point org, Scalar color, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ if ( text.empty() ) ++ { ++ return org; ++ } ++ Mat img = _img.getMat(); ++ ++ const int yoffset = org.y - size * 2; ++ ++ unsigned int _color = 0; ++ unsigned char* border_color = (unsigned char*)&_color; ++ ++ if (img.channels() == 1) ++ { ++ border_color[0] = color[0]; ++ draw_text_c1(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 3) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ draw_text_c3(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 4) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ border_color[3] = color[3]; ++ draw_text_c4(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Point(org.x + w, org.y); ++} ++ ++Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Rect(org.x, org.y - size * 2, w, h); } } -@@ -2679,7 +2723,7 @@ cvInitFont( CvFont *font, int font_face, +@@ -2679,7 +2827,7 @@ cvInitFont( CvFont *font, int font_face, { CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 ); @@ -100,8 +245,8 @@ diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/drawing.cpp opencv-2.4.13.7/mo font->hscale = (float)hscale; font->vscale = (float)vscale; diff -Nuarp opencv-2.4.13.7.orig/modules/core/src/tables.cpp opencv-2.4.13.7/modules/core/src/tables.cpp ---- opencv-2.4.13.7.orig/modules/core/src/tables.cpp 2018-07-02 20:41:56.000000000 +0800 -+++ opencv-2.4.13.7/modules/core/src/tables.cpp 2023-12-09 14:51:50.948704080 +0800 +--- opencv-2.4.13.7.orig/modules/core/src/tables.cpp 2024-08-03 13:33:29.648494328 +0800 ++++ opencv-2.4.13.7/modules/core/src/tables.cpp 2024-08-03 13:33:44.160445806 +0800 @@ -204,6 +204,7 @@ const uchar g_Saturate8u[] = 255 }; diff --git a/patches/opencv-3.4.20-drawing-mono-font.patch b/patches/opencv-3.4.20-drawing-mono-font.patch index d2718adb..008aef21 100644 --- a/patches/opencv-3.4.20-drawing-mono-font.patch +++ b/patches/opencv-3.4.20-drawing-mono-font.patch @@ -1,16 +1,74 @@ -diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/modules/imgproc/src/drawing.cpp ---- opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp 2023-06-27 19:29:13.000000000 +0800 -+++ opencv-3.4.20/modules/imgproc/src/drawing.cpp 2023-12-09 17:09:13.910181866 +0800 -@@ -40,6 +40,8 @@ - //M*/ - #include "precomp.hpp" +diff -Nuarp opencv-3.4.20.orig/modules/imgproc/include/opencv2/imgproc.hpp opencv-3.4.20/modules/imgproc/include/opencv2/imgproc.hpp +--- opencv-3.4.20.orig/modules/imgproc/include/opencv2/imgproc.hpp 2024-08-03 13:22:07.649774626 +0800 ++++ opencv-3.4.20/modules/imgproc/include/opencv2/imgproc.hpp 2024-08-03 13:23:14.297551785 +0800 +@@ -4912,6 +4912,37 @@ CV_EXPORTS_W double getFontScaleFromHeig + const int pixelHeight, + const int thickness = 1); -+#include "draw_text.h" ++class FontFaceImpl; ++class CV_EXPORTS_W FontFace ++{ ++public: ++ FontFace(); ++ FontFace(const String& fontPath); ++ ++ ~FontFace(); ++ ++protected: ++ void set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps); ++ ++public: ++ FontFaceImpl* const d; ++}; ++ ++enum PutTextFlags ++{ ++ PUT_TEXT_ALIGN_LEFT=0, // put the text to the right from the origin ++ PUT_TEXT_ALIGN_CENTER=1,// center the text at the origin; not implemented yet ++ PUT_TEXT_ALIGN_RIGHT=2, // put the text to the left of the origin ++ PUT_TEXT_ALIGN_MASK=3, // alignment mask ++ PUT_TEXT_ORIGIN_TL=0, ++ PUT_TEXT_ORIGIN_BL=32, // treat the target image as having bottom-left origin ++ PUT_TEXT_WRAP=128 // wrap text to the next line if it does not fit ++}; ++ ++CV_EXPORTS_W Point putText(InputOutputArray img, const String &text, Point org, Scalar color, const FontFace &fface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); ++ ++CV_EXPORTS_W Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); + + /** @brief Class for iterating over all pixels on a raster line segment. + + The class LineIterator is used to get each pixel of a raster line connecting +diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/modules/imgproc/src/drawing.cpp +--- opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp 2024-08-03 13:22:07.653774613 +0800 ++++ opencv-3.4.20/modules/imgproc/src/drawing.cpp 2024-08-03 13:30:01.392190643 +0800 +@@ -42,6 +42,25 @@ + namespace cv { ++class FontFaceImpl ++{ ++public: ++ FontFaceImpl(); ++ ++public: ++ int glyph_count; ++ const unsigned int* glyph_unicode; ++ const unsigned char* glyph_bitmaps; ++ ++public: ++ const unsigned char* get_glyph_bitmap(unsigned int ch) const; ++}; ++} ++ ++#include "draw_text.h" ++ ++namespace cv ++{ + + enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 }; -@@ -2051,6 +2053,7 @@ void polylines( Mat& img, const Point* c +@@ -2051,6 +2070,7 @@ void polylines( Mat& img, const Point* c } @@ -18,7 +76,7 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8), FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8), FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8), -@@ -2265,6 +2268,7 @@ inline void readCheck(int &c, int &i, co +@@ -2265,6 +2285,7 @@ inline void readCheck(int &c, int &i, co } extern const char* g_HersheyGlyphs[]; @@ -26,7 +84,7 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod void putText( InputOutputArray _img, const String& text, Point org, int fontFace, double fontScale, Scalar color, -@@ -2278,6 +2282,35 @@ void putText( InputOutputArray _img, con +@@ -2278,6 +2299,35 @@ void putText( InputOutputArray _img, con return; } Mat img = _img.getMat(); @@ -62,7 +120,7 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod const int* ascii = getFontData(fontFace); double buf[4]; -@@ -2332,10 +2365,21 @@ void putText( InputOutputArray _img, con +@@ -2332,10 +2382,21 @@ void putText( InputOutputArray _img, con } view_x += dx; } @@ -84,7 +142,7 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod Size size; double view_x = 0; const char **faces = cv::g_HersheyGlyphs; -@@ -2362,10 +2406,13 @@ Size getTextSize( const String& text, in +@@ -2362,10 +2423,13 @@ Size getTextSize( const String& text, in if( _base_line ) *_base_line = cvRound(base_line*fontScale + thickness*0.5); return size; @@ -98,15 +156,104 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod // By https://stackoverflow.com/a/27898487/1531708 const int* ascii = getFontData(fontFace); -@@ -2373,6 +2420,7 @@ double getFontScaleFromHeight(const int +@@ -2373,6 +2437,96 @@ double getFontScaleFromHeight(const int int cap_line = (ascii[0] >> 4) & 15; return static_cast(pixelHeight - static_cast((thickness + 1)) / 2.0) / static_cast(cap_line + base_line); +#endif ++} ++ ++FontFaceImpl::FontFaceImpl() ++{ ++ glyph_count = 0; ++ glyph_unicode = 0; ++ glyph_bitmaps = 0; ++} ++ ++const unsigned char* FontFaceImpl::get_glyph_bitmap(unsigned int ch) const ++{ ++ if (!glyph_count || !glyph_unicode || !glyph_bitmaps) ++ return 0; ++ ++ for (int i = 0; i < glyph_count; i++) ++ { ++ if (glyph_unicode[i] == ch) ++ return glyph_bitmaps + i * 40 * 20; ++ } ++ ++ return 0; ++} ++ ++FontFace::FontFace() : d(new FontFaceImpl) ++{ ++} ++ ++FontFace::~FontFace() ++{ ++ delete d; ++} ++ ++void FontFace::set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps) ++{ ++ d->glyph_count = count; ++ d->glyph_unicode = unicode; ++ d->glyph_bitmaps = bitmaps; ++} ++ ++Point putText(InputOutputArray _img, const String& text, Point org, Scalar color, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ CV_INSTRUMENT_REGION(); ++ ++ if ( text.empty() ) ++ { ++ return org; ++ } ++ Mat img = _img.getMat(); ++ ++ const int yoffset = org.y - size * 2; ++ ++ unsigned int _color = 0; ++ unsigned char* border_color = (unsigned char*)&_color; ++ ++ if (img.channels() == 1) ++ { ++ border_color[0] = color[0]; ++ draw_text_c1(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 3) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ draw_text_c3(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 4) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ border_color[3] = color[3]; ++ draw_text_c4(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Point(org.x + w, org.y); ++} ++ ++Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Rect(org.x, org.y - size * 2, w, h); } } -@@ -2879,7 +2927,7 @@ cvInitFont( CvFont *font, int font_face, +@@ -2879,7 +3033,7 @@ cvInitFont( CvFont *font, int font_face, { CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 ); @@ -116,8 +263,8 @@ diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/drawing.cpp opencv-3.4.20/mod font->hscale = (float)hscale; font->vscale = (float)vscale; diff -Nuarp opencv-3.4.20.orig/modules/imgproc/src/hershey_fonts.cpp opencv-3.4.20/modules/imgproc/src/hershey_fonts.cpp ---- opencv-3.4.20.orig/modules/imgproc/src/hershey_fonts.cpp 2023-06-27 19:29:13.000000000 +0800 -+++ opencv-3.4.20/modules/imgproc/src/hershey_fonts.cpp 2023-12-09 17:02:22.175067906 +0800 +--- opencv-3.4.20.orig/modules/imgproc/src/hershey_fonts.cpp 2024-08-03 13:22:07.654774610 +0800 ++++ opencv-3.4.20/modules/imgproc/src/hershey_fonts.cpp 2024-08-03 13:22:25.006716593 +0800 @@ -51,6 +51,7 @@ namespace cv { diff --git a/patches/opencv-4.10.0-drawing-mono-font.patch b/patches/opencv-4.10.0-drawing-mono-font.patch index 11779752..fd689308 100644 --- a/patches/opencv-4.10.0-drawing-mono-font.patch +++ b/patches/opencv-4.10.0-drawing-mono-font.patch @@ -1,16 +1,74 @@ -diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/modules/imgproc/src/drawing.cpp ---- opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp 2024-06-02 04:41:06.000000000 +0800 -+++ opencv-4.10.0/modules/imgproc/src/drawing.cpp 2024-06-04 21:05:11.279908634 +0800 -@@ -41,6 +41,8 @@ - #include "precomp.hpp" - using namespace cv; +diff -Nuarp opencv-4.10.0.orig/modules/imgproc/include/opencv2/imgproc.hpp opencv-4.10.0/modules/imgproc/include/opencv2/imgproc.hpp +--- opencv-4.10.0.orig/modules/imgproc/include/opencv2/imgproc.hpp 2024-08-03 13:16:17.646944880 +0800 ++++ opencv-4.10.0/modules/imgproc/include/opencv2/imgproc.hpp 2024-08-01 23:08:51.014584430 +0800 +@@ -4898,6 +4898,37 @@ CV_EXPORTS_W double getFontScaleFromHeig + const int pixelHeight, + const int thickness = 1); -+#include "draw_text.h" ++class FontFaceImpl; ++class CV_EXPORTS_W FontFace ++{ ++public: ++ FontFace(); ++ FontFace(const String& fontPath); ++ ++ ~FontFace(); ++ ++protected: ++ void set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps); ++ ++public: ++ FontFaceImpl* const d; ++}; ++ ++enum PutTextFlags ++{ ++ PUT_TEXT_ALIGN_LEFT=0, // put the text to the right from the origin ++ PUT_TEXT_ALIGN_CENTER=1,// center the text at the origin; not implemented yet ++ PUT_TEXT_ALIGN_RIGHT=2, // put the text to the left of the origin ++ PUT_TEXT_ALIGN_MASK=3, // alignment mask ++ PUT_TEXT_ORIGIN_TL=0, ++ PUT_TEXT_ORIGIN_BL=32, // treat the target image as having bottom-left origin ++ PUT_TEXT_WRAP=128 // wrap text to the next line if it does not fit ++}; ++ ++CV_EXPORTS_W Point putText(InputOutputArray img, const String &text, Point org, Scalar color, const FontFace &fface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); ++ ++CV_EXPORTS_W Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight=0, PutTextFlags flags=PUT_TEXT_ALIGN_LEFT, Range wrap=Range()); + + /** @brief Class for iterating over all pixels on a raster line segment. + + The class LineIterator is used to get each pixel of a raster line connecting +diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/modules/imgproc/src/drawing.cpp +--- opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp 2024-08-03 13:16:17.650944867 +0800 ++++ opencv-4.10.0/modules/imgproc/src/drawing.cpp 2024-08-01 23:09:27.473433279 +0800 +@@ -43,6 +43,25 @@ using namespace cv; + namespace cv { ++class FontFaceImpl ++{ ++public: ++ FontFaceImpl(); ++ ++public: ++ int glyph_count; ++ const unsigned int* glyph_unicode; ++ const unsigned char* glyph_bitmaps; ++ ++public: ++ const unsigned char* get_glyph_bitmap(unsigned int ch) const; ++}; ++} ++ ++#include "draw_text.h" ++ ++namespace cv ++{ + + enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 }; -@@ -2076,6 +2078,7 @@ void polylines( InputOutputArray _img, c +@@ -2076,6 +2095,7 @@ void polylines( InputOutputArray _img, c } @@ -18,7 +76,7 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8), FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8), FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8), -@@ -2290,6 +2293,7 @@ inline void readCheck(int &c, int &i, co +@@ -2290,6 +2310,7 @@ inline void readCheck(int &c, int &i, co } extern const char* g_HersheyGlyphs[]; @@ -26,7 +84,7 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod void putText( InputOutputArray _img, const String& text, Point org, int fontFace, double fontScale, Scalar color, -@@ -2303,6 +2307,35 @@ void putText( InputOutputArray _img, con +@@ -2303,6 +2324,35 @@ void putText( InputOutputArray _img, con return; } Mat img = _img.getMat(); @@ -62,7 +120,7 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod const int* ascii = getFontData(fontFace); double buf[4]; -@@ -2357,10 +2390,21 @@ void putText( InputOutputArray _img, con +@@ -2357,10 +2407,21 @@ void putText( InputOutputArray _img, con } view_x += dx; } @@ -84,7 +142,7 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod Size size; double view_x = 0; const char **faces = cv::g_HersheyGlyphs; -@@ -2387,10 +2431,13 @@ Size getTextSize( const String& text, in +@@ -2387,10 +2448,13 @@ Size getTextSize( const String& text, in if( _base_line ) *_base_line = cvRound(base_line*fontScale + thickness*0.5); return size; @@ -98,15 +156,104 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod // By https://stackoverflow.com/a/27898487/1531708 const int* ascii = getFontData(fontFace); -@@ -2398,6 +2445,7 @@ double getFontScaleFromHeight(const int +@@ -2398,6 +2462,96 @@ double getFontScaleFromHeight(const int int cap_line = (ascii[0] >> 4) & 15; return static_cast(pixelHeight - static_cast((thickness + 1)) / 2.0) / static_cast(cap_line + base_line); +#endif ++} ++ ++FontFaceImpl::FontFaceImpl() ++{ ++ glyph_count = 0; ++ glyph_unicode = 0; ++ glyph_bitmaps = 0; ++} ++ ++const unsigned char* FontFaceImpl::get_glyph_bitmap(unsigned int ch) const ++{ ++ if (!glyph_count || !glyph_unicode || !glyph_bitmaps) ++ return 0; ++ ++ for (int i = 0; i < glyph_count; i++) ++ { ++ if (glyph_unicode[i] == ch) ++ return glyph_bitmaps + i * 40 * 20; ++ } ++ ++ return 0; ++} ++ ++FontFace::FontFace() : d(new FontFaceImpl) ++{ ++} ++ ++FontFace::~FontFace() ++{ ++ delete d; ++} ++ ++void FontFace::set_glyph(int count, const unsigned int* unicode, const unsigned char* bitmaps) ++{ ++ d->glyph_count = count; ++ d->glyph_unicode = unicode; ++ d->glyph_bitmaps = bitmaps; ++} ++ ++Point putText(InputOutputArray _img, const String& text, Point org, Scalar color, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ CV_INSTRUMENT_REGION(); ++ ++ if ( text.empty() ) ++ { ++ return org; ++ } ++ Mat img = _img.getMat(); ++ ++ const int yoffset = org.y - size * 2; ++ ++ unsigned int _color = 0; ++ unsigned char* border_color = (unsigned char*)&_color; ++ ++ if (img.channels() == 1) ++ { ++ border_color[0] = color[0]; ++ draw_text_c1(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 3) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ draw_text_c3(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ else if (img.channels() == 4) ++ { ++ border_color[0] = color[0]; ++ border_color[1] = color[1]; ++ border_color[2] = color[2]; ++ border_color[3] = color[3]; ++ draw_text_c4(img.data, img.cols, img.rows, text.c_str(), org.x, yoffset, size, _color, fontface); ++ } ++ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Point(org.x + w, org.y); ++} ++ ++Rect getTextSize(Size imgsize, const String& text, Point org, const FontFace& fontface, int size, int weight, PutTextFlags flags, Range wrap) ++{ ++ int w; ++ int h; ++ get_text_drawing_size(text.c_str(), size, &w, &h, fontface); ++ ++ return Rect(org.x, org.y - size * 2, w, h); } } -@@ -2883,7 +2931,7 @@ cvInitFont( CvFont *font, int font_face, +@@ -2883,7 +3037,7 @@ cvInitFont( CvFont *font, int font_face, { CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 ); @@ -116,8 +263,8 @@ diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/drawing.cpp opencv-4.10.0/mod font->hscale = (float)hscale; font->vscale = (float)vscale; diff -Nuarp opencv-4.10.0.orig/modules/imgproc/src/hershey_fonts.cpp opencv-4.10.0/modules/imgproc/src/hershey_fonts.cpp ---- opencv-4.10.0.orig/modules/imgproc/src/hershey_fonts.cpp 2024-06-02 04:41:06.000000000 +0800 -+++ opencv-4.10.0/modules/imgproc/src/hershey_fonts.cpp 2024-06-04 21:05:11.280908629 +0800 +--- opencv-4.10.0.orig/modules/imgproc/src/hershey_fonts.cpp 2024-08-03 13:16:17.651944863 +0800 ++++ opencv-4.10.0/modules/imgproc/src/hershey_fonts.cpp 2024-08-03 13:16:57.200812630 +0800 @@ -51,6 +51,7 @@ namespace cv {