pyvips seems to do this correctly. I tried this:
$ python3
Python 3.7 .3(
default, Apr 3 2019, 05: 39: 12)[GCC 8.3 .0] on linux
Type "help", "copyright", "credits"
or "license"
for more information. >>>
import pyvips >>>
x = pyvips.Image.text("Puzzling", dpi = 300, font = "Miss Fajardose", fontfile = "/home/john/pics/MissFajardose-Regular.ttf") >>>
x.write_to_file("x.png")
Here's some code I created that works for me and is PIL-based. I found using getsize_multiline worked pretty well (and also drew the text using the ImageDraw.Draw multiline_text function).
from PIL
import Image, ImageFont, ImageDraw, ImageColor
def text_to_image(
text: str,
font_filepath: str,
font_size: int,
color: (int, int, int), #color is in RGB font_align = "center"):
font = ImageFont.truetype(font_filepath, size = font_size)
box = font.getsize_multiline(text)
img = Image.new("RGBA", (box[0], box[1]))
draw = ImageDraw.Draw(img)
draw_point = (0, 0)
draw.multiline_text(draw_point, text, font = font, fill = color, align = font_align)
return img
September 17, 2018 at 9:56 pm,September 17, 2018 at 7:47 pm,September 17, 2018 at 7:34 pm,September 17, 2018 at 7:22 pm
To check your Ubuntu version you can use the lsb_release
command:
$ lsb_release - a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04 .1 LTS Release: 18.04 Codename: bionic
For Ubuntu 18.04 users, Tesseract 4 is part of the main apt-get repository, making it super easy to install Tesseract via the following command:
$ sudo apt install tesseract - ocr
Just add the alex-p/tesseract-ocr
PPA repository to your system, update your package definitions, and then install Tesseract:
$ sudo add - apt - repository ppa: alex - p / tesseract - ocr $ sudo apt - get update $ sudo apt install tesseract - ocr
If you already have Tesseract installed on your Mac (if you followed my previous Tesseract install tutorial, for example), you’ll first want to unlink the original install:
$ brew unlink tesseract
Once you have Tesseract installed on your machine you should execute the following command to verify your Tesseract version:
$ tesseract - v tesseract 4.0 .0 - beta .3 leptonica - 1.76 .0 libjpeg 9 c: libpng 1.6 .34: libtiff 4.0 .9: zlib 1.2 .11 Found AVX512BW Found AVX512F Found AVX2 Found AVX Found SSE
The textwrap module provides some convenience functions, as well as TextWrapper, the class that does all the work. If you’re just wrapping or filling one or two text strings, the convenience functions should be good enough; otherwise, you should use an instance of TextWrapper for efficiency.,TextWrapper also provides some public methods, analogous to the module-level convenience functions:,wrap(), fill() and shorten() work by creating a TextWrapper instance and calling a single method on it. That instance is not reused, so for applications that process many text strings using wrap() and/or fill(), it may be more efficient to create your own TextWrapper object.,Since the sentence detection algorithm relies on string.lowercase for the definition of “lowercase letter”, and a convention of using two spaces after a period to separate sentences on the same line, it is specific to English-language texts.
"\n".join(wrap(text, ...))
>>> textwrap.shorten("Hello world!", width = 12)
'Hello world!' >>>
textwrap.shorten("Hello world!", width = 11)
'Hello [...]' >>>
textwrap.shorten("Hello world", width = 10, placeholder = "...")
'Hello...'
def test(): # end first line with\ to avoid the empty line! s = '' '\ hello world '' ' print(repr(s)) # prints ' hello\n world\n ' print(repr(dedent(s))) # prints 'hello\n world\n'
>>> s = 'hello\n\n \nworld' >>>
indent(s, ' ')
' hello\n\n \n world'
>>> print(indent(s, '+ ', lambda line: True)) +
hello +
+
+world
wrapper = TextWrapper(initial_indent = "* ")
Last modified: Apr 5, 2022, by MDN contributors
/* Keyword values */
text - rendering: auto;
text - rendering: optimizeSpeed;
text - rendering: optimizeLegibility;
text - rendering: geometricPrecision;
/* Global values */
text - rendering: inherit;
text - rendering: initial;
text - rendering: revert;
text - rendering: revert - layer;
text - rendering: unset;
text - rendering = auto | optimizeSpeed | optimizeLegibility | geometricPrecision
<p class="small">LYoWAT - ff fi fl ffl</p>
<p class="big">LYoWAT - ff fi fl ffl</p>
.small {
font: 19.9 px "Constantia",
"Times New Roman",
"Georgia",
"Palatino",
serif;
}
.big {
font: 20 px "Constantia",
"Times New Roman",
"Georgia",
"Palatino",
serif;
}
<p class="speed">LYoWAT - ff fi fl ffl</p>
<p class="legibility">LYoWAT - ff fi fl ffl</p>
p {
font: 1.5 em "Constantia",
"Times New Roman",
"Georgia",
"Palatino",
serif
}
.speed {
text - rendering: optimizeSpeed;
}
.legibility {
text - rendering: optimizeLegibility;
}
A FreeType face hosts a collection of glyphs. We can set one of those glyphs as the active glyph by calling FT_Load_Char. Here we choose to load the character glyph 'X': , We combine both the position and texture coordinate data into one vec4. The vertex shader multiplies the coordinates with a projection matrix and forwards the texture coordinates to the fragment shader: , FreeType loads these TrueType fonts and, for each glyph, generates a bitmap image and calculates several metrics. We can extract these bitmap images for generating textures and position each character glyph appropriately using the loaded metrics. , Each of these FreeType functions returns a non-zero integer whenever an error occurred.
Then include the appropriate headers:
#include <ft2build.h>
#include FT_FREETYPE_H
To load a font, all we have to do is initialize the FreeType library and load the font as a arial.ttf
TrueType font file that was copied from the Windows/Fonts
directory:
FT_Library ft;
if (FT_Init_FreeType( & ft)) {
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
return -1;
}
FT_Face face;
if (FT_New_Face(ft, "fonts/arial.ttf", 0, & face)) {
std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
return -1;
}
Once we've loaded the face, we should define the pixel font size we'd like to extract from this face:
FT_Set_Pixel_Sizes(face, 0, 48);
We could load a character glyph, retrieve its metrics, and generate a texture each time we want to render a character to the screen, but it would be inefficient to do this each frame. We'd rather store the generated data somewhere in the application and query it whenever we want to render a character. We'll define a convenient struct
that we'll store in a
struct Character {
unsigned int TextureID; // ID handle of the glyph texture
glm::ivec2 Size; // Size of glyph
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
unsigned int Advance; // Offset to advance to next glyph
};
std::map<char, Character> Characters;
For this chapter we'll keep things simple by restricting ourselves to the first 128 characters of the ASCII character set. For each character, we generate a texture and store its relevant data into a
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
for (unsigned char c = 0; c < 128; c++)
{
// load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
continue;
}
// generate texture
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
// set texture options
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// now store character for later use
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x
};
Characters.insert(std::pair<char, Character>(c, character));
}