/********************************************************************** * File: char_samp_enum.cpp * Description: Implementation of a Character Set Class * Author: Ahmad Abdulkader * Created: 2007 * * (C) Copyright 2008, Google Inc. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/ #include #include "char_set.h" #include "cube_utils.h" #include "tessdatamanager.h" namespace tesseract { CharSet::CharSet() { class_cnt_ = 0; class_strings_ = NULL; unicharset_map_ = NULL; init_ = false; // init hash table memset(hash_bin_size_, 0, sizeof(hash_bin_size_)); } CharSet::~CharSet() { if (class_strings_ != NULL) { for (int cls = 0; cls < class_cnt_; cls++) { if (class_strings_[cls] != NULL) { delete class_strings_[cls]; } } delete []class_strings_; class_strings_ = NULL; } delete []unicharset_map_; } // Creates CharSet object by reading the unicharset from the // TessDatamanager, and mapping Cube's unicharset to Tesseract's if // they differ. CharSet *CharSet::Create(TessdataManager *tessdata_manager, UNICHARSET *tess_unicharset) { CharSet *char_set = new CharSet(); if (char_set == NULL) { return NULL; } // First look for Cube's unicharset; if not there, use tesseract's bool cube_unicharset_exists; if (!(cube_unicharset_exists = tessdata_manager->SeekToStart(TESSDATA_CUBE_UNICHARSET)) && !tessdata_manager->SeekToStart(TESSDATA_UNICHARSET)) { fprintf(stderr, "Cube ERROR (CharSet::Create): could not find " "either cube or tesseract unicharset\n"); return NULL; } FILE *charset_fp = tessdata_manager->GetDataFilePtr(); if (!charset_fp) { fprintf(stderr, "Cube ERROR (CharSet::Create): could not load " "a unicharset\n"); return NULL; } // If we found a cube unicharset separate from tesseract's, load it and // map its unichars to tesseract's; if only one unicharset exists, // just load it. bool loaded; if (cube_unicharset_exists) { char_set->cube_unicharset_.load_from_file(charset_fp); loaded = tessdata_manager->SeekToStart(TESSDATA_CUBE_UNICHARSET); loaded = loaded && char_set->LoadSupportedCharList( tessdata_manager->GetDataFilePtr(), tess_unicharset); char_set->unicharset_ = &char_set->cube_unicharset_; } else { loaded = char_set->LoadSupportedCharList(charset_fp, NULL); char_set->unicharset_ = tess_unicharset; } if (!loaded) { delete char_set; return NULL; } char_set->init_ = true; return char_set; } // Load the list of supported chars from the given data file pointer. bool CharSet::LoadSupportedCharList(FILE *fp, UNICHARSET *tess_unicharset) { if (init_) return true; char str_line[256]; // init hash table memset(hash_bin_size_, 0, sizeof(hash_bin_size_)); // read the char count if (fgets(str_line, sizeof(str_line), fp) == NULL) { fprintf(stderr, "Cube ERROR (CharSet::InitMemory): could not " "read char count.\n"); return false; } class_cnt_ = atoi(str_line); if (class_cnt_ < 2) { fprintf(stderr, "Cube ERROR (CharSet::InitMemory): invalid " "class count: %d\n", class_cnt_); return false; } // memory for class strings class_strings_ = new string_32*[class_cnt_]; if (class_strings_ == NULL) { fprintf(stderr, "Cube ERROR (CharSet::InitMemory): could not " "allocate memory for class strings.\n"); return false; } // memory for unicharset map if (tess_unicharset) { unicharset_map_ = new int[class_cnt_]; if (unicharset_map_ == NULL) { fprintf(stderr, "Cube ERROR (CharSet::InitMemory): could not " "allocate memory for unicharset map.\n"); return false; } } // Read in character strings and add to hash table for (int class_id = 0; class_id < class_cnt_; class_id++) { // Read the class string if (fgets(str_line, sizeof(str_line), fp) == NULL) { fprintf(stderr, "Cube ERROR (CharSet::ReadAndHashStrings): " "could not read class string with class_id=%d.\n", class_id); return false; } // Terminate at space if any char *p = strchr(str_line, ' '); if (p != NULL) *p = '\0'; // Convert to UTF32 and store string_32 str32; // Convert NULL to a space if (strcmp(str_line, "NULL") == 0) { strcpy(str_line, " "); } CubeUtils::UTF8ToUTF32(str_line, &str32); class_strings_[class_id] = new string_32(str32); if (class_strings_[class_id] == NULL) { fprintf(stderr, "Cube ERROR (CharSet::ReadAndHashStrings): could not " "allocate memory for class string with class_id=%d.\n", class_id); return false; } // Add to hash-table int hash_val = Hash(reinterpret_cast(str32.c_str())); if (hash_bin_size_[hash_val] >= kMaxHashSize) { fprintf(stderr, "Cube ERROR (CharSet::LoadSupportedCharList): hash " "table is full.\n"); return false; } hash_bins_[hash_val][hash_bin_size_[hash_val]++] = class_id; if (tess_unicharset != NULL) { // Add class id to unicharset map UNICHAR_ID tess_id = tess_unicharset->unichar_to_id(str_line); if (tess_id == INVALID_UNICHAR_ID) { tess_unicharset->unichar_insert(str_line); tess_id = tess_unicharset->unichar_to_id(str_line); } ASSERT_HOST(tess_id != INVALID_UNICHAR_ID); unicharset_map_[class_id] = tess_id; } } return true; } } // tesseract