///////////////////////////////////////////////////////////////////////
// File:        tessdll.cpp
// Description: Windows dll interface for Tesseract.
// Author:      Glen Wernersbach
// Created:     Tue May 15 10:30:01 PDT 2007
//
// (C) Copyright 2007, Jetsoftdev.
// 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.
//
///////////////////////////////////////////////////////////////////////
// tessdll.cpp : Defines the entry point for the DLL application.
//


#include "mfcpch.h"
#include "applybox.h"
#include "control.h"
#include "tessvars.h"
#include "tessedit.h"
#include "pageres.h"
#include "imgs.h"
#include "tprintf.h"
#include "tesseractmain.h"
#include "stderr.h"



#include "tessdll.h"

extern ESHM_INFO shm;            /*info on shm */

extern BOOL_VARIABLE tessedit_write_ratings;
extern BOOL_VARIABLE tessedit_write_output;
extern BOOL_VARIABLE tessedit_write_raw_output;
extern BOOL_VARIABLE tessedit_write_txt_map;
extern BOOL_VARIABLE tessedit_resegment_from_boxes;

TessDllAPI::TessDllAPI(const char *sDataDir, const char* lang) {

  init_tesseract (sDataDir, NULL, lang, NULL);

  tessedit_write_ratings.set_value (TRUE);
  tessedit_write_output.set_value(FALSE);
  tessedit_write_raw_output.set_value(FALSE);
  tessedit_write_txt_map.set_value(FALSE);


  page_res=0L;
  block_list = 0L;
  memset(&shm, 0, sizeof(ESHM_INFO));
  shm.shm_size = sizeof (ETEXT_DESC) + 32000L * sizeof (EANYCODE_CHAR);
  shm.shm_mem = malloc(shm.shm_size);
}

TessDllAPI::~TessDllAPI() {
  EndPage();

  End();

  if (shm.shm_mem != NULL) {
	  free(shm.shm_mem);
	  shm.shm_mem = NULL;
	  shm.shm_size = 0;
  }
}

int TessDllAPI::BeginPage(uinT32 xsize,uinT32 ysize,unsigned char *buf)
{
    return BeginPage(xsize,ysize,buf,1);
}

int TessDllAPI::BeginPage(uinT32 xsize,uinT32 ysize,unsigned char *buf,uinT8 bpp) {
  inT16 c;

  EndPage();

  if (page_image.create (xsize+800, ysize+800, 1)==-1)
    return 0L;  //make the image bigger to enclose in whitespace

  //copy the passed buffer into the center of the image

  IMAGE tmp;

  tmp.create(xsize, ysize, bpp);

  for (c=0;c<ysize;c++)
    memcpy(tmp.get_buffer ()+(c)*((xsize*bpp + 7)/8),
               buf+((ysize-1)-c)*((xsize*bpp + 7)/8),((xsize*bpp + 7)/8));


  copy_sub_image(&tmp, 0, 0, 0, 0, &page_image, 400, 400, false);




  return ProcessPagePass1();
}
int TessDllAPI::BeginPageUpright(uinT32 xsize,uinT32 ysize,unsigned char *buf)
{

    return BeginPageUpright(xsize,ysize,buf,1);
}

int TessDllAPI::BeginPageUpright(uinT32 xsize,uinT32 ysize, const unsigned char *buf, uinT8 bpp) {
    EndPage();

//It looks like Adaptive thresholding is disabled so this must be a 1 bpp image
  if (page_image.create (xsize+800, ysize+800, 1)==-1)
    return 0L;  //make the image bigger to enclose in whitespace

  //copy the passed buffer into the center of the image
  copy_buff_to_sub_image(buf, xsize, ysize, &page_image, 400, 400);
  return ProcessPagePass1();
}

int TessDllAPI::ProcessPagePass1() {
  STRING pagefile;               //input file
  block_list = new BLOCK_LIST;
  pgeditor_read_file(block_list);


  if (tessedit_resegment_from_boxes)
    apply_boxes(block_list);
  page_res = new PAGE_RES(block_list);

  if (page_res)
    recog_all_words(page_res, global_monitor,0L,1);

  return (page_res!=0);
}

void TessDllAPI::EndPage() {
  if (page_res) delete page_res;
  page_res=0L;
  if (block_list) delete block_list;
  block_list = 0L;
}


ETEXT_DESC * TessDllAPI::Recognize_all_Words(void) {
  return Recognize_a_Block(0,0,0,0);
}

ETEXT_DESC * TessDllAPI::Recognize_a_Block(uinT32 left,uinT32 right,
                                           uinT32 top,uinT32 bottom) {
  TBOX          target_word_box(ICOORD (left+400, top+400), ICOORD (right+400, bottom+400));
  int           i;

  memset(shm.shm_mem, 0,shm.shm_size);


  global_monitor = ocr_setup_monitor();

  recog_all_words(page_res, global_monitor,(right==0 ? 0L : &target_word_box),2);

  for (i=0;i<global_monitor->count;i++) {
    global_monitor->text[i].left-=400;
    global_monitor->text[i].right-=400;
    global_monitor->text[i].bottom-=400;
    global_monitor->text[i].top-=400;
  }

  global_monitor = 0L;

  return ((ETEXT_DESC *) shm.shm_mem);
}

TessDllAPI *recognize=0L;
char* current_lang = 0L;

extern "C"
{

void TessDllRelease() {
  if (recognize) delete recognize;
  recognize=0L;
}

void  * TessDllInit(const char *sDataDir, const char* lang) {
  if (recognize) TessDllRelease();

  recognize = new TessDllAPI(sDataDir, lang);
  if (current_lang != 0L)
    free(current_lang);
  current_lang = lang ? strdup(lang) : 0L;

  return (void*) recognize;
}

int TessDllBeginPageBPP(uinT32 xsize,uinT32 ysize,
                                         unsigned char *buf, uinT8 bpp) {
  return TessDllBeginPageLangBPP(xsize, ysize, buf, NULL,bpp);
}

int TessDllBeginPageLangBPP(uinT32 xsize, uinT32 ysize,
                                             unsigned char *buf,
                                             const char* lang, uinT8 bpp) {
  //if (recognize==0L || (lang != 0L) != (current_lang != 0L) ||
  //    lang != 0L && strcmp(lang, current_lang))
  //  TessDllInit(lang);

  return recognize->BeginPage(xsize, ysize, buf,bpp);
}

int TessDllBeginPageUprightBPP(uinT32 xsize, uinT32 ysize,
                                             const unsigned char *buf, uinT8 bpp) {
  return recognize->BeginPageUpright(xsize, ysize, buf, bpp);
 
}

int TessDllBeginPage(uinT32 xsize,uinT32 ysize,
                                         unsigned char *buf) {
  return TessDllBeginPageLangBPP(xsize, ysize, buf, NULL,1);
}

int TessDllBeginPageLang(uinT32 xsize, uinT32 ysize,
                                             unsigned char *buf,
                                             const char* lang) {
  //if (recognize==0L || (lang != 0L) != (current_lang != 0L) ||
  //    lang != 0L && strcmp(lang, current_lang))
  //  TessDllInit(lang);

  return recognize->BeginPage(xsize, ysize, buf,1);
}

int TessDllBeginPageUpright(uinT32 xsize, uinT32 ysize,
                                             unsigned char *buf,
                                             const char* lang) {
  //if (recognize==0L || (lang != 0L) != (current_lang != 0L) ||
  //    lang != 0L && strcmp(lang, current_lang))
  //  TessDllInit(lang);

  return recognize->BeginPageUpright(xsize, ysize, buf);
}

void TessDllEndPage(void) {
  recognize->EndPage();
  recognize->ClearAdaptiveClassifier();
}

ETEXT_DESC * TessDllRecognize_a_Block(uinT32 left,
                                                          uinT32 right,
                                                          uinT32 top,
                                                          uinT32 bottom) {
  return recognize->Recognize_a_Block(left,right,top,bottom);
}


ETEXT_DESC * TessDllRecognize_all_Words(void) {
  return recognize->Recognize_all_Words();
}



//deprecated funtions
void ReleaseRecognize()
{

    if (recognize) delete recognize;recognize=0L;

}

ETEXT_DESC * reconize_a_word(uinT32 left,uinT32 right,uinT32 top,uinT32 bottom)
{
return recognize->Recognize_a_Block(left,right,top,bottom);
}


}
