/********************************************************************** * File: ocrclass.h * Description: Class definitions and constants for the OCR API. * Author: Hewlett-Packard Co * * (C) Copyright 1996, Hewlett-Packard Co. ** 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. * **********************************************************************/ /********************************************************************** * This file contains typedefs for all the structures used by * the HP OCR interface. * The structures are designed to allow them to be used with any * structure alignment up to 8. **********************************************************************/ #ifndef CCUTIL_OCRCLASS_H_ #define CCUTIL_OCRCLASS_H_ #include #include #ifdef _WIN32 #include // for timeval #endif /********************************************************************** * EANYCODE_CHAR * Description of a single character. The character code is defined by * the character set of the current font. * Output text is sent as an array of these structures. * Spaces and line endings in the output are represented in the * structures of the surrounding characters. They are not directly * represented as characters. * The first character in a word has a positive value of blanks. * Missing information should be set to the defaults in the comments. * If word bounds are known, but not character bounds, then the top and * bottom of each character should be those of the word. The left of the * first and right of the last char in each word should be set. All other * lefts and rights should be set to -1. * If set, the values of right and bottom are left+width and top+height. * Most of the members come directly from the parameters to ocr_append_char. * The formatting member uses the enhancement parameter and combines the * line direction stuff into the top 3 bits. * The coding is 0=RL char, 1=LR char, 2=DR NL, 3=UL NL, 4=DR Para, * 5=UL Para, 6=TB char, 7=BT char. API users do not need to know what * the coding is, only that it is backwards compatible with the previous * version. **********************************************************************/ typedef struct { /*single character */ // It should be noted that the format for char_code for version 2.0 and beyond // is UTF8 which means that ASCII characters will come out as one structure // but other characters will be returned in two or more instances of this // structure with a single byte of the UTF8 code in each, but each will have // the same bounding box. Programs which want to handle languagues with // different characters sets will need to handle extended characters // appropriately, but *all* code needs to be prepared to receive UTF8 coded // characters for characters such as bullet and fancy quotes. uint16_t char_code; /*character itself */ int16_t left; /*of char (-1) */ int16_t right; /*of char (-1) */ int16_t top; /*of char (-1) */ int16_t bottom; /*of char (-1) */ int16_t font_index; /*what font (0) */ uint8_t confidence; /*0=perfect, 100=reject (0/100) */ uint8_t point_size; /*of char, 72=i inch, (10) */ int8_t blanks; /*no of spaces before this char (1) */ uint8_t formatting; /*char formatting (0) */ } EANYCODE_CHAR; /*single character */ /********************************************************************** * ETEXT_DESC * Description of the output of the OCR engine. * This structure is used as both a progress monitor and the final * output header, since it needs to be a valid progress monitor while * the OCR engine is storing its output to shared memory. * During progress, all the buffer info is -1. * Progress starts at 0 and increases to 100 during OCR. No other constraint. * Additionally the progress callback contains the bounding box of the word that * is currently being processed. * Every progress callback, the OCR engine must set ocr_alive to 1. * The HP side will set ocr_alive to 0. Repeated failure to reset * to 1 indicates that the OCR engine is dead. * If the cancel function is not null then it is called with the number of * user words found. If it returns true then operation is cancelled. **********************************************************************/ class ETEXT_DESC; using CANCEL_FUNC = bool (*)(void*, int); using PROGRESS_FUNC = bool (*)(int, int, int, int, int); using PROGRESS_FUNC2 = bool (*)(ETEXT_DESC*, int, int, int, int); class ETEXT_DESC { // output header public: int16_t count{0}; /// chars in this buffer(0) int16_t progress{0}; /// percent complete increasing (0-100) /** Progress monitor covers word recognition and it does not cover layout * analysis. * See Ray comment in https://github.com/tesseract-ocr/tesseract/pull/27 */ int8_t more_to_come{0}; /// true if not last volatile int8_t ocr_alive{0}; /// ocr sets to 1, HP 0 int8_t err_code{0}; /// for errcode use CANCEL_FUNC cancel{nullptr}; /// returns true to cancel PROGRESS_FUNC progress_callback{ nullptr}; /// called whenever progress increases PROGRESS_FUNC2 progress_callback2; /// monitor-aware progress callback void* cancel_this{nullptr}; /// this or other data for cancel struct timeval end_time; /// Time to stop. Expected to be set only /// by call to set_deadline_msecs(). EANYCODE_CHAR text[1]{}; /// character data ETEXT_DESC() : progress_callback2(&default_progress_func) { auto chrono_end_time = std::chrono::time_point(); timePointToTimeval(chrono_end_time, &end_time); } // Sets the end time to be deadline_msecs milliseconds from now. void set_deadline_msecs(int32_t deadline_msecs) { if (deadline_msecs > 0) { auto chrono_end_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(deadline_msecs); timePointToTimeval(chrono_end_time, &end_time); } } // Returns false if we've not passed the end_time, or have not set a deadline. bool deadline_exceeded() const { if (end_time.tv_sec == 0 && end_time.tv_usec == 0) return false; auto chrono_now = std::chrono::steady_clock::now(); struct timeval now; timePointToTimeval(chrono_now, &now); return (now.tv_sec > end_time.tv_sec || (now.tv_sec == end_time.tv_sec && now.tv_usec > end_time.tv_usec)); } private: static void timePointToTimeval( std::chrono::steady_clock::time_point chrono_point, struct timeval* tv) { auto millisecs = std::chrono::duration_cast( chrono_point.time_since_epoch()); tv->tv_sec = millisecs.count() / 1000; tv->tv_usec = (millisecs.count() % 1000) * 1000; } static bool default_progress_func(ETEXT_DESC* ths, int left, int right, int top, int bottom) { if (ths->progress_callback != nullptr) { return (*(ths->progress_callback))(ths->progress, left, right, top, bottom); } return true; } }; #endif // CCUTIL_OCRCLASS_H_