Crenatura al volo


10

Qualcuno conosce qualche algoritmo che calcolerebbe automaticamente la crenatura dei caratteri in base alle forme dei glifi quando l'utente digita il testo?

Non intendo un calcolo banale di larghezze avanzate o simili, intendo analizzare la forma dei glifi per stimare la distanza visivamente ottimale tra i caratteri. Ad esempio, se disponiamo tre caratteri in sequenza in una riga, il personaggio centrale dovrebbe SEMPRE essere al centro della linea, nonostante le forme del personaggio. Un esempio illumina la funzionalità di crenatura al volo:

Un esempio di crenatura al volo:

Immagine dello schermo

Nell'immagine sopra asembra essere troppo giusto. Dovrebbe essere spostato di un certo importo verso in Tmodo che sembri essere nel mezzo di Te g. L'algoritmo dovrebbe esaminare le forme di Te a(e possibilmente anche altre lettere) e decidere quanto adeve essere spostato a sinistra. Questa certa quantità è la cosa che dovrebbe essere calcolata dall'algoritmo - SENZA ESAMINARE LE POSSIBILI COPPIE DEL FONT.

Sto pensando di codificare un programma javascript (+ svg + html) che utilizza caratteri disegnati a mano e molti di loro mancano di coppie di crenatura. I campi di testo saranno modificabili e possono includere testo di più caratteri. Penso che la crenatura al volo potrebbe essere un modo per garantire un flusso di testo medio in questo caso.

EDIT: un punto di partenza potrebbe essere l'uso del carattere svg, quindi è facile ottenere i valori del percorso. Nel carattere svg il percorso è definito in questo modo:

<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'algoritmo (o codice javascript) dovrebbe esaminare quei percorsi in qualche modo e determinare la distanza ottimale tra loro.


1
Se stai cercando una soluzione di codifica, questo sarebbe meglio chiedere a SO. È quello che stai cercando? In tal caso, migrerò la domanda lì.
Alan Gilbertson,

2
Sono d'accordo che questa è una domanda così. Ho fatto la stessa domanda in SO, ma era chiusa come fuori tema. Quindi chiesto su math.stackexchange, ma è avvenuta la stessa chiusura. Questo è il terzo posto, può essere questo il posto giusto, chiunque lo sappia.
Timo Kähkönen,

2
Non so come funzioni l'algoritmo, ma InDesign può farlo: "La crenatura ottica regola la spaziatura tra caratteri adiacenti in base alle loro forme. Alcuni caratteri includono solide specifiche di coppia di kern. Tuttavia, quando un carattere include solo un minimo incorporato crenatura o nessuna, o se usi due caratteri o dimensioni diversi in una o più parole su una riga, potresti voler usare l'opzione crenatura ottica. " help.adobe.com/en_US/indesign/cs/using/…
e100

2
Penso che questo rientri probabilmente nell'ambito di applicazione di un algoritmo generale: una sequenza di passaggi da eseguire per risolvere un problema. Ma non credo che i dettagli dell'implementazione in JS o in altri linguaggi appartengano e sto modificando per menzionare JS solo come caso d'uso in background.
e100,

1
Penso che il primo ordine del giorno sia definire "ottimale" in modo utile per un algoritmo di macchina.
horatio,

Risposte:


4

So che questo è vecchio. Ci sto lavorando proprio ora in un'implementazione WebGL di testo traballante (qualunque cosa). La soluzione a cui sto lavorando è questa:

  1. Ottieni una versione bitmap della coppia di glifi (o fallo con i vettori se vuoi)
  2. Per ogni riga di pixel (o unità verticale arbitraria se si utilizzano i vettori), verificare che entrambi i glifi abbiano almeno un pixel presente
  3. Per ogni riga che supera il passaggio 2, calcola la distanza tra il pixel più a destra del primo glifo e il pixel più a sinistra del secondo glifo
  4. Sposta il secondo glifo il più a sinistra possibile pur rispettando questi criteri:
    • lo spazio in quella riga di pixel è maggiore di uno spazio minimo specificato
    • l'area totale (ignorando le righe senza pixel in uno dei glifi) è maggiore di un'area minima specificata

In questo modo, l'area vuota tra le lettere dovrebbe essere ridotta a una media abbastanza comune. Specifica lo spazio minimo e l'area minima usando tentativi ed errori e i tuoi gusti, e forse consenti a quei parametri di essere regolati anche da qualche altro agente ... come un valore di crenatura manuale.

Sìì :)

Modifica: l' ho impiantato con successo ora e funziona davvero bene :)


Bella risposta! Benvenuti in GD.SE :)
Yisela il

Grazie per il benvenuto: D !! Vorrei aggiungere che l'area dovrebbe essere divisa per il numero di righe effettivamente testate (il che in realtà lo rende solo un gap medio e non proprio un'area). E sarebbe anche utile verificare se il gap di una riga è un valore anomalo statistico e ignorarlo se lo è. Ciò contribuirà a evitare di stringere troppo le lettere quando c'è una grande apertura come in "G"
jaya

Sembra che ci siano alcuni bambini problematici qua e là, come T- o o 'per esempio in alcuni stili di carattere di alcuni caratteri. Lascia che il trattino si avvicini troppo alla T e non condivido alcun pixel nella stessa riga, quindi ho fatto un fallback per usare le righe più vicine con un pixel ciascuna quando ciò accade. Per rendere l'algoritmo di cui sopra più robusto, dovresti verificare in qualche modo questi tipi di problemi. Per i miei scopi, non era necessario.
jaya,

3

Questo è un algoritmo abbastanza semplice che ho provato una volta e potrebbe essere abbastanza buono.

Rendi i personaggi a bassa risoluzione: dire che sei o sette pixel di altezza (altezza della tipica maiuscola) circa lo stesso in orizzontale. Volete una semplice mappa binaria in cui vi sia spazio vuoto rispetto a parti della lettera, su una semplice griglia a bassa risoluzione.

"Ingrassare" queste mappe delle lettere. Cioè, riempire ogni cella vuota adiacente a una cella riempita. Questo per rivendicare un territorio vuoto più vicino ai bordi della lettera, quindi la lettera vicina non si avvicina troppo.

Gioca a "Tetris orizzontale" con le mappe delle lettere risultanti. Lascia che la gravità agisca a sinistra. Il "ventre" sinistro della sporgenza della "a" "cadrà" nella cavità sotto la barra superiore della "T". Quante celle si è mossa la "a"? Ridimensionalo in proporzione alla dimensione effettiva delle lettere ed è fino a che punto piegare la "a" ad alta risoluzione verso sinistra.


1
Grazie! Per visualizzare il tuo algoritmo potresti fornire alcuni esempi di immagini a bassa risoluzione usando le coppie "db", "AA", "Ta" e "c-" usando Arial.
Timo Kähkönen,

Buon inizio, ma sto pensando che questo potrebbe essere limitato quando coppie di personaggi protruberanti non "Tetris" insieme, ad esempio "bd", "TT", "pq", "gj"
e100

@ e100: a prima vista quei particolari accoppiamenti non avrebbero contorni sovrapposti ...
horatio

Ma in generale, dovrebbero essere più severi di "MM", "NN" ecc.
e100

2

Gli algoritmi per la crenatura automatica esistono già. Nessuno di questi è a prova di folle e tendono ad avere bisogno di un po 'di manipolazione manuale e correzione manuale di alcuni aspetti, specialmente se il tuo monitoraggio è relativamente stretto.

Ma quegli algoritmi servono per applicare la crenatura al file dei caratteri , non alle lettere come sono generate dal file dei caratteri.

Hai preso in considerazione l'applicazione della crenatura automatica al file dei caratteri?

Fontforge (open source) e Fontlab (commerciale) contengono algoritmi di crenatura automatica. Avrebbero una curva di apprendimento relativamente ripida: devi avere familiarità con gli aspetti tecnici di come funzionano i caratteri.

C'è anche iKern che è un ragazzo che offre un servizio commerciale di crenatura dei caratteri in base al quale cresta il tuo carattere per te e fa un lavoro piuttosto eccellente. Non so quanto costerebbe.


Ma la domanda è davvero "come funzionerebbe un tale algoritmo?" - puoi aggiungere qualche dettaglio su come funziona FontForge?
e100,


0

Non ho tempo di pensarci fino in fondo o di disegnare illustrazioni, ma ho avuto una mezza idea basata sulla prima bisettrice di ciascun glifo in verticale.

Quindi, per ogni metà, determinare due assi verticali: - la bisettrice - esattamente la metà tra gli estremi sinistro e destro - l'asse "peso" - esattamente la metà dell'inchiostro su ciascun lato

Quindi spostare il glifo vicino adiacente verso o lontano dal mezzo glifo di prova in base alle posizioni relative dei due assi.

Quindi, ad esempio, nella coppia "AV", la metà destra di A è pesante e "attira" la V; la metà sinistra della V è pesantemente destra "attira" la A, quindi vengono messe insieme in modo significativo.

Tuttavia, sono sicuro che c'è un difetto nel fatto che "AA" verrebbe messo insieme come "AV".


0

Considerando lettere maiuscole e minuscole, ci sono 56X55=2652situazioni di coppie di caratteri che dovresti preoccupare, tutte le soluzioni potrebbero essere facilmente rotte perché se cambi lo stile del carattere, tutte le regole sono andate.

Il modo migliore è utilizzare la tecnica di apprendimento automatico, provare a stabilire un modello di studio della rete neurale e importare più immagini di testo o vettore con crenatura o cose del genere, addestrare quel modello e utilizzare quel modello addestrato per regolare in modo intelligente qualsiasi tipo di carattere.

perché non esiste un algoritmo statico per regolare perfettamente il carattere nella radice, l'apprendimento automatico sarebbe una buona soluzione a questo tipo di problema!


Non se ci sono solo criteri prevalentemente soggettivi. "È un cane o un gatto?", Non importa quanto strano sia il cane, ha ancora una risposta esatta. (Anche se ci vuole un veterinario per verificare.)
usr2564301
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.