22 #include "config_auto.h" 27 #if defined(__MINGW32__) 33 #include "allheaders.h" 56 int* max_x,
int* max_y) {
59 for (
int f = 0; f < features.
size(); ++f) {
60 if (features[f].x_ > *max_x) *max_x = features[f].x_;
61 if (features[f].y_ > *max_y) *max_y = features[f].y_;
68 #ifndef GRAPHICS_DISABLED 69 for (
int f = 0; f < features.
size(); ++f) {
70 FCOORD pos(features[f].x_, features[f].y_);
84 if (fwrite(&x_,
sizeof(x_), 1, fp) != 1)
return false;
85 if (fwrite(&y_,
sizeof(y_), 1, fp) != 1)
return false;
86 if (fwrite(&dir_,
sizeof(dir_), 1, fp) != 1)
return false;
92 if (fread(&x_,
sizeof(x_), 1, fp) != 1)
return false;
94 if (fread(&y_,
sizeof(y_), 1, fp) != 1)
return false;
95 if (fread(&dir_,
sizeof(dir_), 1, fp) != 1)
return false;
102 for (
int i = 0; i < word_features.
size(); ++i) {
104 f.
x = word_features[i].x();
105 f.
y = word_features[i].y();
106 f.
dir = word_features[i].dir();
118 if (x_diff == 0)
return f1->
y - f2->
y;
126 : page_number_(0), vertical_text_(vertical) {
135 const char* imagedata,
int imagedatasize,
136 const char* truth_text,
const char*
box_text) {
138 image_data->imagefilename_ = name;
140 image_data->language_ =
lang;
143 memcpy(&image_data->image_data_[0], imagedata, imagedatasize);
144 if (!image_data->
AddBoxes(box_text)) {
145 if (truth_text == NULL || truth_text[0] ==
'\0') {
146 tprintf(
"Error: No text corresponding to page %d from image %s!\n",
151 image_data->transcription_ = truth_text;
153 image_data->box_texts_.
push_back(truth_text);
156 }
else if (truth_text != NULL && truth_text[0] !=
'\0' &&
157 image_data->transcription_ != truth_text) {
159 image_data->transcription_ = truth_text;
166 if (!imagefilename_.
Serialize(fp))
return false;
167 if (fp->
FWrite(&page_number_,
sizeof(page_number_), 1) != 1)
return false;
168 if (!image_data_.
Serialize(fp))
return false;
169 if (!language_.
Serialize(fp))
return false;
170 if (!transcription_.
Serialize(fp))
return false;
174 inT8 vertical = vertical_text_;
175 if (fp->
FWrite(&vertical,
sizeof(vertical), 1) != 1)
return false;
183 if (fp->
FReadEndian(&page_number_,
sizeof(page_number_), 1) != 1)
192 if (fp->
FRead(&vertical,
sizeof(vertical), 1) != 1)
return false;
193 vertical_text_ = vertical != 0;
201 if (fp->
FRead(&page_number,
sizeof(page_number), 1) != 1)
return false;
208 return fp->
FRead(&vertical,
sizeof(vertical), 1) == 1;
213 SetPixInternal(pix, &image_data_);
218 return GetPixInternal(image_data_);
228 int* scaled_width,
int* scaled_height,
231 int input_height = 0;
234 input_width = pixGetWidth(src_pix);
235 input_height = pixGetHeight(src_pix);
236 if (target_height == 0) {
237 target_height =
MIN(input_height, max_height);
239 float im_factor =
static_cast<float>(target_height) / input_height;
240 if (scaled_width != NULL)
242 if (scaled_height != NULL)
243 *scaled_height = target_height;
245 Pix* pix = pixScale(src_pix, im_factor, im_factor);
247 tprintf(
"Scaling pix of size %d, %d by factor %g made null pix!!\n",
248 input_width, input_height, im_factor);
250 if (scaled_width != NULL) *scaled_width = pixGetWidth(pix);
251 if (scaled_height != NULL) *scaled_height = pixGetHeight(pix);
252 pixDestroy(&src_pix);
256 for (
int b = 0; b < boxes_.
size(); ++b) {
257 TBOX box = boxes_[b];
258 box.
scale(im_factor);
261 if (boxes->
empty()) {
263 TBOX box(0, 0, im_factor * input_width, target_height);
267 if (scale_factor != NULL) *scale_factor = im_factor;
272 return image_data_.
size();
277 #ifndef GRAPHICS_DISABLED 278 const int kTextSize = 64;
281 if (pix == NULL)
return;
282 int width = pixGetWidth(pix);
283 int height = pixGetHeight(pix);
285 2 * (width + 2 * kTextSize),
286 2 * (height + 4 * kTextSize),
287 width + 10, height + 3 * kTextSize,
true);
288 win->
Image(pix, 0, height - 1);
293 int text_size = kTextSize;
294 if (!boxes_.
empty() && boxes_[0].height() * 2 < text_size)
295 text_size = boxes_[0].height() * 2;
297 if (!boxes_.
empty()) {
298 for (
int b = 0; b < boxes_.
size(); ++b) {
300 win->
Text(boxes_[b].left(), height + kTextSize, box_texts_[b].
string());
305 win->
Text(0, height + kTextSize * 2, transcription_.
string());
318 for (
int i = 0; i < box_pages.
size(); ++i) {
319 if (page_number_ >= 0 && box_pages[i] != page_number_)
continue;
320 transcription_ += texts[i];
330 pixWriteMem(&data, &size, pix, IFF_PNG);
333 memcpy(&(*image_data)[0], data, size);
340 if (!image_data.
empty()) {
342 const unsigned char* u_data =
343 reinterpret_cast<const unsigned char*
>(&image_data[0]);
344 pix = pixReadMem(u_data, image_data.
size());
352 if (box_text != NULL && box_text[0] !=
'\0') {
357 true, &boxes, &texts, NULL,
362 tprintf(
"Error: No boxes for page %d from image %s!\n",
363 page_number_, imagefilename_.
string());
372 document_data->ReCachePages();
377 : document_name_(name),
394 pages_offset_ = start_page;
395 return ReCachePages();
405 max_memory_ = max_memory;
414 if (!pages_.Serialize(&fp) || !fp.
CloseWrite(filename, writer)) {
415 tprintf(
"Serialize failed: %s\n", filename);
424 return pages_.Serialize(&fp);
430 pages_.push_back(page);
440 if (pages_offset_ == index)
return;
441 pages_offset_ = index;
453 bool needs_loading = pages_offset_ != index;
458 #if defined(__MINGW32__) 461 std::this_thread::sleep_for(std::chrono::seconds(1));
473 if (num_pages == 0 || index < 0) {
478 index =
Modulo(index, num_pages);
479 if (pages_offset_ <= index && index < pages_offset_ + pages_.size()) {
480 *page = pages_[index - pages_offset_];
496 tprintf(
"Unloaded document %s, saving %" PRId64
" memory\n",
497 document_name_.
string(), memory_saved);
507 int num_pages = pages_.size();
509 for (
int i = 0; i < num_pages; ++i) {
510 int src = random.
IntRand() % num_pages;
511 int dest = random.
IntRand() % num_pages;
512 std::swap(pages_[src], pages_[dest]);
518 bool DocumentData::ReCachePages() {
523 int loaded_pages = 0;
526 if (!fp.
Open(document_name_, reader_) ||
529 tprintf(
"Deserialize header failed: %s\n", document_name_.
string());
532 pages_offset_ %= loaded_pages;
536 for (page = 0; page < loaded_pages; ++page) {
537 if (page < pages_offset_ ||
538 (max_memory_ > 0 &&
memory_used() > max_memory_)) {
540 tprintf(
"Deserializeskip failed\n");
544 if (!pages_.DeSerializeElement(&fp))
break;
553 if (page < loaded_pages) {
554 tprintf(
"Deserialize failed: %s read %d/%d pages\n",
555 document_name_.
string(), page, loaded_pages);
558 tprintf(
"Loaded %d/%d pages (%d-%d) of document %s\n", pages_.size(),
559 loaded_pages, pages_offset_ + 1, pages_offset_ + pages_.size(),
562 set_total_pages(loaded_pages);
563 return !pages_.empty();
568 : num_pages_per_doc_(0), max_memory_(max_memory) {}
576 cache_strategy_ = cache_strategy;
577 inT64 fair_share_memory = 0;
582 fair_share_memory = max_memory_ / filenames.
size();
583 for (
int arg = 0; arg < filenames.
size(); ++arg) {
589 if (!documents_.empty()) {
592 tprintf(
"Load of page 0 failed!\n");
599 documents_.push_back(data);
605 for (
int i = 0; i < documents_.size(); ++i) {
606 if (documents_[i]->document_name() == document_name)
607 return documents_[i];
618 if (num_pages_per_doc_ == 0) GetPageSequential(0);
619 return num_pages_per_doc_ * documents_.size();
622 int num_docs = documents_.size();
623 for (
int d = 0; d < num_docs; ++d) {
625 documents_[d]->GetPage(0);
626 total_pages += documents_[d]->NumPages();
634 const ImageData* DocumentCache::GetPageRoundRobin(
int serial) {
635 int num_docs = documents_.size();
636 int doc_index = serial % num_docs;
637 const ImageData* doc = documents_[doc_index]->GetPage(serial / num_docs);
638 for (
int offset = 1; offset <=
kMaxReadAhead && offset < num_docs; ++offset) {
639 doc_index = (serial + offset) % num_docs;
640 int page = (serial + offset) / num_docs;
641 documents_[doc_index]->LoadPageInBackground(page);
649 const ImageData* DocumentCache::GetPageSequential(
int serial) {
650 int num_docs = documents_.size();
652 if (num_pages_per_doc_ == 0) {
654 documents_[0]->GetPage(0);
655 num_pages_per_doc_ = documents_[0]->NumPages();
656 if (num_pages_per_doc_ == 0) {
657 tprintf(
"First document cannot be empty!!\n");
661 if (serial / num_pages_per_doc_ % num_docs > 0) documents_[0]->UnCache();
663 int doc_index = serial / num_pages_per_doc_ % num_docs;
665 documents_[doc_index]->GetPage(serial % num_pages_per_doc_);
668 inT64 total_memory = 0;
669 for (
int d = 0; d < num_docs; ++d) {
670 total_memory += documents_[d]->memory_used();
672 if (total_memory >= max_memory_) {
678 int num_in_front = CountNeighbourDocs(doc_index, 1);
679 for (
int offset = num_in_front - 2;
680 offset > 1 && total_memory >= max_memory_; --offset) {
681 int next_index = (doc_index + offset) % num_docs;
682 total_memory -= documents_[next_index]->UnCache();
687 int num_behind = CountNeighbourDocs(doc_index, -1);
688 for (
int offset = num_behind; offset < 0 && total_memory >= max_memory_;
690 int next_index = (doc_index + offset + num_docs) % num_docs;
691 total_memory -= documents_[next_index]->UnCache();
694 int next_index = (doc_index + 1) % num_docs;
695 if (!documents_[next_index]->IsCached() && total_memory < max_memory_) {
696 documents_[next_index]->LoadPageInBackground(0);
703 int DocumentCache::CountNeighbourDocs(
int index,
int dir) {
704 int num_docs = documents_.size();
705 for (
int offset = dir; abs(offset) < num_docs; offset += dir) {
706 int offset_index = (index + offset + num_docs) % num_docs;
707 if (!documents_[offset_index]->IsCached())
return offset - dir;
static bool DeSerializeSize(TFile *fp, inT32 *size)
int FWrite(const void *buffer, int size, int count)
bool IsPageAvailable(int index, ImageData **page)
static bool SkipDeSerialize(tesseract::TFile *fp)
void Lock()
Locks on a mutex.
void DrawTo(int x, int y)
static int SortByXBucket(const void *, const void *)
void Unlock()
Unlocks on a mutex.
bool AddToCache(DocumentData *data)
void OpenWrite(GenericVector< char > *data)
void scale(const float f)
const STRING & imagefilename() const
bool LoadDocument(const char *filename, int start_page, inT64 max_memory, FileReader reader)
bool LoadDocuments(const GenericVector< STRING > &filenames, CachingStrategy cache_strategy, FileReader reader)
const ImageData * GetPageBySerial(int serial)
void resize_no_init(int size)
void set_page_number(int num)
bool SaveToBuffer(GenericVector< char > *buffer)
void set_imagefilename(const STRING &name)
inT64 memory_used() const
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
void set_seed(uinT64 seed)
void AddBoxes(const GenericVector< TBOX > &boxes, const GenericVector< STRING > &texts, const GenericVector< int > &box_pages)
static void Draw(const GenericVector< WordFeature > &features, ScrollView *window)
const GenericVector< char > & image_data() const
bool(* FileWriter)(const GenericVector< char > &data, const STRING &filename)
static bool SkipDeSerialize(tesseract::TFile *fp)
bool ReadMemBoxes(int target_page, bool skip_blanks, const char *box_data, bool continue_on_failure, GenericVector< TBOX > *boxes, GenericVector< STRING > *texts, GenericVector< STRING > *box_texts, GenericVector< int > *pages)
const char * string() const
const STRING & box_text(int index) const
Pix * PreScale(int target_height, int max_height, float *scale_factor, int *scaled_width, int *scaled_height, GenericVector< TBOX > *boxes) const
void Text(int x, int y, const char *mystring)
DocumentCache(inT64 max_memory)
bool DeSerializeClasses(bool swap, FILE *fp)
bool Serialize(FILE *fp) const
const ImageData * GetPage(int index)
bool Serialize(FILE *fp) const
bool Open(const STRING &filename, FileReader reader)
static void FromWordFeatures(const GenericVector< WordFeature > &word_features, GenericVector< FloatWordFeature > *float_features)
void LoadPageInBackground(int index)
bool Serialize(TFile *fp) const
char window_wait(ScrollView *win)
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
void SetCursor(int x, int y)
bool DeSerialize(bool swap, FILE *fp)
bool DeSerialize(bool swap, FILE *fp)
void from_direction(uinT8 direction)
int FReadEndian(void *buffer, int size, int count)
bool DeSerialize(bool swap, FILE *fp)
void ReverseN(void *ptr, int num_bytes)
DocumentData(const STRING &name)
static ImageData * Build(const char *name, int page_number, const char *lang, const char *imagedata, int imagedatasize, const char *truth_text, const char *box_text)
bool CloseWrite(const STRING &filename, FileWriter writer)
bool DeSerialize(TFile *fp)
bool SaveDocument(const char *filename, FileWriter writer)
const GenericVector< TBOX > & boxes() const
friend void * ReCachePagesFunc(void *data)
bool Serialize(FILE *fp) const
bool(* FileReader)(const STRING &filename, GenericVector< char > *data)
DocumentData * FindDocument(const STRING &document_name) const
bool SerializeClasses(FILE *fp) const
int IntCastRounded(double x)
void Image(struct Pix *image, int x_pos, int y_pos)
int FRead(void *buffer, int size, int count)
void AddPageToDocument(ImageData *page)
void * ReCachePagesFunc(void *data)
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
static void ComputeSize(const GenericVector< WordFeature > &features, int *max_x, int *max_y)
void SetDocument(const char *filename, inT64 max_memory, FileReader reader)