23 #include "allheaders.h"
42 int* max_x,
int* max_y) {
45 for (
int f = 0; f < features.
size(); ++f) {
46 if (features[f].x_ > *max_x) *max_x = features[f].x_;
47 if (features[f].y_ > *max_y) *max_y = features[f].y_;
54 #ifndef GRAPHICS_DISABLED
55 for (
int f = 0; f < features.
size(); ++f) {
56 FCOORD pos(features[f].x_, features[f].y_);
70 if (fwrite(&x_,
sizeof(x_), 1, fp) != 1)
return false;
71 if (fwrite(&y_,
sizeof(y_), 1, fp) != 1)
return false;
72 if (fwrite(&dir_,
sizeof(dir_), 1, fp) != 1)
return false;
78 if (fread(&x_,
sizeof(x_), 1, fp) != 1)
return false;
80 if (fread(&y_,
sizeof(y_), 1, fp) != 1)
return false;
81 if (fread(&dir_,
sizeof(dir_), 1, fp) != 1)
return false;
88 for (
int i = 0; i < word_features.
size(); ++i) {
90 f.
x = word_features[i].x();
91 f.
y = word_features[i].y();
92 f.
dir = word_features[i].dir();
104 if (x_diff == 0)
return f1->
y - f2->
y;
112 : page_number_(0), vertical_text_(vertical) {
121 const char* imagedata,
int imagedatasize,
122 const char* truth_text,
const char* box_text) {
124 image_data->imagefilename_ =
name;
126 image_data->language_ =
lang;
129 memcpy(&image_data->image_data_[0], imagedata, imagedatasize);
130 if (!image_data->
AddBoxes(box_text)) {
131 if (truth_text ==
NULL || truth_text[0] ==
'\0') {
132 tprintf(
"Error: No text corresponding to page %d from image %s!\n",
137 image_data->transcription_ = truth_text;
139 image_data->box_texts_.
push_back(truth_text);
142 }
else if (truth_text !=
NULL && truth_text[0] !=
'\0' &&
143 image_data->transcription_ != truth_text) {
145 image_data->transcription_ = truth_text;
152 if (!imagefilename_.
Serialize(fp))
return false;
153 if (fp->
FWrite(&page_number_,
sizeof(page_number_), 1) != 1)
return false;
154 if (!image_data_.
Serialize(fp))
return false;
155 if (!transcription_.
Serialize(fp))
return false;
159 inT8 vertical = vertical_text_;
160 if (fp->
FWrite(&vertical,
sizeof(vertical), 1) != 1)
return false;
167 if (!imagefilename_.
DeSerialize(swap, fp))
return false;
168 if (fp->
FRead(&page_number_,
sizeof(page_number_), 1) != 1)
return false;
169 if (swap)
ReverseN(&page_number_,
sizeof(page_number_));
170 if (!image_data_.
DeSerialize(swap, fp))
return false;
171 if (!transcription_.
DeSerialize(swap, fp))
return false;
176 if (fp->
FRead(&vertical,
sizeof(vertical), 1) != 1)
return false;
177 vertical_text_ = vertical != 0;
183 SetPixInternal(pix, &image_data_);
188 return GetPixInternal(image_data_);
197 int* scaled_width,
int* scaled_height,
200 int input_height = 0;
203 input_width = pixGetWidth(src_pix);
204 input_height = pixGetHeight(src_pix);
205 if (target_height == 0)
206 target_height = input_height;
207 float im_factor =
static_cast<float>(target_height) / input_height;
208 if (scaled_width !=
NULL)
210 if (scaled_height !=
NULL)
211 *scaled_height = target_height;
215 *pix = pixScale(src_pix, im_factor, im_factor);
217 tprintf(
"Scaling pix of size %d, %d by factor %g made null pix!!\n",
218 input_width, input_height, im_factor);
220 if (scaled_width !=
NULL)
221 *scaled_width = pixGetWidth(*pix);
222 if (scaled_height !=
NULL)
223 *scaled_height = pixGetHeight(*pix);
225 pixDestroy(&src_pix);
229 for (
int b = 0; b < boxes_.
size(); ++b) {
230 TBOX box = boxes_[b];
231 box.
scale(im_factor);
234 if (boxes->
empty()) {
236 TBOX box(0, 0, im_factor * input_width, target_height);
244 return image_data_.
size();
249 #ifndef GRAPHICS_DISABLED
250 const int kTextSize = 64;
253 if (pix ==
NULL)
return;
254 int width = pixGetWidth(pix);
255 int height = pixGetHeight(pix);
257 2 * (width + 2 * kTextSize),
258 2 * (height + 4 * kTextSize),
259 width + 10, height + 3 * kTextSize,
true);
260 win->
Image(pix, 0, height - 1);
266 for (
int b = 0; b < boxes_.
size(); ++b) {
268 win->
Text(boxes_[b].left(), height + kTextSize, box_texts_[b].
string());
269 TBOX scaled(boxes_[b]);
270 scaled.
scale(256.0 / height);
275 win->
Text(0, height + kTextSize * 2, transcription_.
string());
289 for (
int i = 0; i < box_pages.
size(); ++i) {
290 if (page_number_ >= 0 && box_pages[i] != page_number_)
continue;
291 transcription_ += texts[i];
301 pixWriteMem(&data, &size, pix, IFF_PNG);
304 memcpy(&(*image_data)[0], data, size);
311 if (!image_data.
empty()) {
313 const unsigned char* u_data =
314 reinterpret_cast<const unsigned char*
>(&image_data[0]);
315 pix = pixReadMem(u_data, image_data.
size());
323 if (box_text !=
NULL && box_text[0] !=
'\0') {
328 &texts,
NULL, &box_pages)) {
332 tprintf(
"Error: No boxes for page %d from image %s!\n",
333 page_number_, imagefilename_.
string());
340 : document_name_(name), pages_offset_(0), total_pages_(0),
341 memory_used_(0), max_memory_(0), reader_(
NULL) {}
348 int start_page,
inT64 max_memory,
352 pages_offset_ = start_page;
353 max_memory_ = max_memory;
355 return ReCachePages();
362 if (!pages_.Serialize(&fp) || !fp.
CloseWrite(filename, writer)) {
363 tprintf(
"Serialize failed: %s\n", filename);
371 return pages_.Serialize(&fp);
377 index =
Modulo(index, total_pages_);
378 if (index < pages_offset_ || index >= pages_offset_ + pages_.size()) {
379 pages_offset_ = index;
380 if (!ReCachePages())
return NULL;
382 return pages_[index - pages_offset_];
386 bool DocumentData::ReCachePages() {
389 if (!fp.
Open(document_name_, reader_))
return false;
391 if (!pages_.DeSerialize(
false, &fp)) {
392 tprintf(
"Deserialize failed: %s\n", document_name_.
string());
396 total_pages_ = pages_.size();
397 pages_offset_ %= total_pages_;
400 for (page = 0; page < pages_.size(); ++page) {
401 if (page < pages_offset_) {
405 ImageData* image_data = pages_[page];
406 if (max_memory_ > 0 && page > pages_offset_ &&
407 memory_used_ + image_data->MemoryUsed() > max_memory_)
409 if (image_data->imagefilename().length() == 0) {
410 image_data->set_imagefilename(document_name_);
411 image_data->set_page_number(page);
413 image_data->set_language(lang_);
414 memory_used_ += image_data->MemoryUsed();
415 if (pages_offset_ != 0) {
416 pages_[page - pages_offset_] = image_data;
421 pages_.truncate(page - pages_offset_);
422 tprintf(
"Loaded %d/%d pages (%d-%d) of document %s\n",
423 pages_.size(), total_pages_, pages_offset_,
424 pages_offset_ + pages_.size(), document_name_.
string());
425 return !pages_.empty();
430 pages_.push_back(page);
436 : total_pages_(0), memory_used_(0), max_memory_(max_memory) {}
443 inT64 fair_share_memory = max_memory_ / filenames.
size();
444 for (
int arg = 0; arg < filenames.
size(); ++arg) {
448 fair_share_memory, reader)) {
455 tprintf(
"Loaded %d pages, total %gMB\n",
456 total_pages_, memory_used_ / 1048576.0);
457 return total_pages_ > 0;
463 memory_used_ += new_memory;
464 documents_.push_back(data);
468 while (memory_used_ >= max_memory_ && max_memory_ > 0) {
469 tprintf(
"Memory used=%lld vs max=%lld, discarding doc of size %lld\n",
470 memory_used_ , max_memory_, documents_[0]->memory_used());
471 memory_used_ -= documents_[0]->memory_used();
472 total_pages_ -= documents_[0]->NumPages();
473 documents_.remove(0);
480 for (
int i = 0; i < documents_.size(); ++i) {
481 if (documents_[i]->document_name() == document_name)
482 return documents_[i];
490 int document_index = serial % documents_.size();
491 return documents_[document_index]->GetPage(serial / documents_.size());
bool DeSerialize(bool swap, FILE *fp)
bool DeSerialize(bool swap, FILE *fp)
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 DeSerializeClasses(bool swap, FILE *fp)
bool DeSerialize(bool swap, TFile *fp)
static void ComputeSize(const GenericVector< WordFeature > &features, int *max_x, int *max_y)
bool(* FileWriter)(const GenericVector< char > &data, const STRING &filename)
void Text(int x, int y, const char *mystring)
void DrawTo(int x, int y)
bool CloseWrite(const STRING &filename, FileWriter writer)
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
float PreScale(int target_height, Pix **pix, int *scaled_width, int *scaled_height, GenericVector< TBOX > *boxes) const
void Image(struct Pix *image, int x_pos, int y_pos)
bool Serialize(FILE *fp) const
bool(* FileReader)(const STRING &filename, GenericVector< char > *data)
const ImageData * GetPageBySerial(int serial)
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
void AddBoxes(const GenericVector< TBOX > &boxes, const GenericVector< STRING > &texts, const GenericVector< int > &box_pages)
const ImageData * GetPage(int index)
bool Serialize(FILE *fp) const
bool SerializeClasses(FILE *fp) const
bool ReadMemBoxes(int target_page, bool skip_blanks, const char *box_data, GenericVector< TBOX > *boxes, GenericVector< STRING > *texts, GenericVector< STRING > *box_texts, GenericVector< int > *pages)
bool SaveDocument(const char *filename, FileWriter writer)
void SetCursor(int x, int y)
bool Serialize(FILE *fp) const
void init_to_size(int size, T t)
bool DeSerialize(bool swap, FILE *fp)
bool Open(const STRING &filename, FileReader reader)
DocumentCache(inT64 max_memory)
bool LoadDocuments(const GenericVector< STRING > &filenames, const char *lang, FileReader reader)
DocumentData * FindDocument(const STRING &document_name) const
char window_wait(ScrollView *win)
void AddPageToDocument(ImageData *page)
void ReverseN(void *ptr, int num_bytes)
int FWrite(const void *buffer, int size, int count)
void from_direction(uinT8 direction)
static int SortByXBucket(const void *, const void *)
int IntCastRounded(double x)
const GenericVector< TBOX > & boxes() const
bool AddToCache(DocumentData *data)
DocumentData(const STRING &name)
void OpenWrite(GenericVector< char > *data)
inT64 memory_used() const
static void Draw(const GenericVector< WordFeature > &features, ScrollView *window)
const GenericVector< char > & image_data() const
const char * string() const
bool SaveToBuffer(GenericVector< char > *buffer)
bool LoadDocument(const char *filename, const char *lang, int start_page, inT64 max_memory, FileReader reader)
bool Serialize(TFile *fp) const
void scale(const float f)
int FRead(void *buffer, int size, int count)
static void FromWordFeatures(const GenericVector< WordFeature > &word_features, GenericVector< FloatWordFeature > *float_features)
void plot(ScrollView *fd) const