Leptonica  1.77.0
Image processing and image analysis suite
bmf.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
69 #include <string.h>
70 #include "allheaders.h"
71 #include "bmfdata.h"
72 
73 static const l_float32 VERT_FRACT_SEP = 0.3;
74 
75 #ifndef NO_CONSOLE_IO
76 #define DEBUG_BASELINE 0
77 #define DEBUG_CHARS 0
78 #define DEBUG_FONT_GEN 0
79 #endif /* ~NO_CONSOLE_IO */
80 
81 static PIXA *pixaGenerateFontFromFile(const char *dir, l_int32 fontsize,
82  l_int32 *pbl0, l_int32 *pbl1,
83  l_int32 *pbl2);
84 static PIXA *pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0,
85  l_int32 *pbl1, l_int32 *pbl2);
86 static PIXA *pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0,
87  l_int32 *pbl1, l_int32 *pbl2);
88 static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py);
89 static l_int32 bmfMakeAsciiTables(L_BMF *bmf);
90 
91 
92 /*---------------------------------------------------------------------*/
93 /* Bmf create/destroy */
94 /*---------------------------------------------------------------------*/
113 L_BMF *
114 bmfCreate(const char *dir,
115  l_int32 fontsize)
116 {
117 L_BMF *bmf;
118 PIXA *pixa;
119 
120  PROCNAME("bmfCreate");
121 
122  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
123  return (L_BMF *)ERROR_PTR("fontsize must be in {4, 6, ..., 20}",
124  procName, NULL);
125  if ((bmf = (L_BMF *)LEPT_CALLOC(1, sizeof(L_BMF))) == NULL)
126  return (L_BMF *)ERROR_PTR("bmf not made", procName, NULL);
127 
128  if (!dir) { /* Generate from a string */
129  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
130  &bmf->baseline2, &bmf->baseline3);
131  } else { /* Look for the pixa in a directory */
132  pixa = pixaGetFont(dir, fontsize, &bmf->baseline1, &bmf->baseline2,
133  &bmf->baseline3);
134  if (!pixa) { /* Not found; make it from a file */
135  L_INFO("Generating pixa of bitmap fonts from file\n", procName);
136  pixa = pixaGenerateFontFromFile(dir, fontsize, &bmf->baseline1,
137  &bmf->baseline2, &bmf->baseline3);
138  if (!pixa) { /* Not made; make it from a string after all */
139  L_ERROR("Failed to make font; use string\n", procName);
140  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
141  &bmf->baseline2, &bmf->baseline3);
142  }
143  }
144  }
145 
146  if (!pixa) {
147  bmfDestroy(&bmf);
148  return (L_BMF *)ERROR_PTR("font pixa not made", procName, NULL);
149  }
150 
151  bmf->pixa = pixa;
152  bmf->size = fontsize;
153  if (dir) bmf->directory = stringNew(dir);
154  bmfMakeAsciiTables(bmf);
155  return bmf;
156 }
157 
158 
165 void
167 {
168 L_BMF *bmf;
169 
170  PROCNAME("bmfDestroy");
171 
172  if (pbmf == NULL) {
173  L_WARNING("ptr address is null!\n", procName);
174  return;
175  }
176 
177  if ((bmf = *pbmf) == NULL)
178  return;
179 
180  pixaDestroy(&bmf->pixa);
181  LEPT_FREE(bmf->directory);
182  LEPT_FREE(bmf->fonttab);
183  LEPT_FREE(bmf->baselinetab);
184  LEPT_FREE(bmf->widthtab);
185  LEPT_FREE(bmf);
186  *pbmf = NULL;
187  return;
188 }
189 
190 
191 /*---------------------------------------------------------------------*/
192 /* Bmf accessors */
193 /*---------------------------------------------------------------------*/
201 PIX *
203  char chr)
204 {
205 l_int32 i, index;
206 PIXA *pixa;
207 
208  PROCNAME("bmfGetPix");
209 
210  if ((index = (l_int32)chr) == 10) /* NL */
211  return NULL;
212  if (!bmf)
213  return (PIX *)ERROR_PTR("bmf not defined", procName, NULL);
214 
215  i = bmf->fonttab[index];
216  if (i == UNDEF) {
217  L_ERROR("no bitmap representation for %d\n", procName, index);
218  return NULL;
219  }
220 
221  if ((pixa = bmf->pixa) == NULL)
222  return (PIX *)ERROR_PTR("pixa not found", procName, NULL);
223 
224  return pixaGetPix(pixa, i, L_CLONE);
225 }
226 
227 
236 l_ok
238  char chr,
239  l_int32 *pw)
240 {
241 l_int32 i, index;
242 PIXA *pixa;
243 
244  PROCNAME("bmfGetWidth");
245 
246  if (!pw)
247  return ERROR_INT("&w not defined", procName, 1);
248  *pw = -1;
249  if (!bmf)
250  return ERROR_INT("bmf not defined", procName, 1);
251  if ((index = (l_int32)chr) == 10) /* NL */
252  return 0;
253 
254  i = bmf->fonttab[index];
255  if (i == UNDEF) {
256  L_ERROR("no bitmap representation for %d\n", procName, index);
257  return 1;
258  }
259 
260  if ((pixa = bmf->pixa) == NULL)
261  return ERROR_INT("pixa not found", procName, 1);
262 
263  return pixaGetPixDimensions(pixa, i, pw, NULL, NULL);
264 }
265 
266 
275 l_ok
277  char chr,
278  l_int32 *pbaseline)
279 {
280 l_int32 bl, index;
281 
282  PROCNAME("bmfGetBaseline");
283 
284  if (!pbaseline)
285  return ERROR_INT("&baseline not defined", procName, 1);
286  *pbaseline = 0;
287  if (!bmf)
288  return ERROR_INT("bmf not defined", procName, 1);
289  if ((index = (l_int32)chr) == 10) /* NL */
290  return 0;
291 
292  bl = bmf->baselinetab[index];
293  if (bl == UNDEF) {
294  L_ERROR("no bitmap representation for %d\n", procName, index);
295  return 1;
296  }
297 
298  *pbaseline = bl;
299  return 0;
300 }
301 
302 
303 /*---------------------------------------------------------------------*/
304 /* Font bitmap acquisition and generation */
305 /*---------------------------------------------------------------------*/
321 PIXA *
322 pixaGetFont(const char *dir,
323  l_int32 fontsize,
324  l_int32 *pbl0,
325  l_int32 *pbl1,
326  l_int32 *pbl2)
327 {
328 char *pathname;
329 l_int32 fileno;
330 PIXA *pixa;
331 
332  PROCNAME("pixaGetFont");
333 
334  fileno = (fontsize / 2) - 2;
335  if (fileno < 0 || fileno >= NUM_FONTS)
336  return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
337  if (!pbl0 || !pbl1 || !pbl2)
338  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
339  *pbl0 = baselines[fileno][0];
340  *pbl1 = baselines[fileno][1];
341  *pbl2 = baselines[fileno][2];
342 
343  pathname = pathJoin(dir, outputfonts[fileno]);
344  pixa = pixaRead(pathname);
345  LEPT_FREE(pathname);
346 
347  if (!pixa)
348  L_WARNING("pixa of char bitmaps not found\n", procName);
349  return pixa;
350 }
351 
352 
371 l_ok
372 pixaSaveFont(const char *indir,
373  const char *outdir,
374  l_int32 fontsize)
375 {
376 char *pathname;
377 l_int32 bl1, bl2, bl3;
378 PIXA *pixa;
379 
380  PROCNAME("pixaSaveFont");
381 
382  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
383  return ERROR_INT("fontsize must be in {4, 6, ..., 20}", procName, 1);
384 
385  if (!indir) /* Generate from a string */
386  pixa = pixaGenerateFontFromString(fontsize, &bl1, &bl2, &bl3);
387  else /* Generate from an image file */
388  pixa = pixaGenerateFontFromFile(indir, fontsize, &bl1, &bl2, &bl3);
389  if (!pixa)
390  return ERROR_INT("pixa not made", procName, 1);
391 
392  pathname = pathJoin(outdir, outputfonts[(fontsize - 4) / 2]);
393  pixaWrite(pathname, pixa);
394 
395 #if DEBUG_FONT_GEN
396  L_INFO("Found %d chars in font size %d\n", procName, pixaGetCount(pixa),
397  fontsize);
398  L_INFO("Baselines are at: %d, %d, %d\n", procName, bl1, bl2, bl3);
399 #endif /* DEBUG_FONT_GEN */
400 
401  LEPT_FREE(pathname);
402  pixaDestroy(&pixa);
403  return 0;
404 }
405 
406 
433 static PIXA *
434 pixaGenerateFontFromFile(const char *dir,
435  l_int32 fontsize,
436  l_int32 *pbl0,
437  l_int32 *pbl1,
438  l_int32 *pbl2)
439 {
440 char *pathname;
441 l_int32 fileno;
442 PIX *pix;
443 PIXA *pixa;
444 
445  PROCNAME("pixaGenerateFontFromFile");
446 
447  if (!pbl0 || !pbl1 || !pbl2)
448  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
449  *pbl0 = *pbl1 = *pbl2 = 0;
450  if (!dir)
451  return (PIXA *)ERROR_PTR("dir not defined", procName, NULL);
452  fileno = (fontsize / 2) - 2;
453  if (fileno < 0 || fileno >= NUM_FONTS)
454  return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
455 
456  pathname = pathJoin(dir, inputfonts[fileno]);
457  pix = pixRead(pathname);
458  LEPT_FREE(pathname);
459  if (!pix) {
460  L_ERROR("pix not found for font size %d\n", procName, fontsize);
461  return NULL;
462  }
463 
464  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
465  pixDestroy(&pix);
466  return pixa;
467 }
468 
469 
484 static PIXA *
485 pixaGenerateFontFromString(l_int32 fontsize,
486  l_int32 *pbl0,
487  l_int32 *pbl1,
488  l_int32 *pbl2)
489 {
490 l_uint8 *data;
491 l_int32 redsize, nbytes;
492 PIX *pix;
493 PIXA *pixa;
494 
495  PROCNAME("pixaGenerateFontFromString");
496 
497  if (!pbl0 || !pbl1 || !pbl2)
498  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
499  *pbl0 = *pbl1 = *pbl2 = 0;
500  redsize = (fontsize / 2) - 2;
501  if (redsize < 0 || redsize >= NUM_FONTS)
502  return (PIXA *)ERROR_PTR("invalid font size", procName, NULL);
503 
504  if (fontsize == 4) {
505  data = decodeBase64(fontdata_4, strlen(fontdata_4), &nbytes);
506  } else if (fontsize == 6) {
507  data = decodeBase64(fontdata_6, strlen(fontdata_6), &nbytes);
508  } else if (fontsize == 8) {
509  data = decodeBase64(fontdata_8, strlen(fontdata_8), &nbytes);
510  } else if (fontsize == 10) {
511  data = decodeBase64(fontdata_10, strlen(fontdata_10), &nbytes);
512  } else if (fontsize == 12) {
513  data = decodeBase64(fontdata_12, strlen(fontdata_12), &nbytes);
514  } else if (fontsize == 14) {
515  data = decodeBase64(fontdata_14, strlen(fontdata_14), &nbytes);
516  } else if (fontsize == 16) {
517  data = decodeBase64(fontdata_16, strlen(fontdata_16), &nbytes);
518  } else if (fontsize == 18) {
519  data = decodeBase64(fontdata_18, strlen(fontdata_18), &nbytes);
520  } else { /* fontsize == 20 */
521  data = decodeBase64(fontdata_20, strlen(fontdata_20), &nbytes);
522  }
523  if (!data)
524  return (PIXA *)ERROR_PTR("data not made", procName, NULL);
525 
526  pix = pixReadMem(data, nbytes);
527  LEPT_FREE(data);
528  if (!pix)
529  return (PIXA *)ERROR_PTR("pix not made", procName, NULL);
530 
531  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
532  pixDestroy(&pix);
533  return pixa;
534 }
535 
536 
555 static PIXA *
557  l_int32 fontsize,
558  l_int32 *pbl0,
559  l_int32 *pbl1,
560  l_int32 *pbl2)
561 {
562 l_int32 i, j, nrows, nrowchars, nchars, h, yval;
563 l_int32 width, height;
564 l_int32 baseline[3];
565 l_int32 *tab = NULL;
566 BOX *box, *box1, *box2;
567 BOXA *boxar, *boxac, *boxacs;
568 PIX *pix1, *pix2, *pixr, *pixrc, *pixc;
569 PIXA *pixa;
570 l_int32 n, w, inrow, top;
571 l_int32 *ia;
572 NUMA *na;
573 
574  PROCNAME("pixaGenerateFont");
575 
576  if (!pbl0 || !pbl1 || !pbl2)
577  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
578  *pbl0 = *pbl1 = *pbl2 = 0;
579  if (!pixs)
580  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
581 
582  /* Locate the 3 rows of characters */
583  w = pixGetWidth(pixs);
584  na = pixCountPixelsByRow(pixs, NULL);
585  boxar = boxaCreate(0);
586  n = numaGetCount(na);
587  ia = numaGetIArray(na);
588  inrow = 0;
589  for (i = 0; i < n; i++) {
590  if (!inrow && ia[i] > 0) {
591  inrow = 1;
592  top = i;
593  } else if (inrow && ia[i] == 0) {
594  inrow = 0;
595  box = boxCreate(0, top, w, i - top);
596  boxaAddBox(boxar, box, L_INSERT);
597  }
598  }
599  LEPT_FREE(ia);
600  numaDestroy(&na);
601  nrows = boxaGetCount(boxar);
602 #if DEBUG_FONT_GEN
603  L_INFO("For fontsize %s, have %d rows\n", procName, fontsize, nrows);
604 #endif /* DEBUG_FONT_GEN */
605  if (nrows != 3) {
606  L_INFO("nrows = %d; skipping fontsize %d\n", procName, nrows, fontsize);
607  boxaDestroy(&boxar);
608  return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
609  }
610 
611  /* Grab the character images and baseline data */
612 #if DEBUG_BASELINE
613  lept_rmdir("baseline");
614  lept_mkdir("baseline");
615 #endif /* DEBUG_BASELINE */
616  tab = makePixelSumTab8();
617  pixa = pixaCreate(95);
618  for (i = 0; i < nrows; i++) {
619  box = boxaGetBox(boxar, i, L_CLONE);
620  pixr = pixClipRectangle(pixs, box, NULL); /* row of chars */
621  pixGetTextBaseline(pixr, tab, &yval);
622  baseline[i] = yval;
623 
624 #if DEBUG_BASELINE
625  L_INFO("Baseline info: row %d, yval = %d, h = %d\n", procName,
626  i, yval, pixGetHeight(pixr));
627  pix1 = pixCopy(NULL, pixr);
628  pixRenderLine(pix1, 0, yval, pixGetWidth(pix1), yval, 1,
629  L_FLIP_PIXELS);
630  if (i == 0 )
631  pixWriteDebug("/tmp/baseline/row0.png", pix1, IFF_PNG);
632  else if (i == 1)
633  pixWriteDebug("/tmp/baseline/row1.png", pix1, IFF_PNG);
634  else
635  pixWriteDebug("/tmp/baseline/row2.png", pix1, IFF_PNG);
636  pixDestroy(&pix1);
637 #endif /* DEBUG_BASELINE */
638 
639  boxDestroy(&box);
640  pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
641  boxac = pixConnComp(pixrc, NULL, 8);
642  boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
643  if (i == 0) { /* consolidate the two components of '"' */
644  box1 = boxaGetBox(boxacs, 1, L_CLONE);
645  box2 = boxaGetBox(boxacs, 2, L_CLONE);
646  box1->w = box2->x + box2->w - box1->x; /* increase width */
647  boxDestroy(&box1);
648  boxDestroy(&box2);
649  boxaRemoveBox(boxacs, 2);
650  }
651  h = pixGetHeight(pixr);
652  nrowchars = boxaGetCount(boxacs);
653  for (j = 0; j < nrowchars; j++) {
654  box = boxaGetBox(boxacs, j, L_COPY);
655  if (box->w <= 2 && box->h == 1) { /* skip 1x1, 2x1 components */
656  boxDestroy(&box);
657  continue;
658  }
659  box->y = 0;
660  box->h = h - 1;
661  pixc = pixClipRectangle(pixr, box, NULL);
662  boxDestroy(&box);
663  if (i == 0 && j == 0) /* add a pix for the space; change later */
664  pixaAddPix(pixa, pixc, L_COPY);
665  if (i == 2 && j == 0) /* add a pix for the '\'; change later */
666  pixaAddPix(pixa, pixc, L_COPY);
667  pixaAddPix(pixa, pixc, L_INSERT);
668  }
669  pixDestroy(&pixr);
670  pixDestroy(&pixrc);
671  boxaDestroy(&boxac);
672  boxaDestroy(&boxacs);
673  }
674  LEPT_FREE(tab);
675 
676  nchars = pixaGetCount(pixa);
677  if (nchars != 95)
678  return (PIXA *)ERROR_PTR("95 chars not generated", procName, NULL);
679 
680  *pbl0 = baseline[0];
681  *pbl1 = baseline[1];
682  *pbl2 = baseline[2];
683 
684  /* Fix the space character up; it should have no ON pixels,
685  * and be about twice as wide as the '!' character. */
686  pix1 = pixaGetPix(pixa, 0, L_CLONE);
687  width = 2 * pixGetWidth(pix1);
688  height = pixGetHeight(pix1);
689  pixDestroy(&pix1);
690  pix1 = pixCreate(width, height, 1);
691  pixaReplacePix(pixa, 0, pix1, NULL);
692 
693  /* Fix up the '\' character; use a LR flip of the '/' char */
694  pix1 = pixaGetPix(pixa, 15, L_CLONE);
695  pix2 = pixFlipLR(NULL, pix1);
696  pixDestroy(&pix1);
697  pixaReplacePix(pixa, 60, pix2, NULL);
698 
699 #if DEBUG_CHARS
700  pix1 = pixaDisplayTiled(pixa, 1500, 0, 10);
701  pixDisplay(pix1, 100 * i, 200);
702  pixDestroy(&pix1);
703 #endif /* DEBUG_CHARS */
704 
705  boxaDestroy(&boxar);
706  return pixa;
707 }
708 
709 
726 static l_int32
728  l_int32 *tab8,
729  l_int32 *py)
730 {
731 l_int32 i, h, val1, val2, diff, diffmax, ymax;
732 l_int32 *tab;
733 NUMA *na;
734 
735  PROCNAME("pixGetTextBaseline");
736 
737  if (!pixs)
738  return ERROR_INT("pixs not defined", procName, 1);
739  if (!py)
740  return ERROR_INT("&y not defined", procName, 1);
741  *py = 0;
742  if (!tab8)
743  tab = makePixelSumTab8();
744  else
745  tab = tab8;
746 
747  na = pixCountPixelsByRow(pixs, tab);
748  h = numaGetCount(na);
749  diffmax = 0;
750  ymax = 0;
751  for (i = 1; i < h; i++) {
752  numaGetIValue(na, i - 1, &val1);
753  numaGetIValue(na, i, &val2);
754  diff = L_MAX(0, val1 - val2);
755  if (diff > diffmax) {
756  diffmax = diff;
757  ymax = i - 1; /* upper raster line */
758  }
759  }
760  *py = ymax;
761 
762  if (!tab8)
763  LEPT_FREE(tab);
764  numaDestroy(&na);
765  return 0;
766 }
767 
768 
801 static l_int32
803 {
804 l_int32 i, maxh, height, charwidth, xwidth, kernwidth;
805 l_int32 *fonttab, *baselinetab, *widthtab;
806 PIX *pix;
807 
808  PROCNAME("bmfMakeAsciiTables");
809 
810  if (!bmf)
811  return ERROR_INT("bmf not defined", procName, 1);
812 
813  /* First get the fonttab; we use this later for the char widths */
814  if ((fonttab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32))) == NULL)
815  return ERROR_INT("fonttab not made", procName, 1);
816  bmf->fonttab = fonttab;
817  for (i = 0; i < 128; i++)
818  fonttab[i] = UNDEF;
819  for (i = 32; i < 127; i++)
820  fonttab[i] = i - 32;
821 
822  if ((baselinetab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32))) == NULL)
823  return ERROR_INT("baselinetab not made", procName, 1);
824  bmf->baselinetab = baselinetab;
825  for (i = 0; i < 128; i++)
826  baselinetab[i] = UNDEF;
827  for (i = 32; i <= 57; i++)
828  baselinetab[i] = bmf->baseline1;
829  for (i = 58; i <= 91; i++)
830  baselinetab[i] = bmf->baseline2;
831  baselinetab[92] = bmf->baseline1; /* the '\' char */
832  for (i = 93; i < 127; i++)
833  baselinetab[i] = bmf->baseline3;
834 
835  /* Generate array of character widths; req's fonttab to exist */
836  if ((widthtab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32))) == NULL)
837  return ERROR_INT("widthtab not made", procName, 1);
838  bmf->widthtab = widthtab;
839  for (i = 0; i < 128; i++)
840  widthtab[i] = UNDEF;
841  for (i = 32; i < 127; i++) {
842  bmfGetWidth(bmf, i, &charwidth);
843  widthtab[i] = charwidth;
844  }
845 
846  /* Get the line height of text characters, from the highest
847  * ascender to the lowest descender; req's fonttab to exist. */
848  pix = bmfGetPix(bmf, 32);
849  maxh = pixGetHeight(pix);
850  pixDestroy(&pix);
851  pix = bmfGetPix(bmf, 58);
852  height = pixGetHeight(pix);
853  pixDestroy(&pix);
854  maxh = L_MAX(maxh, height);
855  pix = bmfGetPix(bmf, 93);
856  height = pixGetHeight(pix);
857  pixDestroy(&pix);
858  maxh = L_MAX(maxh, height);
859  bmf->lineheight = maxh;
860 
861  /* Get the kern width (distance between characters).
862  * We let it be the same for all characters in a given
863  * font size, and scale it linearly with the size;
864  * req's fonttab to be built first. */
865  bmfGetWidth(bmf, 120, &xwidth);
866  kernwidth = (l_int32)(0.08 * (l_float32)xwidth + 0.5);
867  bmf->kernwidth = L_MAX(1, kernwidth);
868 
869  /* Save the space width (between words) */
870  bmfGetWidth(bmf, 32, &charwidth);
871  bmf->spacewidth = charwidth;
872 
873  /* Save the extra vertical space between lines */
874  bmf->vertlinesep = (l_int32)(VERT_FRACT_SEP * bmf->lineheight + 0.5);
875 
876  return 0;
877 }
static PIXA * pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFont()
Definition: bmf.c:556
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:423
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2029
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:166
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
PIX * bmfGetPix(L_BMF *bmf, char chr)
bmfGetPix()
Definition: bmf.c:202
BOXA * boxaSort(BOXA *boxas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex)
boxaSort()
Definition: boxfunc2.c:568
l_int32 lineheight
Definition: bmf.h:53
l_ok pixaSaveFont(const char *indir, const char *outdir, l_int32 fontsize)
pixaSaveFont()
Definition: bmf.c:372
PIXA * pixaGetFont(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGetFont()
Definition: bmf.c:322
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
l_int32 * baselinetab
Definition: bmf.h:58
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:215
l_ok pixaWrite(const char *filename, PIXA *pixa)
pixaWrite()
Definition: pixabasic.c:2733
l_int32 y
Definition: pix.h:483
PIXA * pixaRead(const char *filename)
pixaRead()
Definition: pixabasic.c:2572
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
struct Pix * pixs
Definition: bilateral.h:117
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
PIX * pixReadMem(const l_uint8 *data, size_t size)
pixReadMem()
Definition: readfile.c:839
l_int32 * widthtab
Definition: bmf.h:59
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
Definition: pix.h:492
l_ok bmfGetWidth(L_BMF *bmf, char chr, l_int32 *pw)
bmfGetWidth()
Definition: bmf.c:237
Definition: bmf.h:45
char * directory
Definition: bmf.h:49
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:820
static l_int32 bmfMakeAsciiTables(L_BMF *bmf)
bmfMakeAsciiTables
Definition: bmf.c:802
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:147
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
PIX * pixCloseSafeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeBrick()
Definition: morph.c:949
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_int32 baseline3
Definition: bmf.h:52
l_int32 w
Definition: pix.h:484
l_int32 baseline1
Definition: bmf.h:50
static PIXA * pixaGenerateFontFromFile(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromFile()
Definition: bmf.c:434
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2297
l_int32 kernwidth
Definition: bmf.h:54
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
l_ok bmfGetBaseline(L_BMF *bmf, char chr, l_int32 *pbaseline)
bmfGetBaseline()
Definition: bmf.c:276
l_int32 x
Definition: pix.h:482
Definition: pix.h:454
l_ok pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1483
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_int32 vertlinesep
Definition: bmf.h:56
l_int32 size
Definition: bmf.h:48
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:190
l_ok boxaRemoveBox(BOXA *boxa, l_int32 index)
boxaRemoveBox()
Definition: boxbasic.c:1029
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2686
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
Definition: pix.h:718
l_int32 h
Definition: pix.h:485
Definition: pix.h:134
Definition: pix.h:719
static PIXA * pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromString()
Definition: bmf.c:485
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:707
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py)
pixGetTextBaseline()
Definition: bmf.c:727
l_int32 * fonttab
Definition: bmf.h:57
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2021
struct Pixa * pixa
Definition: bmf.h:47
Definition: pix.h:480
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
l_int32 baseline2
Definition: bmf.h:51
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_int32 spacewidth
Definition: bmf.h:55
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
l_ok pixaReplacePix(PIXA *pixa, l_int32 index, PIX *pix, BOX *box)
pixaReplacePix()
Definition: pixabasic.c:1299
PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing)
pixaDisplayTiled()
Definition: pixafunc2.c:722
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:114