Ejemplo n.º 1
0
    /* Returns 1 on error */
static l_int32
test_mem_gif(const char  *fname,
             l_int32      index)
{
l_uint8  *data = NULL;
l_int32   same;
size_t    size = 0;
PIX      *pixs;
PIX      *pixd = NULL;

    if ((pixs = pixRead(fname)) == NULL) {
        fprintf(stderr, "Failure to read gif file: %s\n", fname);
        return 1;
    }
    if (pixWriteMem(&data, &size, pixs, IFF_GIF)) {
        fprintf(stderr, "Mem gif write fail on image %d\n", index);
        return 1;
    }
    if ((pixd = pixReadMem(data, size)) == NULL) {
        fprintf(stderr, "Mem gif read fail on image %d\n", index);
        lept_free(data);
        return 1;
    }

    pixEqual(pixs, pixd, &same);
    pixDestroy(&pixs);
    pixDestroy(&pixd);
    lept_free(data);
    if (!same && index < 6) {
        fprintf(stderr, "Mem gif write/read fail for file %s\n", fname);
        return 1;
    }
    else
        return 0;
}
Ejemplo n.º 2
0
    /* Returns 1 on error */
static l_int32
test_mem_png(const char  *fname)
{
l_uint8  *data = NULL;
l_int32   same;
size_t    size = 0;
PIX      *pixs;
PIX      *pixd = NULL;

    if ((pixs = pixRead(fname)) == NULL) {
        fprintf(stderr, "Failure to read %s\n", fname);
        return 1;
    }
    if (pixWriteMem(&data, &size, pixs, IFF_PNG)) {
        fprintf(stderr, "Mem write fail for png\n");
        return 1;
    }
    if ((pixd = pixReadMem(data, size)) == NULL) {
        fprintf(stderr, "Mem read fail for png\n");
        lept_free(data);
        return 1;
    }

    pixEqual(pixs, pixd, &same);
    if (!same)
        fprintf(stderr, "Mem write/read fail for file %s\n", fname);
    pixDestroy(&pixs);
    pixDestroy(&pixd);
    lept_free(data);
    return (!same);
}
Ejemplo n.º 3
0
// Returns the Pix image for the image_data. Must be pixDestroyed after use.
Pix* ImageData::GetPixInternal(const GenericVector<char>& image_data) {
  Pix* pix = NULL;
  if (!image_data.empty()) {
    // Convert the array to an image.
    const unsigned char* u_data =
        reinterpret_cast<const unsigned char*>(&image_data[0]);
    pix = pixReadMem(u_data, image_data.size());
  }
  return pix;
}
Ejemplo n.º 4
0
    /* Returns 1 on error */
static l_int32
test_writemem(PIX      *pixs,
              l_int32   format,
              char     *psfile)
{
l_uint8  *data = NULL;
l_int32   same;
size_t    size = 0;
PIX      *pixd = NULL;

    if (format == IFF_PS) {
        pixWriteMemPS(&data, &size, pixs, NULL, 0, 1.0);
        l_binaryWrite(psfile, "w", data, size);
        lept_free(data);
        return 0;
    }

    /* Fail silently if library is not available */
#if !HAVE_LIBJPEG
    if (format == IFF_JFIF_JPEG)
        return 0;
#endif  /* !HAVE_LIBJPEG */
#if !HAVE_LIBPNG
    if (format == IFF_PNG)
        return 0;
#endif  /* !HAVE_LIBPNG */
#if !HAVE_LIBTIFF
    if (format == IFF_TIFF)
        return 0;
#endif  /* !HAVE_LIBTIFF */

    if (pixWriteMem(&data, &size, pixs, format)) {
        fprintf(stderr, "Mem write fail for format %d\n", format);
        return 1;
    }
    if ((pixd = pixReadMem(data, size)) == NULL) {
        fprintf(stderr, "Mem read fail for format %d\n", format);
        lept_free(data);
        return 1;
    }
    if (format == IFF_JFIF_JPEG) {
        fprintf(stderr, "jpeg size = %ld\n", size);
        pixDisplayWrite(pixd, 1);
        same = TRUE;
    }
    else {
        pixEqual(pixs, pixd, &same);
        if (!same)
           fprintf(stderr, "Mem write/read fail for format %d\n", format);
    }
    pixDestroy(&pixd);
    lept_free(data);
    return (!same);
}
Ejemplo n.º 5
0
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadMem(JNIEnv *env, jclass clazz,
                                                                   jbyteArray image, jint length) {
    jbyte *image_buffer = env->GetByteArrayElements(image, NULL);
    int buffer_length = env->GetArrayLength(image);

    PIX *pix = pixReadMem((const l_uint8 *) image_buffer, buffer_length);

    env->ReleaseByteArrayElements(image, image_buffer, JNI_ABORT);

    return (jlong) pix;
}
/*!
 *  pixaGenerateFontFromString()
 *
 *      Input:  fontsize (4, 6, 8, ... , 20, in pts at 300 ppi)
 *              &bl1 (<return> baseline of row 1)
 *              &bl2 (<return> baseline of row 2)
 *              &bl3 (<return> baseline of row 3)
 *      Return: pixa of font bitmaps for 95 characters, or null on error
 *
 *  Notes:
 *      (1) See pixaGenerateFontFromFile() for details.
 */
PIXA *
pixaGenerateFontFromString(l_int32   fontsize,
                           l_int32  *pbl0,
                           l_int32  *pbl1,
                           l_int32  *pbl2)
{
l_uint8  *data;
l_int32   redsize, nbytes;
PIX      *pix;
PIXA     *pixa;

    PROCNAME("pixaGenerateFontFromString");

    if (!pbl0 || !pbl1 || !pbl2)
        return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
    *pbl0 = *pbl1 = *pbl2 = 0;
    redsize = (fontsize / 2) - 2;
    if (redsize < 0 || redsize > NUM_FONTS)
        return (PIXA *)ERROR_PTR("invalid font size", procName, NULL);

    if (fontsize == 4) {
        data = decodeBase64(fontdata_4, strlen(fontdata_4), &nbytes);
    } else if (fontsize == 6) {
        data = decodeBase64(fontdata_6, strlen(fontdata_6), &nbytes);
    } else if (fontsize == 8) {
        data = decodeBase64(fontdata_8, strlen(fontdata_8), &nbytes);
    } else if (fontsize == 10) {
        data = decodeBase64(fontdata_10, strlen(fontdata_10), &nbytes);
    } else if (fontsize == 12) {
        data = decodeBase64(fontdata_12, strlen(fontdata_12), &nbytes);
    } else if (fontsize == 14) {
        data = decodeBase64(fontdata_14, strlen(fontdata_14), &nbytes);
    } else if (fontsize == 16) {
        data = decodeBase64(fontdata_16, strlen(fontdata_16), &nbytes);
    } else if (fontsize == 18) {
        data = decodeBase64(fontdata_18, strlen(fontdata_18), &nbytes);
    } else {  /* fontsize == 20 */
        data = decodeBase64(fontdata_20, strlen(fontdata_20), &nbytes);
    }
    if (!data)
        return (PIXA *)ERROR_PTR("data not made", procName, NULL);

    pix = pixReadMem(data, nbytes);
    FREE(data);
    if (!pix)
        return (PIXA *)ERROR_PTR("pix not made", procName, NULL);

    pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
    pixDestroy(&pix);
    return pixa;
}
Ejemplo n.º 7
0
int main(int    argc,
         char **argv)
{
char          buf[512];
char         *pathname, *datastr, *formstr;
l_uint8      *data1, *data2;
l_int32       i, bl1, bl2, bl3, sbytes, formbytes, fontsize, rbytes;
size_t        nbytes;
PIX          *pix1, *pix2, *pixd;
PIXA         *pixa;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    /* ------------  Generate pixa char bitmap files from file ----------- */
    lept_rmdir("filefonts");
    lept_mkdir("filefonts");
    for (i = 0; i < 9; i++) {
        pixaSaveFont("fonts", "/tmp/filefonts", sizes[i]);
        pathname = genPathname("/tmp/filefonts", outputfonts[i]);
        pixa = pixaRead(pathname);
        if (rp->display) {
            fprintf(stderr, "Found %d chars in font size %d\n",
                    pixaGetCount(pixa), sizes[i]);
        }
        pixd = pixaDisplayTiled(pixa, 1500, 0, 15);
        regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 0 - 8 */
        if (i == 2) pixDisplayWithTitle(pixd, 100, 0, NULL, rp->display);
        pixDestroy(&pixd);
        pixaDestroy(&pixa);
        lept_free(pathname);
    }
    lept_rmdir("filefonts");

    /* ----------  Generate pixa char bitmap files from string --------- */
    lept_rmdir("strfonts");
    lept_mkdir("strfonts");
    for (i = 0; i < 9; i++) {
        pixaSaveFont(NULL, "/tmp/strfonts", sizes[i]);
        pathname = genPathname("/tmp/strfonts", outputfonts[i]);
        pixa = pixaRead(pathname);
        if (rp->display) {
            fprintf(stderr, "Found %d chars in font size %d\n",
                    pixaGetCount(pixa), sizes[i]);
        }
        pixd = pixaDisplayTiled(pixa, 1500, 0, 15);
        regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 9 - 17 */
        if (i == 2) pixDisplayWithTitle(pixd, 100, 150, NULL, rp->display);
        pixDestroy(&pixd);
        pixaDestroy(&pixa);
        lept_free(pathname);
    }

    /* -----  Use pixaGetFont() and write the result out  -----*/
    lept_rmdir("pafonts");
    lept_mkdir("pafonts");
    for (i = 0; i < 9; i++) {
        pixa = pixaGetFont("/tmp/strfonts", sizes[i], &bl1, &bl2, &bl3);
        fprintf(stderr, "Baselines are at: %d, %d, %d\n", bl1, bl2, bl3);
        snprintf(buf, sizeof(buf), "/tmp/pafonts/chars-%d.pa", sizes[i]);
        pixaWrite(buf, pixa);
        if (i == 2) {
            pixd = pixaDisplayTiled(pixa, 1500, 0, 15);
            pixDisplayWithTitle(pixd, 100, 300, NULL, rp->display);
            pixDestroy(&pixd);
        }
        pixaDestroy(&pixa);
    }
    lept_rmdir("pafonts");

    /* -------  Generate 4/3 encoded ascii strings from tiff files ------ */
    lept_rmdir("fontencode");
    lept_mkdir("fontencode");
    for (i = 0; i < 9; i++) {
        fontsize = 2 * i + 4;
        pathname = genPathname("fonts", inputfonts[i]);
        data1 = l_binaryRead(pathname, &nbytes);
        datastr = encodeBase64(data1, nbytes, &sbytes);
        if (rp->display)
            fprintf(stderr, "nbytes = %lu, sbytes = %d\n",
                    (unsigned long)nbytes, sbytes);
        formstr = reformatPacked64(datastr, sbytes, 4, 72, 1, &formbytes);
        snprintf(buf, sizeof(buf), "/tmp/fontencode/formstr_%d.txt", fontsize);
        l_binaryWrite(buf, "w", formstr, formbytes);
        regTestCheckFile(rp, buf);  /* 18-26 */
        if (i == 8)
            pix1 = pixReadMem(data1, nbytes);  /* original */
        FREE(data1);

        data2 = decodeBase64(datastr, sbytes, &rbytes);
        snprintf(buf, sizeof(buf), "/tmp/fontencode/image_%d.tif", fontsize);
        l_binaryWrite(buf, "w", data2, rbytes);
        if (i == 8) {
            pix2 = pixReadMem(data2, rbytes);  /* encode/decode */
            regTestComparePix(rp, pix1, pix2);  /* 27 */
            pixDestroy(&pix1);
            pixDestroy(&pix2);
        }
        FREE(data2);

        FREE(pathname);
        FREE(datastr);
        FREE(formstr);
    }

    /* ------------  Get timing for font generation ----------- */
    startTimer();
    for (i = 0; i < 100; i++) {
        pixa = pixaGenerateFontFromString(sizes[5], &bl1, &bl2, &bl3);
        pixaDestroy(&pixa);
    }
    fprintf(stderr, "Time for font gen = %7.4f sec\n", stopTimer() / 100.0);

    return regTestCleanup(rp);
}
Ejemplo n.º 8
0
char *internalDoScanningOperation(char *uuid, char *lang) {

  int request_resolution = 0;
  int docid;
  int current_page = 0;
  int total_requested_pages;
  double totbytes = 0;
  SANE_Status status;
  SANE_Handle *openDeviceHandle;
  SANE_Byte *raw_image;
  SANE_Parameters pars;
  char *docid_s;
  char *total_requested_pages_s;
  char *devName;
  char *outFilename;
  char *raw_image_format;
  char *header;

  o_log(DEBUGM, "doScanningOperation: sane initialized uuid(%s)",(char *)uuid);
  updateScanProgress(uuid, SCAN_WAITING_ON_SCANNER, 0);

  // Open the device
  devName = getScanParam(uuid, SCAN_PARAM_DEVNAME);
  o_log(DEBUGM, "sane_open of \"%s\"",devName);
  status = sane_open ((SANE_String_Const) devName, (SANE_Handle)&openDeviceHandle);
  if(status != SANE_STATUS_GOOD) {
    handleSaneErrors("Cannot open device ", devName, status, 0);
    updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
    free(devName);
    return 0;
  }
  free(devName);

  /* ========================================================== */
  if ( ! setOptions( (char *)uuid, openDeviceHandle, &request_resolution ) )
    return 0;
  o_log(DEBUGM, "sane_start: setOptions returned request_resolution %d\n",request_resolution);

  int timeout = 5;
  while( 0 < timeout ) {
    status = sane_start (openDeviceHandle);
    if(status == SANE_STATUS_GOOD) {  
      break;
    }
    else {
      if(status == SANE_STATUS_DEVICE_BUSY ) {  
        // BUSY signal could be the scanner just having a 
        // bit of lag - specially network connected devices
        timeout--;
        if ( timeout == 0 ) {
          handleSaneErrors("Cannot start scanning", "even after trying several time", status, 0);
          updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
          return 0;
        }
        else {
          o_log(WARNING, "Device reports not ready to 'start', waiting 500ms. Will try another %d times", timeout);
          usleep(500 * 1000); // 500ms or 0.5sec
        }
      }
      else {
        handleSaneErrors("Cannot start scanning", "", status, 0);
        updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
        return 0;
      }
    }
  }

  // Get scanning params (from the scanner)
  if( request_resolution == 0 ) {
    o_log(DEBUGM, "Resolution did not get set in scanner setup.");
    updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10004);
    return 0;
  }

  o_log(DEBUGM, "Get scanning params");
  status = sane_get_parameters (openDeviceHandle, &pars);
  o_log(INFORMATION, "Scanner Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d",
    sane_strstatus (status),
    pars.format, pars.last_frame,
    pars.bytes_per_line, pars.pixels_per_line,
    pars.lines, pars.depth);

  switch (pars.format) {
    case SANE_FRAME_GRAY:
      o_log(DEBUGM, "Expecting Gray data (1 channel only).");
      raw_image_format = o_strdup( "P5" );
      break;
    case SANE_FRAME_RGB:
      o_log(DEBUGM, "Expecting RGB data (3 channels).");
      raw_image_format = o_strdup( "P6" );
      break;
    default:
      o_log(DEBUGM, "backend returns three frames speratly. We do not currently support this.");
      updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10003);
      return 0;
      break;
  }
  
  header = o_printf ("%s\n# SANE data follows\n%d %d\n%d\n", 
    raw_image_format, pars.pixels_per_line, pars.lines,
    (pars.depth <= 8) ? 255 : 65535);
  free( raw_image_format );


  // Save Record
  //
  docid_s = getScanParam(uuid, SCAN_PARAM_DOCID);
  total_requested_pages_s = getScanParam(uuid, SCAN_PARAM_REQUESTED_PAGES);
  total_requested_pages = atoi(total_requested_pages_s);
  free(total_requested_pages_s);
  if( docid_s == NULL ) {
    o_log(DEBUGM, "Saving record");
    updateScanProgress(uuid, SCAN_DB_WORKING, 0);

    docid_s = addNewScannedDoc(pars.lines, pars.pixels_per_line, request_resolution, total_requested_pages); 
    setScanParam(uuid, SCAN_PARAM_DOCID, docid_s);
    setScanParam(uuid, SCAN_PARAM_ON_PAGE, "1");
    current_page = 1;
  }
  else {
    char *current_page_s = getScanParam(uuid, SCAN_PARAM_ON_PAGE);
    current_page = atoi(current_page_s);
    free(current_page_s);

    current_page++;

    current_page_s = itoa(current_page, 10);
    setScanParam(uuid, SCAN_PARAM_ON_PAGE, current_page_s);
    free(current_page_s);
  }
  docid = atoi(docid_s);
  free(docid_s);

  totbytes = (double)((pars.bytes_per_line * pars.lines));

  /* ========================================================== */
  raw_image = collectData( (char *)uuid, openDeviceHandle, totbytes, pars.bytes_per_line, header );
  o_log(INFORMATION, "Scanning done.");

  o_log(DEBUGM, "sane_cancel");
  sane_cancel(openDeviceHandle);

  o_log(DEBUGM, "sane_close");
  sane_close(openDeviceHandle);


  // Convert Raw into JPEG
  //
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 0);
  PIX *pix;
  if ( ( pix = pixReadMem( raw_image, (pars.bytes_per_line*pars.lines)+strlen(header) ) ) == NULL) {
    o_log(ERROR, "Could not load the image data into a PIX");
  }
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 55);
  o_log(INFORMATION, "Convertion process: Loaded (depth: %d)", pixGetDepth(pix));
  free(raw_image);
  free(header);

  outFilename = o_printf("%s/scans/%d_%d.jpg", BASE_DIR, docid, current_page);
  pixWrite(outFilename, pix, IFF_JFIF_JPEG);
  free(outFilename);
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 100);
  o_log(INFORMATION, "Conversion process: Complete");




  // Do OCR - on this page
  // - OCR libs just wants the raw data and not the image header
  ocrImage( uuid, docid, current_page, request_resolution, pix, lang );


#ifdef CAN_PHASH
  // Calulate the pHash, so we can compare images later
  if( current_page == 1 ) {
    updateScanProgress(uuid, SCAN_CALULATING_PHASH, 0);
    unsigned long long hash = getImagePhash_px( pix );
    savePhash( docid, hash );
  }
#endif /* CAN_PHASH */
  pixDestroy( &pix );


  // cleaup && What should we do next
  //
  o_log(DEBUGM, "mostly done.");
  if(current_page >= total_requested_pages)
    updateScanProgress(uuid, SCAN_FINISHED, docid);
  else
    updateScanProgress(uuid, SCAN_WAITING_ON_NEW_PAGE, ++current_page);

  o_log(DEBUGM, "Page scan done.");

  return o_strdup("OK"); 
}
Ejemplo n.º 9
0
int main(int argc, char **argv) {
  if ((argc == 2 && strcmp(argv[1], "-v") == 0) ||
      (argc == 2 && strcmp(argv[1], "--version") == 0)) {
    char *versionStrP;

    fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version());

    versionStrP = getLeptonicaVersion();
    fprintf(stderr, " %s\n", versionStrP);
    lept_free(versionStrP);

    versionStrP = getImagelibVersions();
    fprintf(stderr, "  %s\n", versionStrP);
    lept_free(versionStrP);

#ifdef USE_OPENCL
    cl_platform_id platform;
    cl_uint num_platforms;
    cl_device_id devices[2];
    cl_uint num_devices;
    char info[256];
    int i;

    fprintf(stderr, " OpenCL info:\n");
    clGetPlatformIDs(1, &platform, &num_platforms);
    fprintf(stderr, "  Found %d platforms.\n", num_platforms);
    clGetPlatformInfo(platform, CL_PLATFORM_NAME, 256, info, 0);
    fprintf(stderr, "  Platform name: %s.\n", info);
    clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 256, info, 0);
    fprintf(stderr, "  Version: %s.\n", info);
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, devices, &num_devices);
    fprintf(stderr, "  Found %d devices.\n", num_devices);
    for (i = 0; i < num_devices; ++i) {
      clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 256, info, 0);
      fprintf(stderr, "    Device %d name: %s.\n", i+1, info);
    }
#endif
    exit(0);
  }

  // Make the order of args a bit more forgiving than it used to be.
  const char* lang = "eng";
  const char* image = NULL;
  const char* output = NULL;
  const char* datapath = NULL;
  bool noocr = false;
  bool list_langs = false;
  bool print_parameters = false;

  tesseract::PageSegMode pagesegmode = tesseract::PSM_AUTO;
  int arg = 1;
  while (arg < argc && (output == NULL || argv[arg][0] == '-')) {
    if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) {
      lang = argv[arg + 1];
      ++arg;
    } else if (strcmp(argv[arg], "--tessdata-dir") == 0 && arg + 1 < argc) {
      datapath = argv[arg + 1];
      ++arg;
    } else if (strcmp(argv[arg], "--list-langs") == 0) {
      noocr = true;
      list_langs = true;
    } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) {
      pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1]));
      ++arg;
    } else if (strcmp(argv[arg], "--print-parameters") == 0) {
      noocr = true;
      print_parameters = true;
    } else if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) {
      // handled properly after api init
      ++arg;
    } else if (image == NULL) {
      image = argv[arg];
    } else if (output == NULL) {
      output = argv[arg];
    }
    ++arg;
  }

  if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {
    list_langs = true;
    noocr = true;
  }

  if (output == NULL && noocr == false) {
    fprintf(stderr, "Usage:\n  %s imagename|stdin outputbase|stdout "
            "[options...] [configfile...]\n\n", argv[0]);

    fprintf(stderr, "OCR options:\n");
    fprintf(stderr, "  --tessdata-dir /path\tspecify location of tessdata"
                      " path\n");
    fprintf(stderr, "  -l lang[+lang]\tspecify language(s) used for OCR\n");
    fprintf(stderr, "  -c configvar=value\tset value for control parameter.\n"
                      "\t\t\tMultiple -c arguments are allowed.\n");
    fprintf(stderr, "  -psm pagesegmode\tspecify page segmentation mode.\n");
    fprintf(stderr, "These options must occur before any configfile.\n\n");
    fprintf(stderr,
            "pagesegmode values are:\n"
            "  0 = Orientation and script detection (OSD) only.\n"
            "  1 = Automatic page segmentation with OSD.\n"
            "  2 = Automatic page segmentation, but no OSD, or OCR\n"
            "  3 = Fully automatic page segmentation, but no OSD. (Default)\n"
            "  4 = Assume a single column of text of variable sizes.\n"
            "  5 = Assume a single uniform block of vertically aligned text.\n"
            "  6 = Assume a single uniform block of text.\n"
            "  7 = Treat the image as a single text line.\n"
            "  8 = Treat the image as a single word.\n"
            "  9 = Treat the image as a single word in a circle.\n"
            "  10 = Treat the image as a single character.\n\n");
    fprintf(stderr, "Single options:\n");
    fprintf(stderr, "  -v --version: version info\n");
    fprintf(stderr, "  --list-langs: list available languages for tesseract "
                      "engine. Can be used with --tessdata-dir.\n");
    fprintf(stderr, "  --print-parameters: print tesseract parameters to the "
                      "stdout.\n");
    exit(1);
  }

  if (output != NULL && strcmp(output, "-") && strcmp(output, "stdout")) {
    tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
           tesseract::TessBaseAPI::Version());
  }
  PERF_COUNT_START("Tesseract:main")
  tesseract::TessBaseAPI api;

  api.SetOutputName(output);
  int rc = api.Init(datapath, lang, tesseract::OEM_DEFAULT,
                &(argv[arg]), argc - arg, NULL, NULL, false);

  if (rc) {
    fprintf(stderr, "Could not initialize tesseract.\n");
    exit(1);
  }

  char opt1[255], opt2[255];
  for (arg = 0; arg < argc; arg++) {
    if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) {
      strncpy(opt1, argv[arg + 1], 255);
      *(strchr(opt1, '=')) = 0;
      strncpy(opt2, strchr(argv[arg + 1], '=') + 1, 255);
      opt2[254] = 0;
      ++arg;

      if (!api.SetVariable(opt1, opt2)) {
        fprintf(stderr, "Could not set option: %s=%s\n", opt1, opt2);
      }
    }
  }

  if (list_langs) {
     GenericVector<STRING> languages;
     api.GetAvailableLanguagesAsVector(&languages);
     fprintf(stderr, "List of available languages (%d):\n",
             languages.size());
     for (int index = 0; index < languages.size(); ++index) {
       STRING& string = languages[index];
       fprintf(stderr, "%s\n", string.string());
     }
     api.End();
     exit(0);
  }

  if (print_parameters) {
     FILE* fout = stdout;
     fprintf(stdout, "Tesseract parameters:\n");
     api.PrintVariables(fout);
     api.End();
     exit(0);
  }

  // We have 2 possible sources of pagesegmode: a config file and
  // the command line. For backwards compatability reasons, the
  // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the
  // default for this program is tesseract::PSM_AUTO. We will let
  // the config file take priority, so the command-line default
  // can take priority over the tesseract default, so we use the
  // value from the command line only if the retrieved mode
  // is still tesseract::PSM_SINGLE_BLOCK, indicating no change
  // in any config file. Therefore the only way to force
  // tesseract::PSM_SINGLE_BLOCK is from the command line.
  // It would be simpler if we could set the value before Init,
  // but that doesn't work.
  if (api.GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK)
     api.SetPageSegMode(pagesegmode);

  bool stdInput = !strcmp(image, "stdin") || !strcmp(image, "-");
  Pix* pixs = NULL;
  if (stdInput) {
    char byt;
    GenericVector<l_uint8> ch_data;
    std::istream file(std::cin.rdbuf());

#ifdef WIN32
    if (_setmode(_fileno(stdin), _O_BINARY) == -1)
      tprintf("ERROR: cin to binary: %s", strerror(errno));
#endif  // WIN32

    while (file.get(byt)) {
      ch_data.push_back(byt);
    }
    std::cin.ignore(std::cin.rdbuf()->in_avail() + 1);

    pixs = pixReadMem(&ch_data[0], ch_data.size());
  }

  if (pagesegmode == tesseract::PSM_AUTO_ONLY ||
      pagesegmode == tesseract::PSM_OSD_ONLY) {
    int ret_val = 0;

    if (!pixs)
      pixs = pixRead(image);
    if (!pixs) {
      fprintf(stderr, "Cannot open input file: %s\n", image);
      exit(2);
    }
    api.SetImage(pixs);

    if (pagesegmode == tesseract::PSM_OSD_ONLY) {
       OSResults osr;
       if (api.DetectOS(&osr)) {
         int orient = osr.best_result.orientation_id;
         int script_id = osr.get_best_script(orient);
         float orient_oco = osr.best_result.oconfidence;
         float orient_sco = osr.best_result.sconfidence;
         tprintf("Orientation: %d\nOrientation in degrees: %d\n" \
                 "Orientation confidence: %.2f\n" \
                 "Script: %d\nScript confidence: %.2f\n",
                 orient, OrientationIdToValue(orient), orient_oco,
                 script_id, orient_sco);
       } else {
         ret_val = 1;
       }
    } else {
       tesseract::Orientation orientation;
       tesseract::WritingDirection direction;
       tesseract::TextlineOrder order;
       float deskew_angle;
       tesseract::PageIterator* it =  api.AnalyseLayout();
       if (it) {
         it->Orientation(&orientation, &direction, &order, &deskew_angle);
         tprintf("Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n" \
                 "Deskew angle: %.4f\n",
                  orientation, direction, order, deskew_angle);
       } else {
         ret_val = 1;
       }
       delete it;
    }
    pixDestroy(&pixs);
    exit(ret_val);
  }

  tesseract::TessResultRenderer* renderer = NULL;
  bool b;
  api.GetBoolVariable("tessedit_create_hocr", &b);
  if (b && renderer == NULL) renderer = new tesseract::TessHOcrRenderer();

  api.GetBoolVariable("tessedit_create_pdf", &b);
  if (b && renderer == NULL)
    renderer = new tesseract::TessPDFRenderer(api.GetDatapath());

  api.GetBoolVariable("tessedit_create_boxfile", &b);
  if (b && renderer == NULL) renderer = new tesseract::TessBoxTextRenderer();

  if (renderer == NULL) renderer = new tesseract::TessTextRenderer();

  if (pixs) {
    api.ProcessPage(pixs, 0, NULL, NULL, 0, renderer);
    pixDestroy(&pixs);
  } else {
    FILE* fin = fopen(image, "rb");
    if (fin == NULL) {
      fprintf(stderr, "Cannot open input file: %s\n", image);
      exit(2);
    }
    fclose(fin);
    if (!api.ProcessPages(image, NULL, 0, renderer)) {
      fprintf(stderr, "Error during processing.\n");
      exit(1);
    }
  }

  FILE* fout = stdout;
  if (strcmp(output, "-") && strcmp(output, "stdout")) {
    STRING outfile = STRING(output)
        + STRING(".")
        + STRING(renderer->file_extension());
    fout = fopen(outfile.string(), "wb");
    if (fout == NULL) {
      fprintf(stderr, "Cannot create output file %s\n", outfile.string());
      exit(1);
    }
  }

  const char* data;
  inT32 data_len;
  if (renderer->GetOutput(&data, &data_len)) {
    fwrite(data, 1, data_len, fout);
    if (fout != stdout)
      fclose(fout);
    else
      clearerr(fout);
  }
  PERF_COUNT_END
  return 0;                      // Normal exit
}