This program reads in a text file consisting of feature samples from a training page in the following format:
The result of this program is a binary inttemp file used by the OCR engine.
417 if (FLAGS_list_available_fonts) {
418 const vector<string>& all_fonts = FontUtils::ListAvailableFonts();
419 for (
int i = 0; i < all_fonts.size(); ++i) {
420 tprintf(
"%3d: %s\n", i, all_fonts[i].c_str());
422 "Font %s is unrecognized.\n", all_fonts[i].c_str());
430 "Use --unicharset_file only if --render_ngrams is set.\n");
432 if (!FLAGS_find_fonts && !FontUtils::IsAvailableFont(FLAGS_font.c_str())) {
434 if (!FontUtils::IsAvailableFont(FLAGS_font.c_str(), &pango_name)) {
435 tprintf(
"Could not find font named %s. Pango suggested font %s\n",
436 FLAGS_font.c_str(), pango_name.c_str());
441 if (FLAGS_render_ngrams)
442 FLAGS_output_word_boxes =
true;
444 char font_desc_name[1024];
445 snprintf(font_desc_name, 1024,
"%s %d", FLAGS_font.c_str(),
446 static_cast<int>(FLAGS_ptsize));
448 render.set_add_ligatures(FLAGS_ligatures);
449 render.set_leading(FLAGS_leading);
450 render.set_resolution(FLAGS_resolution);
451 render.set_char_spacing(FLAGS_char_spacing * FLAGS_ptsize);
452 render.set_h_margin(FLAGS_margin);
453 render.set_v_margin(FLAGS_margin);
454 render.set_output_word_boxes(FLAGS_output_word_boxes);
455 render.set_box_padding(FLAGS_box_padding);
456 render.set_strip_unrenderable_words(FLAGS_strip_unrenderable_words);
457 render.set_underline_start_prob(FLAGS_underline_start_prob);
458 render.set_underline_continuation_prob(FLAGS_underline_continuation_prob);
461 if (FLAGS_writing_mode ==
"horizontal") {
463 render.set_vertical_text(
false);
464 render.set_gravity_hint_strong(
false);
465 render.set_render_fullwidth_latin(
false);
466 }
else if (FLAGS_writing_mode ==
"vertical") {
468 render.set_vertical_text(
true);
469 render.set_gravity_hint_strong(
false);
470 render.set_render_fullwidth_latin(
false);
471 }
else if (FLAGS_writing_mode ==
"vertical-upright") {
477 render.set_vertical_text(
true);
478 render.set_gravity_hint_strong(
true);
479 render.set_render_fullwidth_latin(
true);
481 TLOG_FATAL(
"Invalid writing mode : %s\n", FLAGS_writing_mode.c_str());
486 File::ReadFileToStringOrDie(FLAGS_text.c_str(), &src_utf8);
489 if (strncmp(src_utf8.c_str(),
"\xef\xbb\xbf", 3) == 0) {
490 src_utf8.erase(0, 3);
492 tlog(1,
"Render string of size %d\n", src_utf8.length());
494 if (FLAGS_render_ngrams || FLAGS_only_extract_font_properties) {
497 const string kSeparator = FLAGS_render_ngrams ?
" " :
" ";
501 const int kCharsPerLine = (FLAGS_ptsize > 20) ? 50 : 100;
504 if (FLAGS_render_ngrams && !FLAGS_unicharset_file.empty() &&
506 TLOG_FATAL(
"Failed to load unicharset from file %s\n",
507 FLAGS_unicharset_file.c_str());
513 const char *str8 = src_utf8.c_str();
514 int len = src_utf8.length();
516 vector<pair<int, int> > offsets;
518 while (offset < len) {
520 offsets.push_back(make_pair(offset, step));
524 if (FLAGS_render_ngrams)
525 std::random_shuffle(offsets.begin(), offsets.end());
527 for (
int i = 0, line = 1; i < offsets.size(); ++i) {
528 const char *curr_pos = str8 + offsets[i].first;
529 int ngram_len = offsets[i].second;
531 if (!FLAGS_unicharset_file.empty() &&
535 rand_utf8.append(curr_pos, ngram_len);
536 if (rand_utf8.length() > line * kCharsPerLine) {
537 rand_utf8.append(
" \n");
539 if (line & 0x1) rand_utf8.append(kSeparator);
541 rand_utf8.append(kSeparator);
544 tlog(1,
"Rendered ngram string of size %d\n", rand_utf8.length());
545 src_utf8.swap(rand_utf8);
547 if (FLAGS_only_extract_font_properties) {
548 tprintf(
"Extracting font properties only\n");
555 vector<float> page_rotation;
556 const char* to_render_utf8 = src_utf8.c_str();
560 vector<string> font_names;
564 int num_pass = FLAGS_bidirectional_rotation ? 2 : 1;
565 for (
int pass = 0; pass < num_pass; ++pass) {
568 for (
int offset = 0; offset < strlen(to_render_utf8); ++im, ++page_num) {
569 tlog(1,
"Starting page %d\n", im);
571 if (FLAGS_find_fonts) {
572 offset += render.RenderAllFontsToImage(FLAGS_min_coverage,
573 to_render_utf8 + offset,
574 strlen(to_render_utf8 + offset),
577 offset += render.RenderToImage(to_render_utf8 + offset,
578 strlen(to_render_utf8 + offset), &pix);
584 rotation = -1 * page_rotation[page_num];
586 if (FLAGS_degrade_image) {
587 pix =
DegradeImage(pix, FLAGS_exposure, &randomizer, &rotation);
589 render.RotatePageBoxes(rotation);
593 page_rotation.push_back(rotation);
596 Pix* gray_pix = pixConvertTo8(pix,
false);
598 Pix* binary = pixThresholdToBinary(gray_pix, 128);
599 pixDestroy(&gray_pix);
600 char tiff_name[1024];
601 if (FLAGS_find_fonts) {
602 if (FLAGS_render_per_font) {
603 string fontname_for_file = tesseract::StringReplace(
604 font_used,
" ",
"_");
605 snprintf(tiff_name, 1024,
"%s.%s.tif", FLAGS_outputbase.c_str(),
606 fontname_for_file.c_str());
607 pixWriteTiff(tiff_name, binary, IFF_TIFF_G4,
"w");
608 tprintf(
"Rendered page %d to file %s\n", im, tiff_name);
610 font_names.push_back(font_used);
613 snprintf(tiff_name, 1024,
"%s.tif", FLAGS_outputbase.c_str());
614 pixWriteTiff(tiff_name, binary, IFF_TIFF_G4, im == 0 ?
"w" :
"a");
615 tprintf(
"Rendered page %d to file %s\n", im, tiff_name);
618 if (FLAGS_output_individual_glyph_images) {
620 tprintf(
"ERROR: Individual glyphs not saved\n");
625 if (FLAGS_find_fonts && offset != 0) {
632 if (!FLAGS_find_fonts) {
633 string box_name = FLAGS_outputbase.c_str();
635 render.WriteAllBoxes(box_name);
636 }
else if (!FLAGS_render_per_font && !font_names.empty()) {
637 string filename = FLAGS_outputbase.c_str();
638 filename +=
".fontlist.txt";
639 FILE* fp = fopen(filename.c_str(),
"wb");
641 tprintf(
"Failed to create output font list %s\n", filename.c_str());
643 for (
int i = 0; i < font_names.size(); ++i) {
644 fprintf(fp,
"%s\n", font_names[i].c_str());
bool MakeIndividualGlyphs(Pix *pix, const vector< BoxChar * > &vbox, const int input_tiff_page)
void ParseCommandLineFlags(const char *usage, int *argc, char ***argv, const bool remove_flags)
bool load_from_file(const char *const filename, bool skip_fragments)
int SpanUTF8Whitespace(const char *text)
#define ASSERT_HOST_MSG(x, msg...)
int SpanUTF8NotWhitespace(const char *text)
void set_seed(uinT64 seed)
#define TLOG_FATAL(msg...)
bool encodable_string(const char *str, int *first_bad_position) const
Pix * DegradeImage(Pix *input, int exposure, TRand *randomizer, float *rotation)
void ExtractFontProperties(const string &utf8_text, StringRenderer *render, const string &output_base)