diff --git a/include/tesseract/renderer.h b/include/tesseract/renderer.h index 6f40523335..954f167367 100644 --- a/include/tesseract/renderer.h +++ b/include/tesseract/renderer.h @@ -106,6 +106,22 @@ class TESS_API TessResultRenderer { return imagenum_; } + /** + * Allow the caller to choose alternate image to render with the extracted text. + * It must be called after BeginDocument and before AddImage methods. + */ + void SetRenderingImage(Pix *rendering_image) { + rendering_image_ = rendering_image; + } + + /** + * Allow the caller to specify the target rendering resolution. + * If not set, rendering_dpi api params will be used. + */ + void SetRenderingResolution(int rendering_dpi) { + rendering_dpi_ = rendering_dpi; + } + protected: /** * Called by concrete classes. @@ -139,6 +155,16 @@ class TESS_API TessResultRenderer { // This method will grow the output buffer if needed. void AppendData(const char *s, int len); + // Renderers can call this to get the actual image to render with extracted text. + // This method returns: + // - the rendering image set by the caller or + // - the input image scaled to the rendering_dpi field if defined or + // - the input image from the api otherwise + Pix* GetRenderingImage(TessBaseAPI *api); + + // Resolution of the rendering image either set manually by the caller or with the rendering_dpi api parameter. + int GetRenderingResolution(TessBaseAPI *api); + private: TessResultRenderer *next_; // Can link multiple renderers together FILE *fout_; // output file pointer @@ -146,6 +172,8 @@ class TESS_API TessResultRenderer { std::string title_; // title of document being rendered int imagenum_; // index of last image added bool happy_; // I get grumpy when the disk fills up, etc. + Pix *rendering_image_; // Image to render with the extracted text + int rendering_dpi_; // Resolution of the rendering_image }; /** diff --git a/src/api/pdfrenderer.cpp b/src/api/pdfrenderer.cpp index 81cf2e24d8..a017c4ab0a 100644 --- a/src/api/pdfrenderer.cpp +++ b/src/api/pdfrenderer.cpp @@ -809,9 +809,9 @@ bool TessPDFRenderer::imageToPDFObj(Pix *pix, const char *filename, long int obj } bool TessPDFRenderer::AddImageHandler(TessBaseAPI *api) { - Pix *pix = api->GetInputImage(); + Pix *pix = GetRenderingImage(api); const char *filename = api->GetInputName(); - int ppi = api->GetSourceYResolution(); + int ppi = GetRenderingResolution(api); if (!pix || ppi <= 0) { return false; } diff --git a/src/api/renderer.cpp b/src/api/renderer.cpp index 8d4f1adc1b..bd43eb16a0 100644 --- a/src/api/renderer.cpp +++ b/src/api/renderer.cpp @@ -18,12 +18,14 @@ #ifdef HAVE_CONFIG_H # include "config_auto.h" #endif +#include #include #include #include #include // std::unique_ptr #include // std::string #include "serialis.h" // Serialize +#include "tprintf.h" namespace tesseract { @@ -90,13 +92,69 @@ bool TessResultRenderer::AddImage(TessBaseAPI *api) { return false; } ++imagenum_; + Pix *rendering_image = rendering_image_; + int rendering_dpi = rendering_dpi_; bool ok = AddImageHandler(api); + if (rendering_image_ != rendering_image) { + delete rendering_image_; + rendering_image_ = rendering_image; + } + if (rendering_dpi_ != rendering_dpi) { + rendering_dpi_ = rendering_dpi; + } if (next_) { ok = next_->AddImage(api) && ok; } return ok; } +Pix* TessResultRenderer::GetRenderingImage(TessBaseAPI *api) { + if (!happy_) { + return nullptr; + } + if (!rendering_image_) { + Pix *input_image = api->GetInputImage(); + int source_dpi = api->GetSourceYResolution(); + if (!input_image || source_dpi <= 0) { + happy_ = false; + return nullptr; + } + + int rendering_dpi = GetRenderingResolution(api); + if (rendering_dpi != source_dpi) { + float scale = (float)rendering_dpi / (float)source_dpi; + + rendering_image_ = pixScale(input_image, scale, scale); + } else { + return input_image; + } + } + return rendering_image_; +} + +int TessResultRenderer::GetRenderingResolution(tesseract::TessBaseAPI *api) { + if (rendering_dpi_) { + return rendering_dpi_; + } + int source_dpi = api->GetSourceYResolution(); + int rendering_dpi; + if (api->GetIntVariable("rendering_dpi", &rendering_dpi) && + rendering_dpi > 0 && rendering_dpi != source_dpi) { + if (rendering_dpi < kMinCredibleResolution || + rendering_dpi > kMaxCredibleResolution) { +#if !defined(NDEBUG) + tprintf( + "Warning: User defined rendering dpi %d is outside of expected range " + "(%d - %d)!\n", + rendering_dpi, kMinCredibleResolution, kMaxCredibleResolution); +#endif + } + rendering_dpi_ = rendering_dpi; + return rendering_dpi_; + } + return source_dpi; +} + bool TessResultRenderer::EndDocument() { if (!happy_) { return false; diff --git a/src/ccmain/tesseractclass.cpp b/src/ccmain/tesseractclass.cpp index fd58ac8746..c12682ceea 100644 --- a/src/ccmain/tesseractclass.cpp +++ b/src/ccmain/tesseractclass.cpp @@ -349,6 +349,7 @@ Tesseract::Tesseract() , BOOL_MEMBER(textonly_pdf, false, "Create PDF with only one invisible text layer", this->params()) , INT_MEMBER(jpg_quality, 85, "Set JPEG quality level", this->params()) + , INT_MEMBER(rendering_dpi, 0, "Scale input image resolution for rendering", this->params()) , INT_MEMBER(user_defined_dpi, 0, "Specify DPI for input image", this->params()) , INT_MEMBER(min_characters_to_try, 50, "Specify minimum characters to try during OSD", this->params()) diff --git a/src/ccmain/tesseractclass.h b/src/ccmain/tesseractclass.h index 732bb9e62e..398fe5861d 100644 --- a/src/ccmain/tesseractclass.h +++ b/src/ccmain/tesseractclass.h @@ -903,6 +903,7 @@ class TESS_API Tesseract : public Wordrec { BOOL_VAR_H(tessedit_create_pdf); BOOL_VAR_H(textonly_pdf); INT_VAR_H(jpg_quality); + INT_VAR_H(rendering_dpi); INT_VAR_H(user_defined_dpi); INT_VAR_H(min_characters_to_try); STRING_VAR_H(unrecognised_char);