Crénage à la volée

10

Quelqu'un connaît-il un algorithme qui calculerait automatiquement le crénage des caractères en fonction des formes de glyphe lorsque l'utilisateur tape du texte?

Je ne veux pas dire un calcul trivial des largeurs d'avance ou similaire, je veux dire analyser la forme des glyphes pour estimer la distance visuellement optimale entre les caractères. Par exemple, si nous plaçons trois caractères séquentiellement sur une ligne, le caractère du milieu devrait SEMBLER être au centre de la ligne malgré les formes du caractère. Un exemple éclaire la fonctionnalité de crénage à la volée:

Un exemple de crénage à la volée:

Capture d'écran

Dans l'image ci-dessus asemble être trop à droite. Il doit être déplacé d'un certain montant vers Tpour qu'il semble être au milieu de Tet g. L'algorithme doit examiner les formes de Tet a(et éventuellement d'autres lettres également) et décider de la quantité aà déplacer vers la gauche. Cette certaine quantité est la chose que l'algorithme doit calculer - SANS EXAMINER LES PAIRES DE KERNING POSSIBLES DE LA POLICE.

Je pense à coder un programme javascript (+ svg + html) qui utilise des polices dessinées à la main et beaucoup d'entre elles n'ont pas de paires de crénage. Les champs de texte seront modifiables et peuvent inclure du texte de plusieurs polices. Je pense que le crénage à la volée pourrait être un moyen d'assurer un flux de texte moyen dans ce cas.

EDIT: Un point de départ pourrait être d'utiliser la police svg, il est donc facile d'obtenir des valeurs de chemin. En police svg, le chemin est défini de cette façon:

<glyph glyph-name="T" unicode="T" horiz-adv-x="1251" d="M531 0v1293h
-483v173h1162v-173h-485v-1293h-194z"/>

<glyph glyph-name="a" unicode="a" horiz-adv-x="1139" d="M828 131q-100 -85
-192.5 -120t-198.5 -35q-175 0 -269 85.5t-94 218.5q0 78 35.5 142.5t93
103.5t129.5 59q53 14 160 27q218 26 321 62q1 37 1 47q0 110 -51 155q-69 61
-205 61q-127 0 -187.5 -44.5t-89.5 -157.5l-176 24q24 113 79 182.5t159
107t241 37.5 q136 0 221 -32t125 -80.5t56 -122.5q9 -46 9 -166v-240q0
-251 11.5 -317.5t45.5 -127.5h-188q-28 56 -36 131zM813 533q-98 -40 -294
-68q-111 -16 -157 -36t-71 -58.5t-25 -85.5q0 -72 54.5 -120t159.5 -48q104
0 185 45.5t119 124.5q29 61 29 180v66z"/>

L'algorithme (ou code javascript) devrait examiner ces chemins d'une certaine manière et déterminer la distance optimale entre eux.

Timo Kähkönen
la source
1
Si vous cherchez une solution de codage, il serait préférable de la poser sur SO. C'est ça que vous cherchez? Si c'est le cas, je vais migrer la question là-bas.
Alan Gilbertson
2
Je suis d'accord que c'est donc une question. J'ai posé la même question dans SO, mais elle a été fermée comme hors sujet là-dedans. Puis demandé sur math.stackexchange, mais la même fermeture s'est produite. C'est la troisième place, peut-être que c'est le bon endroit, qui sait.
Timo Kähkönen
2
Je ne sais pas comment fonctionne l'algorithme, mais InDesign peut le faire: "Le crénage optique ajuste l'espacement entre les caractères adjacents en fonction de leurs formes. Certaines polices incluent des spécifications de paire de crénage robustes. Cependant, lorsqu'une police ne comprend qu'un minimum intégré crénage ou aucun, ou si vous utilisez deux polices ou tailles différentes en un ou plusieurs mots sur une ligne, vous pouvez utiliser l'option de crénage optique. " help.adobe.com/en_US/indesign/cs/using/…
e100
2
Je pense que cela relève probablement de la portée d'un algorithme général - une séquence d'étapes à effectuer pour résoudre un problème. Mais je ne pense pas que les détails de l'implémentation dans JS ou dans un autre langage appartiennent, et je suis en train de modifier pour ne mentionner JS que comme cas d'utilisation en arrière-plan.
e100
1
Je pense que le premier ordre du jour est de définir "optimal" d'une manière qui soit utile pour un algorithme machine.
horatio

Réponses:

4

Je sais que c'est vieux. J'y travaille en ce moment dans une implémentation WebGL de texte bancal (peu importe). La solution sur laquelle je travaille se présente comme suit:

  1. Obtenez une version bitmap de la paire de glyphes (ou faites-le avec des vecteurs si vous le souhaitez)
  2. Pour chaque ligne de pixels (ou unité verticale arbitraire si vous choisissez des vecteurs), vérifiez que les deux glyphes ont au moins un pixel présent
  3. Pour chaque ligne qui passe l'étape 2, calculez la distance entre le pixel le plus à droite du premier glyphe et le pixel le plus à gauche du deuxième glyphe
  4. Déplacez le deuxième glyphe aussi loin que possible à gauche tout en respectant ces critères:
    • l'écart dans cette rangée de pixels est supérieur à un écart minimum que vous avez spécifié
    • la zone totale (en ignorant les lignes sans pixel dans l'un des glyphes) est supérieure à la zone minimale que vous avez spécifiée

De cette façon, la «zone» vide entre les lettres devrait être réduite à une moyenne assez commune. Spécifiez l'écart minimum et la zone minimale à l'aide d'essais et d'erreurs et de vos propres goûts, et peut-être permettre à ces paramètres d'être également ajustés par un autre agent ... comme une valeur de crénage manuel.

Yay :)

Edit: J'ai implémenté cela avec succès maintenant et cela fonctionne vraiment bien :)

jaya
la source
Bonne réponse! Bienvenue sur GD.SE :)
Yisela
Merci pour l'accueil: D !! Je dois ajouter que la zone doit être divisée par le nombre de lignes actuellement testées (ce qui en fait juste un écart moyen et pas vraiment une zone). Et il serait également bon de tester si l'écart d'une ligne est une valeur statistique aberrante et d'ignorer cette ligne si elle l'est. Cela aidera à éviter de serrer les lettres trop près quand il y a une grande ouverture comme dans 'G'
jaya
Il semble y avoir quelques enfants problématiques ici et là, comme T- ou o 'par exemple dans certains styles de police de certaines polices. T- laissez le trait d'union trop près du T, et o 'ne partageait aucun pixel dans la même ligne, j'ai donc fait un repli pour utiliser les lignes les plus proches avec un pixel chacune lorsque cela se produit. Pour rendre l'algorithme ci-dessus plus robuste, vous devez en quelque sorte vérifier ces types de problèmes. Pour mes besoins, ce n'était pas nécessaire.
jaya
3

Il s'agit d'un algorithme assez simple que j'ai essayé une fois et qui peut être suffisant.

Rendez les caractères en basse résolution - disons six ou sept pixels de hauteur (hauteur du capital typique) à peu près la même horizontalement. Vous voulez une simple carte binaire de l'endroit où il y a de l'espace vide par rapport à des parties de la lettre, sur une simple grille basse résolution.

"Engraisser" ces cartes de lettres. Autrement dit, remplissez chaque cellule vide adjacente à une cellule remplie. Il s'agit de revendiquer un territoire vide le plus proche des bords de la lettre, afin que la lettre voisine ne soit pas trop proche.

Jouez "Tetris horizontal" avec les cartes de lettres résultantes. Laissez la gravité agir à gauche. Le "ventre" bombé gauche du "a" "tombera" dans la cavité sous la barre du "T". Combien de cellules le "a" a-t-il déplacé? Augmentez l'échelle proportionnellement à la taille réelle des lettres et c'est dans quelle mesure pour créner le "haute résolution" réel vers la gauche.

DarenW
la source
1
Merci! Pour visualiser votre algorithme, pourriez-vous fournir un exemple d'image basse résolution en utilisant les paires "db", "AA", "Ta" et "c-" en utilisant Arial.
Timo Kähkönen
Bon début, mais je pense que cela peut être limité lorsque des paires de personnages protubérants ne "Tetris" pas ensemble, par exemple "bd", "TT", "pq", "gj"
e100
@ e100: À première vue, ces paires particulières n'auraient pas de boîtes englobantes qui se chevauchent ...
horatio
Mais d'une manière générale, ils devraient être crénés plus serrés que "MM", "NN" etc.
e100
2

Il existe déjà des algorithmes de crénage automatique. Aucun n'est infaillible et ils ont tendance à nécessiter un peu de prise en main et une correction manuelle de certains aspects, surtout si votre suivi est relativement serré.

Mais ces algorithmes sont destinés à appliquer le crénage au fichier de police , pas aux lettres car elles sont générées à partir du fichier de police.

Avez-vous envisagé d'appliquer le crénage automatique au fichier de police?

Fontforge (open source) et Fontlab (commercial) contiennent des algorithmes de crénage automatique. Ils auraient une courbe d'apprentissage relativement abrupte - vous devez être familier avec les aspects techniques du fonctionnement des polices.

Il y a aussi iKern qui est un type qui offre une police crénage commerciale de service par lequel il crène votre police pour vous et fait un excellent travail plutôt. Je ne sais pas combien cela coûterait.

thomasrutter
la source
Mais la question est vraiment "comment fonctionnerait un tel algorithme?" - pouvez-vous ajouter des détails sur le fonctionnement de FontForge?
e100
0

Je n'ai pas le temps de réfléchir à cela, ni de dessiner des illustrations, mais j'avais une demi-idée basée sur la première bissection verticale de chaque glyphe.

Ensuite, pour chaque moitié, déterminez deux axes verticaux: - la bissectrice - exactement la moitié entre les extrémités gauche et droite - l'axe "poids" - exactement la moitié de l'encre de chaque côté

Ensuite, déplacez le glyphe voisin adjacent vers ou à l'écart du demi-glyphe de test en fonction des positions relatives des deux axes.

Ainsi, par exemple, dans la paire "AV", la moitié droite du A est lourde à gauche et "attire" le V; la moitié gauche du V est à droite "attire" le A, donc ils sont crénés ensemble de manière significative.

Cependant, je suis sûr qu'il y a une faille dans le fait que "AA" serait aussi bien groupé que "AV".

e100
la source
0

En considérant les majuscules et les minuscules, il y a 56X55=2652des situations de paires de polices que vous devriez inquiéter, toutes les solutions peuvent être facilement brisées car si vous changez le style de police, toutes les règles ont disparu.

La meilleure façon est d'utiliser la technique d'apprentissage automatique, d'essayer d'établir un modèle d'étude de réseau de neurones et d'importer plusieurs images ou vecteurs de texte en crénage, etc., de former ce modèle et d'utiliser ce modèle formé pour ajuster intelligemment tout type de police.

car il n'y a pas d'algorithme statique pour ajuster parfaitement la police à la racine, le machine learning serait une bonne solution à ce genre de problème!

Super-ilade
la source
Pas s'il n'y a que des critères essentiellement subjectifs. "Est-ce un chien ou un chat?", Peu importe à quel point le chien a l'air bizarre, a toujours une réponse exacte. (Même s'il faut un vétérinaire pour vérifier.)
usr2564301