Herramientas para crear texto como mapas de bits (texto suavizado, espaciado personalizado, fondo transparente)

StackOverflow https://stackoverflow.com/questions/465144

Pregunta

Necesito crear lotes de imágenes con texto. Requisitos:

  1. tamaño arbitrario de mapa de bits
  2. formato PNG
  3. fondo transparente
  4. texto negro suavizado contra la transparencia
  5. espaciado entre caracteres ajustable
  6. posición de texto ajustable (coordenadas x e y donde comienza el texto)
  7. Soporte TrueType y / o Type1
  8. Herramienta de línea de comandos de Unix o biblioteca de Python

Hasta ahora he evaluado lo siguiente:

El problema con PIL es que, p. el espaciado predeterminado para Verdana es demasiado escaso. Necesito que el texto sea un poco más ajustado, pero no hay forma de ajustarlo en PIL.

En ImageMagick no he encontrado una manera fácil de especificar en qué parte de la imagen comienza el texto (estoy usando -size WIDTHxHEIGHT y leyenda: 'TEXT'). Agregar un borde transparente alejará el texto de la esquina a la que está anclado, pero

  • el tamaño de la imagen debe ajustarse en consecuencia, ya que el borde aumenta la extensión
  • no es posible ajustar el desplazamiento horizontal y vertical de forma independiente

¿Me he perdido algunas alternativas obvias o no he podido encontrar las características necesarias de las mencionadas anteriormente?

¿Fue útil?

Solución 2

Aquí está la solución SVG + ImageMagick:

Cree mediante programación documentos SVG basados ??en esta plantilla, reemplazando "TEXTO AQUÍ" con el contenido de texto deseado:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC
      "-//W3C//DTD SVG 1.0//EN"
      "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" width="152px" height="50px">
  <text style="font-size: 22px; font-weight:bold; font-family: Verdana-Bold;
               letter-spacing: -1.3%;">
    <tspan x="10" y="39">TEXT HERE</tspan>
  </text>
</svg>

Convierta los documentos a PNG transparentes de fondo con convert :

de ImageMagick
$ convert -background none input.svg output.png

Otros consejos

(5) de hecho parece complicado, menos que inserte espacios estrechos ficticios en la cadena (lo que romperá el kerning) o usar algo de nivel mucho más alto como el renderizador SVG o HTML / CSS.

Sin embargo, si no te importa ensuciarte las manos, parece bastante fácil hackear el renderizador de tipo libre de PIL para agregar espacio horizontal. Ver _imagingft.c ; después del siguiente código en font_getsize y font_render:

if (kerning && last_index && index) {
    FT_Vector delta;
    FT_Get_Kerning(self->face, last_index, index, ft_kerning_default,
                   &delta);
    x += delta.x >> 6;
}

Añadir:

if (last_index && index) {
    x += tracking;
}

Pruébelo con un entero simple para el seguimiento (probablemente a juzgar bastante grande por ese '> > 6') primero; compilar y ver si funciona. El siguiente paso sería obtener el valor de seguimiento en la función C de Python, para lo cual tendría que cambiar la llamada ParseTuple en font_render a:

long tracking;
if (!PyArg_ParseTuple(args, "Ol|il:render", &string, &id, &mask, &tracking))
    return NULL;

Y en font_getsize:

long tracking;
if (!PyArg_ParseTuple(args, "O|l:getsize", &string, &tracking))
    return NULL;

Luego mira qué interfaz de Python quieres. Este es un caso trivial pero bastante tedioso de agregar el argumento de 'seguimiento' adicional a través de cada nivel de la interfaz, por ejemplo:

def truetype(filename, size, index=0, encoding="", tracking= 0): # added optional tracking
    "Load a truetype font file."
    try:
        return FreeTypeFont(filename, size, index, encoding, tracking) # added tracking
    ...

class FreeTypeFont:
    "FreeType font wrapper (requires _imagingft service)"

    def __init__(self, file, size, index=0, encoding="", tracking= 0): # added tracking
        import _imagingft
        self.font = _imagingft.getfont(file, size, index, encoding)
        self.tracking= tracking # add this line

    ...

    def getmask2(self, text, mode="", fill=Image.core.fill):
        size, offset = self.font.getsize(text, self.tracking) # use tracking
        im = fill("L", size, 0)
        self.font.render(text, im.id, mode=="1", self.tracking) # use tracking
        return im, offset

¡No he probado nada de esto! Si funciona, podría valer la pena enviarlo como un parche.

De un vistazo rápido, Pango tiene soporte para espaciado entre letras . Pango tiene enlaces de Python y está integrado con Cairo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top