Beispiel #1
0
/*
 *  pixaWriteCompressedToPS()
 *
 *      Input:  pixa (any set of images)
 *              fileout (output ps file)
 *              res (of input image)
 *              level (compression: 2 or 3)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This generates a PS file of multiple page images, all
 *          with bounding boxes.
 *      (2) It compresses to:
 *              cmap + level2:        jpeg
 *              cmap + level3:        flate
 *              1 bpp:                tiffg4
 *              2 or 4 bpp + level2:  jpeg
 *              2 or 4 bpp + level3:  flate
 *              8 bpp:                jpeg
 *              16 bpp:               flate
 *              32 bpp:               jpeg
 *      (3) To generate a pdf, use: ps2pdf <infile.ps> <outfile.pdf>
 */
l_int32
pixaWriteCompressedToPS(PIXA        *pixa,
                        const char  *fileout,
                        l_int32      res,
                        l_int32      level)
{
char     *tname, *g4_name, *jpeg_name, *png_name;
l_int32   i, n, firstfile, index, writeout, d;
PIX      *pix, *pixt;
PIXCMAP  *cmap;

    PROCNAME("pixaWriteCompressedToPS");

    if (!pixa)
        return ERROR_INT("pixa not defined", procName, 1);
    if (!fileout)
        return ERROR_INT("fileout not defined", procName, 1);
    if (level != 2 && level != 3) {
        L_ERROR("only levels 2 and 3 permitted; using level 2\n", procName);
        level = 2;
    }

    n = pixaGetCount(pixa);
    firstfile = TRUE;
    index = 0;
    lept_mkdir("lept/comp");
    g4_name = genTempFilename("/tmp/lept/comp", "temp.tif", 0, 0);
    jpeg_name = genTempFilename("/tmp/lept/comp", "temp.jpg", 0, 0);
    png_name = genTempFilename("/tmp/lept/comp", "temp.png", 0, 0);
    for (i = 0; i < n; i++) {
        writeout = TRUE;
        pix = pixaGetPix(pixa, i, L_CLONE);
        d = pixGetDepth(pix);
        cmap = pixGetColormap(pix);
        if (d == 1) {
            tname = g4_name;
            pixWrite(tname, pix, IFF_TIFF_G4);
        } else if (cmap) {
            if (level == 2) {
                pixt = pixConvertForPSWrap(pix);
                tname = jpeg_name;
                pixWrite(tname, pixt, IFF_JFIF_JPEG);
                pixDestroy(&pixt);
            } else {  /* level == 3 */
                tname = png_name;
                pixWrite(tname, pix, IFF_PNG);
            }
        } else if (d == 16) {
            if (level == 2)
                L_WARNING("d = 16; must write out flate\n", procName);
            tname = png_name;
            pixWrite(tname, pix, IFF_PNG);
        } else if (d == 2 || d == 4) {
            if (level == 2) {
                pixt = pixConvertTo8(pix, 0);
                tname = jpeg_name;
                pixWrite(tname, pixt, IFF_JFIF_JPEG);
                pixDestroy(&pixt);
            } else {  /* level == 3 */
                tname = png_name;
                pixWrite(tname, pix, IFF_PNG);
            }
        } else if (d == 8 || d == 32) {
            tname = jpeg_name;
            pixWrite(tname, pix, IFF_JFIF_JPEG);
        } else {  /* shouldn't happen */
            L_ERROR("invalid depth: %d\n", procName, d);
            writeout = FALSE;
        }
        pixDestroy(&pix);

        if (writeout)
            writeImageCompressedToPSFile(tname, fileout, res,
                                         &firstfile, &index);
    }

    LEPT_FREE(g4_name);
    LEPT_FREE(jpeg_name);
    LEPT_FREE(png_name);
    return 0;
}
int main(int    argc,
         char **argv)
{
char         filename[BUF_SIZE];
char        *dirin, *rootname, *fname;
l_int32      i, size, firstpage, npages, nfiles;
l_float32    rank;
JBDATA      *data;
JBCLASSER   *classer;
SARRAY      *safiles;
PIX         *pix, *pixt;
PIXA        *pixa, *pixadb;
static char  mainName[] = "jbrankhaus";

    if (argc != 5 && argc != 7)
        return ERROR_INT(
             " Syntax: jbrankhaus dirin size rank rootname [firstpage, npages]",
             mainName, 1);

    dirin = argv[1];
    size = atoi(argv[2]);
    rank = atof(argv[3]);
    rootname = argv[4];

    if (argc == 5) {
        firstpage = 0;
        npages = 0;
    }
    else {
        firstpage = atoi(argv[5]);
        npages = atoi(argv[6]);
    }

#if 0

    /*--------------------------------------------------------------*/

    jbRankHaus(dirin, size, rank, COMPONENTS, rootname, firstpage, npages, 1);

    /*--------------------------------------------------------------*/

#else

    /*--------------------------------------------------------------*/

    safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages);
    nfiles = sarrayGetCount(safiles);

/*    sarrayWriteStream(stderr, safiles); */

        /* Classify components on requested pages */
    startTimer();
    classer = jbRankHausInit(COMPONENTS, 0, 0, size, rank);
    jbAddPages(classer, safiles);
    fprintf(stderr, "Time to classify components: %6.3f sec\n", stopTimer());

        /* Save and write out the result */
    data = jbDataSave(classer);
    jbDataWrite(rootname, data);

        /* Render the pages from the classifier data.
         * Use debugflag == FALSE to omit outlines of each component. */
    pixa = jbDataRender(data, FALSE);

        /* Write the pages out */
    npages = pixaGetCount(pixa);
    if (npages != nfiles)
        fprintf(stderr, "npages = %d, nfiles = %d, not equal!\n",
                npages, nfiles);
    for (i = 0; i < npages; i++) {
        pix = pixaGetPix(pixa, i, L_CLONE);
        snprintf(filename, BUF_SIZE, "%s.%04d", rootname, i);
        fprintf(stderr, "filename: %s\n", filename);
        pixWrite(filename, pix, IFF_PNG);
        pixDestroy(&pix);
    }

#if  DISPLAY_DIFFERENCE
    fname = sarrayGetString(safiles, 0, L_NOCOPY);
    pixt = pixRead(fname);
    pix = pixaGetPix(pixa, 0, L_CLONE);
    pixXor(pixt, pixt, pix);
    pixWrite("junk_output_diff", pixt, IFF_PNG);
    pixDestroy(&pix);
    pixDestroy(&pixt);
#endif  /* DISPLAY_DIFFERENCE */

#if  DEBUG_TEST_DATA_IO
{ JBDATA  *newdata;
  PIX     *newpix;
  PIXA    *newpixa;
  l_int32  same, iofail;
        /* Read the data back in and render the pages */
    newdata = jbDataRead(rootname);
    newpixa = jbDataRender(newdata, FALSE);
    iofail = FALSE;
    for (i = 0; i < npages; i++) {
        pix = pixaGetPix(pixa, i, L_CLONE);
        newpix = pixaGetPix(newpixa, i, L_CLONE);
        pixEqual(pix, newpix, &same);
        if (!same) {
            iofail = TRUE;
            fprintf(stderr, "pix on page %d are unequal!\n", i);
        }
        pixDestroy(&pix);
        pixDestroy(&newpix);

    }
    if (iofail)
        fprintf(stderr, "read/write for jbdata fails\n");
    else
        fprintf(stderr, "read/write for jbdata succeeds\n");
    jbDataDestroy(&newdata);
    pixaDestroy(&newpixa);
}
#endif  /* DEBUG_TEST_DATA_IO */

#if  RENDER_DEBUG
        /* Use debugflag == TRUE to see outlines of each component. */
    pixadb = jbDataRender(data, TRUE);
        /* Write the debug pages out */
    npages = pixaGetCount(pixadb);
    for (i = 0; i < npages; i++) {
        pix = pixaGetPix(pixadb, i, L_CLONE);
        snprintf(filename, BUF_SIZE, "%s.db.%04d", rootname, i);
        fprintf(stderr, "filename: %s\n", filename);
        pixWrite(filename, pix, IFF_PNG);
        pixDestroy(&pix);
    }
    pixaDestroy(&pixadb);
#endif  /* RENDER_DEBUG */

#if  DISPLAY_ALL_INSTANCES
        /* display all instances, organized by template */
    pix = pixaaDisplayByPixa(classer->pixaa,
                             X_SPACING, Y_SPACING, MAX_OUTPUT_WIDTH);
    pixWrite("output_instances", pix, IFF_PNG);
    pixDestroy(&pix);
#endif  /* DISPLAY_ALL_INSTANCES */

    pixaDestroy(&pixa);
    sarrayDestroy(&safiles);
    jbClasserDestroy(&classer);
    jbDataDestroy(&data);

    /*--------------------------------------------------------------*/

#endif

    return 0;
}
// Performs line segmentation
bool CubeLineSegmenter::LineSegment() {
  // Use full image morphology to find columns
  // This only works for simple layouts where each column
  // of text extends the full height of the input image.
  Pix *pix_temp1 = pixMorphCompSequence(img_, "c5.500", 0);
  if (pix_temp1 == NULL) {
    return false;
  }

  // Mask with a single component over each column
  Pixa *pixam;
  Boxa *boxa = pixConnComp(pix_temp1, &pixam, 8);

  if (boxa == NULL) {
    return false;
  }

  int init_morph_min_hgt = kLineSepMorphMinHgt;
  char sequence_str[16];
  sprintf(sequence_str, "c100.%d", init_morph_min_hgt);

  // Use selective region-based morphology to get the textline mask.
  Pixa *pixad = pixaMorphSequenceByRegion(img_, pixam, sequence_str, 0, 0);
  if (pixad == NULL) {
    return false;
  }

  // for all columns
  int col_cnt = boxaGetCount(boxa);

  // create columns
  columns_ = pixaaCreate(col_cnt);
  if (columns_ == NULL) {
    return false;
  }

  // index columns based on readind order (RTL)
  int *col_order = IndexRTL(pixad);
  if (col_order == NULL) {
    return false;
  }

  line_cnt_ = 0;

  for (int col_idx = 0; col_idx < col_cnt; col_idx++) {
    int col = col_order[col_idx];

    // get the pix and box corresponding to the column
    Pix *pixt3 = pixaGetPix(pixad, col, L_CLONE);
    if (pixt3 == NULL) {
      return false;
    }

    Box *col_box = pixad->boxa->box[col];

    Pixa *pixac;
    Boxa *boxa2 = pixConnComp(pixt3, &pixac, 8);
    if (boxa2 == NULL) {
      return false;
    }

    // offset the boxes by the column box
    for (int line = 0; line < pixac->n; line++) {
      pixac->boxa->box[line]->x += col_box->x;
      pixac->boxa->box[line]->y += col_box->y;
    }

    // add the lines
    if (AddLines(pixac) == true) {
      if (pixaaAddBox(columns_, col_box, L_CLONE) != 0) {
        return false;
      }
    }

    pixDestroy(&pixt3);
    boxaDestroy(&boxa2);

    line_cnt_ += columns_->pixa[col_idx]->n;
  }

  pixaDestroy(&pixam);
  pixaDestroy(&pixad);
  boxaDestroy(&boxa);

  delete []col_order;
  pixDestroy(&pix_temp1);

  return true;
}
Beispiel #4
0
main(int    argc,
     char **argv)
{
char         buf[8];
l_int32      i, n, h;
l_float32    scalefact;
BOXA        *boxa;
PIX         *pixs, *pix, *pixt1, *pixt2;
PIXA        *pixa, *pixas, *pixad;
PIXAA       *pixaa;
static char  mainName[] = "digitprep1";

    if (argc != 1) {
        ERROR_INT(" Syntax: digitprep1", mainName, 1);
        return 1;
    }

    if ((pixs = pixRead("barcode-digits.png")) == NULL)
        return ERROR_INT("pixs not read", mainName, 1);

        /* Extract the digits and scale to HEIGHT */
    boxa = pixConnComp(pixs, &pixa, 8);
    pixas = pixaSort(pixa, L_SORT_BY_X, L_SORT_INCREASING, NULL, L_CLONE);
    n = pixaGetCount(pixas);

        /* Move the last ("0") to the first position */
    pixt1 = pixaGetPix(pixas, n - 1, L_CLONE);
    pixaInsertPix(pixas, 0, pixt1, NULL);
    pixaRemovePix(pixas, n);

        /* Make the output scaled pixa */
    pixad = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pixt1 = pixaGetPix(pixas, i, L_CLONE);
        pixGetDimensions(pixt1, NULL, &h, NULL);
        scalefact = HEIGHT / (l_float32)h;
        pixt2 = pixScale(pixt1, scalefact, scalefact);
        if (pixGetHeight(pixt2) != 32)
            return ERROR_INT("height not 32!", mainName, 1);
        sprintf(buf, "%d", i);
        pixSetText(pixt2, buf);
        pixaAddPix(pixad, pixt2, L_INSERT);
        pixDestroy(&pixt1);
    }

        /* Save in a pixaa, with 1 pix in each pixa */
    pixaa = pixaaCreateFromPixa(pixad, 1, L_CHOOSE_CONSECUTIVE, L_CLONE);
    pixaaWrite("junkdigits.pixaa", pixaa);

        /* Show result */
    pixt1 = pixaaDisplayByPixa(pixaa, 20, 20, 1000);
    pixDisplay(pixt1, 100, 100);
    pixDestroy(&pixt1);

    boxaDestroy(&boxa);
    pixaDestroy(&pixa);
    pixaDestroy(&pixas);
    pixaDestroy(&pixad);
    pixaaDestroy(&pixaa);
    return 0;
}
Beispiel #5
0
/*!
 *  pixSplitIntoCharacters()
 *
 *      Input:  pixs (1 bpp, contains only deskewed text)
 *              minw (minimum component width for initial filtering; typ. 4)
 *              minh (minimum component height for initial filtering; typ. 4)
 *              &boxa (<optional return> character bounding boxes)
 *              &pixa (<optional return> character images)
 *              &pixdebug (<optional return> showing splittings)
 *
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is a simple function that attempts to find split points
 *          based on vertical pixel profiles.
 *      (2) It should be given an image that has an arbitrary number
 *          of text characters.
 *      (3) The returned pixa includes the boxes from which the
 *          (possibly split) components are extracted.
 */
l_int32
pixSplitIntoCharacters(PIX     *pixs,
                       l_int32  minw,
                       l_int32  minh,
                       BOXA   **pboxa,
                       PIXA   **ppixa,
                       PIX    **ppixdebug)
{
l_int32  ncomp, i, xoff, yoff;
BOXA   *boxa1, *boxa2, *boxat1, *boxat2, *boxad;
BOXAA  *baa;
PIX    *pix, *pix1, *pix2, *pixdb;
PIXA   *pixa1, *pixadb;

    PROCNAME("pixSplitIntoCharacters");

    if (pboxa) *pboxa = NULL;
    if (ppixa) *ppixa = NULL;
    if (ppixdebug) *ppixdebug = NULL;
    if (!pixs || pixGetDepth(pixs) != 1)
        return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);

        /* Remove the small stuff */
    pix1 = pixSelectBySize(pixs, minw, minh, 8, L_SELECT_IF_BOTH,
                           L_SELECT_IF_GT, NULL);

        /* Small vertical close for consolidation */
    pix2 = pixMorphSequence(pix1, "c1.10", 0);
    pixDestroy(&pix1);

        /* Get the 8-connected components */
    boxa1 = pixConnComp(pix2, &pixa1, 8);
    pixDestroy(&pix2);
    boxaDestroy(&boxa1);

        /* Split the components if obvious */
    ncomp = pixaGetCount(pixa1);
    boxa2 = boxaCreate(ncomp);
    pixadb = (ppixdebug) ? pixaCreate(ncomp) : NULL;
    for (i = 0; i < ncomp; i++) {
        pix = pixaGetPix(pixa1, i, L_CLONE);
        if (ppixdebug) {
            boxat1 = pixSplitComponentWithProfile(pix, 10, 7, &pixdb);
            if (pixdb)
                pixaAddPix(pixadb, pixdb, L_INSERT);
        } else {
            boxat1 = pixSplitComponentWithProfile(pix, 10, 7, NULL);
        }
        pixaGetBoxGeometry(pixa1, i, &xoff, &yoff, NULL, NULL);
        boxat2 = boxaTransform(boxat1, xoff, yoff, 1.0, 1.0);
        boxaJoin(boxa2, boxat2, 0, -1);
        pixDestroy(&pix);
        boxaDestroy(&boxat1);
        boxaDestroy(&boxat2);
    }
    pixaDestroy(&pixa1);

        /* Generate the debug image */
    if (ppixdebug) {
        if (pixaGetCount(pixadb) > 0) {
            *ppixdebug = pixaDisplayTiledInRows(pixadb, 32, 1500,
                                                1.0, 0, 20, 1);
        }
        pixaDestroy(&pixadb);
    }

        /* Do a 2D sort on the bounding boxes, and flatten the result to 1D */
    baa = boxaSort2d(boxa2, NULL, 0, 0, 5);
    boxad = boxaaFlattenToBoxa(baa, NULL, L_CLONE);
    boxaaDestroy(&baa);
    boxaDestroy(&boxa2);

        /* Optionally extract the pieces from the input image */
    if (ppixa)
        *ppixa = pixClipRectangles(pixs, boxad);
    if (pboxa)
        *pboxa = boxad;
    else
        boxaDestroy(&boxad);
    return 0;
}
// Creates new set of lines from the computed columns
bool CubeLineSegmenter::AddLines(Pixa *lines) {
  // create an array that will hold the bounding boxes
  // of the concomps belonging to each line
  Boxaa *lines_con_comps = boxaaCreate(lines->n);
  if (lines_con_comps == NULL) {
    return false;
  }

  for (int line = 0; line < lines->n; line++) {
    // if the line is not valid
    if (ValidLine(lines->pix[line], lines->boxa->box[line]) == false) {
      // split it
      Pixa *split_lines = SplitLine(lines->pix[line],
          lines->boxa->box[line]);

      // remove the old line
      if (pixaRemovePix(lines, line) != 0) {
        return false;
      }

      line--;

      if (split_lines == NULL) {
        continue;
      }

      // add the split lines instead and move the pointer
      for (int s_line = 0; s_line < split_lines->n; s_line++) {
        Pix *sp_line = pixaGetPix(split_lines, s_line, L_CLONE);
        Box *sp_box = boxaGetBox(split_lines->boxa, s_line, L_CLONE);

        if (sp_line == NULL || sp_box == NULL) {
          return false;
        }

        // insert the new line
        if (pixaInsertPix(lines, ++line, sp_line, sp_box) != 0) {
          return false;
        }
      }

      // remove the split lines
      pixaDestroy(&split_lines);
    }
  }

  // compute the concomps bboxes of each line
  for (int line = 0; line < lines->n; line++) {
    Boxa *line_con_comps = ComputeLineConComps(lines->pix[line],
        lines->boxa->box[line], NULL);

    if (line_con_comps == NULL) {
      return false;
    }

    // insert it into the boxaa array
    if (boxaaAddBoxa(lines_con_comps, line_con_comps, L_INSERT) != 0) {
      return false;
    }
  }

  // post process the lines:
  // merge the contents of "small" lines info legitimate lines
  for (int line = 0; line < lines->n; line++) {
    // a small line detected
    if (SmallLine(lines->boxa->box[line]) == true) {
      // merge its components to one of the valid lines
      if (MergeLine(lines->pix[line], lines->boxa->box[line],
          lines, lines_con_comps) == true) {
        // remove the small line
        if (pixaRemovePix(lines, line) != 0) {
          return false;
        }

        if (boxaaRemoveBoxa(lines_con_comps, line) != 0) {
          return false;
        }

        line--;
      }
    }
  }

  boxaaDestroy(&lines_con_comps);

  // add the pix masks
  if (pixaaAddPixa(columns_, lines, L_INSERT) != 0) {
    return false;
  }

  return true;
}
int main(int    argc,
         char **argv)
{
l_int32       i, j, w, h;
l_int32       minsum[5] =    { 2, 40, 50, 50, 70};
l_int32       skipdist[5] =  { 5,  5, 10, 10, 30};
l_int32       delta[5] =     { 2, 10, 10, 25, 40};
l_int32       maxbg[5] =     {10, 15, 10, 20, 40};
BOX          *box1, *box2, *box3, *box4;
BOXA         *boxa;
PIX          *pixs, *pixc, *pixt, *pixd, *pix32;
PIXA         *pixas, *pixad;
L_REGPARAMS  *rp;

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

        /* Generate and save 1 bpp masks */
    pixas = pixaCreate(0);
    pixs = pixCreate(300, 250, 1);
    pixSetAll(pixs);
    box1 = boxCreate(50, 0, 140, 25);
    box2 = boxCreate(120, 100, 100, 25);
    box3 = boxCreate(75, 170, 80, 20);
    box4 = boxCreate(150, 80, 25, 70);

    pixClearInRect(pixs, box1);
    pixaAddPix(pixas, pixs, L_COPY);
    pixt = pixRotateOrth(pixs, 1);
    pixaAddPix(pixas, pixt, L_INSERT);

    pixClearInRect(pixs, box2);
    pixaAddPix(pixas, pixs, L_COPY);
    pixt = pixRotateOrth(pixs, 1);
    pixaAddPix(pixas, pixt, L_INSERT);

    pixClearInRect(pixs, box3);
    pixaAddPix(pixas, pixs, L_COPY);
    pixt = pixRotateOrth(pixs, 1);
    pixaAddPix(pixas, pixt, L_INSERT);

    pixClearInRect(pixs, box4);
    pixaAddPix(pixas, pixs, L_COPY);
    pixt = pixRotateOrth(pixs, 1);
    pixaAddPix(pixas, pixt, L_INSERT);

    boxDestroy(&box1);
    boxDestroy(&box2);
    boxDestroy(&box3);
    boxDestroy(&box4);
    pixDestroy(&pixs);

        /* Do 5 splittings on each of the 8 masks */
    pixad = pixaCreate(0);
    for (j = 0; j < 8; j++) {
        pixt = pixaGetPix(pixas, j, L_CLONE);
        pixGetDimensions(pixt, &w, &h, NULL);
        pix32 = pixCreate(w, h, 32);
        pixSetAll(pix32);
        pixPaintThroughMask(pix32, pixt, 0, 0, 0xc0c0c000);
        pixSaveTiled(pix32, pixad, 1.0, 1, 30, 32);
        for (i = 0; i < 5; i++) {
            pixc = pixCopy(NULL, pix32);
            boxa = pixSplitComponentIntoBoxa(pixt, NULL, minsum[i], skipdist[i],
                                             delta[i], maxbg[i], 0, 1);
/*            boxaWriteStream(stderr, boxa); */
            pixd = pixBlendBoxaRandom(pixc, boxa, 0.4);
            pixRenderBoxaArb(pixd, boxa, 2, 255, 0, 0);
            pixSaveTiled(pixd, pixad, 1.0, 0, 30, 32);
            pixDestroy(&pixd);
            pixDestroy(&pixc);
            boxaDestroy(&boxa);
        }
        pixDestroy(&pixt);
        pixDestroy(&pix32);
    }

        /* Display results */
    pixd = pixaDisplay(pixad, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixad);

        /* Put the 8 masks all together, and split 5 ways */
    pixad = pixaCreate(0);
    pixs = pixaDisplayOnLattice(pixas, 325, 325, NULL, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);
    pix32 = pixCreate(w, h, 32);
    pixSetAll(pix32);
    pixPaintThroughMask(pix32, pixs, 0, 0, 0xc0c0c000);
    pixSaveTiled(pix32, pixad, 1.0, 1, 30, 32);
    for (i = 0; i < 5; i++) {
        pixc = pixCopy(NULL, pix32);
        boxa = pixSplitIntoBoxa(pixs, minsum[i], skipdist[i],
                                delta[i], maxbg[i], 0, 1);
/*        boxaWriteStream(stderr, boxa); */
        pixd = pixBlendBoxaRandom(pixc, boxa, 0.4);
        pixRenderBoxaArb(pixd, boxa, 2, 255, 0, 0);
        pixSaveTiled(pixd, pixad, 1.0, 0, 30, 32);
        pixDestroy(&pixd);
        pixDestroy(&pixc);
        boxaDestroy(&boxa);
    }
    pixDestroy(&pix32);
    pixDestroy(&pixs);

        /* Display results */
    pixd = pixaDisplay(pixad, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixad);

    pixaDestroy(&pixas);
    return regTestCleanup(rp);
}
Beispiel #8
0
/*!
 *  pixaGenerateFont()
 *
 *      Input:  dir (directory holding image of character set)
 *              size (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
 *
 *  These font generation functions use 9 sets, each with bitmaps
 *  of 94 ascii characters, all in Palatino-Roman font.
 *  Each input bitmap has 3 rows of characters.  The range of
 *  ascii values in each row is as follows:
 *    row 0:  32-57   (32 is a space)
 *    row 1:  58-91   (92, '\', is not represented in this font)
 *    row 2:  93-126 
 *  We LR flip the '/' char to generate a bitmap for the missing
 *  '\' character, so that we have representations of all 95
 *  printable chars.
 *
 *  Computation of the bitmaps and baselines for a single
 *  font takes from 40 to 200 msec on a 2 GHz processor,
 *  depending on the size.  Use pixaGetFont() to read the
 *  generated character set directly from files that were
 *  produced in prog/genfonts.c using this function.
 */
PIXA *
pixaGenerateFont(const char  *dir,
                 l_int32      size,
                 l_int32     *pbl0,
                 l_int32     *pbl1,
                 l_int32     *pbl2)
{
char     *pathname;
l_int32   fileno;
l_int32   i, j, nrows, nrowchars, nchars, h, yval;
l_int32   width, height;
l_int32   baseline[3];
l_int32  *tab;
BOX      *box, *box1, *box2;
BOXA     *boxar, *boxac, *boxacs;
PIX      *pixs, *pixt1, *pixt2, *pixt3;
PIX      *pixr, *pixrc, *pixc;
PIXA     *pixa;

    PROCNAME("pixaGenerateFont");

    if (!pbl0 || !pbl1 || !pbl2)
        return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
    *pbl0 = *pbl1 = *pbl2 = 0;

    fileno = (size / 2) - 2;
    if (fileno < 0 || fileno > NFONTS)
        return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
    tab = makePixelSumTab8();
    pathname = genPathname(dir, inputfonts[fileno]);
    if ((pixs = pixRead(pathname)) == NULL)
        return (PIXA *)ERROR_PTR("pixs not all defined", procName, NULL);
    FREE(pathname);

    pixa = pixaCreate(95);
    pixt1 = pixMorphSequence(pixs, "c1.35 + c101.1", 0);
    boxar = pixConnComp(pixt1, NULL, 8);  /* one box for each row */
    pixDestroy(&pixt1);
    nrows = boxaGetCount(boxar);
#if  DEBUG_FONT_GEN
    fprintf(stderr, "For font %s, number of rows is %d\n",
            inputfonts[fileno], nrows);
#endif  /* DEBUG_FONT_GEN */
    if (nrows != 3) {
        L_INFO_INT2("nrows = %d; skipping font %d", procName, nrows, fileno);
        return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
    }
    for (i = 0; i < nrows; i++) {
        box = boxaGetBox(boxar, i, L_CLONE);
        pixr = pixClipRectangle(pixs, box, NULL);  /* row of chars */
        pixGetTextBaseline(pixr, tab, &yval);
        baseline[i] = yval;

#if DEBUG_BASELINE
      { PIX *pixbl;
        fprintf(stderr, "row %d, yval = %d, h = %d\n",
                i, yval, pixGetHeight(pixr));
        pixbl = pixCopy(NULL, pixr);
        pixRenderLine(pixbl, 0, yval, pixGetWidth(pixbl), yval, 1,
                      L_FLIP_PIXELS);
        if (i == 0 )
            pixWrite("junktl0", pixbl, IFF_PNG);
        else if (i == 1)
            pixWrite("junktl1", pixbl, IFF_PNG);
        else
            pixWrite("junktl2", pixbl, IFF_PNG);
        pixDestroy(&pixbl);
      }
#endif  /* DEBUG_BASELINE */

        boxDestroy(&box);
        pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
        boxac = pixConnComp(pixrc, NULL, 8);
        boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
        if (i == 0) {  /* consolidate the two components of '"' */
            box1 = boxaGetBox(boxacs, 1, L_CLONE);
            box2 = boxaGetBox(boxacs, 2, L_CLONE);
            box1->w = box2->x + box2->w - box1->x;  /* increase width */
            boxDestroy(&box1);
            boxDestroy(&box2);
            boxaRemoveBox(boxacs, 2);
        }
        h = pixGetHeight(pixr);
        nrowchars = boxaGetCount(boxacs);
        for (j = 0; j < nrowchars; j++) {
            box = boxaGetBox(boxacs, j, L_COPY);
            if (box->w <= 2 && box->h == 1) {  /* skip 1x1, 2x1 components */
                boxDestroy(&box);
                continue;
            }
            box->y = 0;
            box->h = h - 1;
            pixc = pixClipRectangle(pixr, box, NULL);
            boxDestroy(&box);
            if (i == 0 && j == 0)  /* add a pix for the space; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            if (i == 2 && j == 0)  /* add a pix for the '\'; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            pixaAddPix(pixa, pixc, L_INSERT);
        }
        pixDestroy(&pixr);
        pixDestroy(&pixrc);
        boxaDestroy(&boxac);
        boxaDestroy(&boxacs);
    }

    nchars = pixaGetCount(pixa);
    if (nchars != 95)
        return (PIXA *)ERROR_PTR("95 chars not generated", procName, NULL);

    *pbl0 = baseline[0];
    *pbl1 = baseline[1];
    *pbl2 = baseline[2];
        
        /* Fix the space character up; it should have no ON pixels,
         * and be about twice as wide as the '!' character.    */
    pixt2 = pixaGetPix(pixa, 0, L_CLONE);
    width = 2 * pixGetWidth(pixt2);
    height = pixGetHeight(pixt2);
    pixDestroy(&pixt2);
    pixt2 = pixCreate(width, height, 1);
    pixaReplacePix(pixa, 0, pixt2, NULL);

        /* Fix up the '\' character; use a LR flip of the '/' char */
    pixt2 = pixaGetPix(pixa, 15, L_CLONE);
    pixt3 = pixFlipLR(NULL, pixt2);
    pixDestroy(&pixt2);
    pixaReplacePix(pixa, 60, pixt3, NULL);
    
#if DEBUG_CHARS
  { PIX *pixd;
    pixd = pixaDisplayTiled(pixa, 1500, 0, 10);
    pixDisplay(pixd, 100 * i, 200);
    pixDestroy(&pixd);
  }
#endif  /* DEBUG_CHARS */

    pixDestroy(&pixs);
    boxaDestroy(&boxar);
    FREE(tab);

    return pixa;
}
Beispiel #9
0
/*!
 *  pixSaveTiledOutline()
 *
 *      Input:  pixs (1, 2, 4, 8, 32 bpp)
 *              pixa (the pix are accumulated here)
 *              reduction (0 to disable; otherwise this is a reduction factor)
 *              newrow (0 if placed on the same row as previous; 1 otherwise)
 *              space (horizontal and vertical spacing, in pixels)
 *              linewidth (width of added outline for image; 0 for no outline)
 *              dp (depth of pixa; 8 or 32 bpp; only used on first call)
 *      Return: 0 if OK, 1 on error.
 *
 *  Notes:
 *      (1) Before calling this function for the first time, use
 *          pixaCreate() to make the @pixa that will accumulate the pix.
 *          This is passed in each time pixSaveTiled() is called.
 *      (2) @reduction is the integer reduction factor for the input
 *          image.  After reduction and possible depth conversion,
 *          the image is saved in the input pixa, along with a box
 *          that specifies the location to place it when tiled later.
 *          Disable saving the pix by setting reduction == 0.
 *      (3) @newrow and @space specify the location of the new pix
 *          with respect to the last one(s) that were entered.
 *      (4) @dp specifies the depth at which all pix are saved.  It can
 *          be only 8 or 32 bpp.  Any colormap is removed.  This is only
 *          used at the first invocation.
 *      (5) This function uses two variables from call to call.
 *          If they were static, the function would not be .so or thread
 *          safe, and furthermore, there would be interference with two or
 *          more pixa accumulating images at a time.  Consequently,
 *          we use the first pix in the pixa to store and obtain both
 *          the depth and the current position of the bottom (one pixel
 *          below the lowest image raster line when laid out using
 *          the boxa).  The bottom variable is stored in the input format
 *          field, which is the only field available for storing an int.
 */
l_int32
pixSaveTiledOutline(PIX     *pixs,
                    PIXA    *pixa,
                    l_int32  reduction,
                    l_int32  newrow,
                    l_int32  space,
                    l_int32  linewidth,
                    l_int32  dp)
{
l_int32         n, top, left, bx, by, bw, w, h, depth, bottom;
l_float32       scale;
BOX            *box;
PIX            *pix, *pixt1, *pixt2, *pixt3;

    PROCNAME("pixSaveTiledOutline");

    if (reduction == 0) return 0;

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixa)
        return ERROR_INT("pixa not defined", procName, 1);

    n = pixaGetCount(pixa);
    if (n == 0) {
        bottom = 0;
        if (dp != 8 && dp != 32) {
            L_WARNING("dp not 8 or 32 bpp; using 32", procName);
            depth = 32;
        } else
            depth = dp;
    }
    else {  /* extract the depth and bottom params from the first pix */
        pix = pixaGetPix(pixa, 0, L_CLONE);
        depth = pixGetDepth(pix);
        bottom = pixGetInputFormat(pix);  /* not typical usage! */
        pixDestroy(&pix);
    }

        /* Scale and convert to output depth */
    if (reduction == 1)
        pixt1 = pixClone(pixs);
    else {
        scale = 1. / (l_float32)reduction;
        if (pixGetDepth(pixs) == 1)
            pixt1 = pixScaleToGray(pixs, scale);
        else
            pixt1 = pixScale(pixs, scale, scale);
    }
    if (depth == 8)
        pixt2 = pixConvertTo8(pixt1, 0);
    else
        pixt2 = pixConvertTo32(pixt1);
    pixDestroy(&pixt1);

        /* Add black outline */
    if (linewidth > 0)
        pixt3 = pixAddBorder(pixt2, linewidth, 0);
    else
        pixt3 = pixClone(pixt2);
    pixDestroy(&pixt2);

        /* Find position of current pix (UL corner plus size) */
    if (n == 0) {
        top = 0;
        left = 0;
    }
    else if (newrow == 1) {
        top = bottom + space;
        left = 0;
    }
    else if (n > 0) {
        pixaGetBoxGeometry(pixa, n - 1, &bx, &by, &bw, NULL);
        top = by;
        left = bx + bw + space;
    }

    pixGetDimensions(pixt3, &w, &h, NULL);
    bottom = L_MAX(bottom, top + h);
    box = boxCreate(left, top, w, h);
    pixaAddPix(pixa, pixt3, L_INSERT);
    pixaAddBox(pixa, box, L_INSERT);

        /* Save the new bottom value */
    pix = pixaGetPix(pixa, 0, L_CLONE);
    pixSetInputFormat(pix, bottom);  /* not typical usage! */
    pixDestroy(&pix);

    return 0;
}
Beispiel #10
0
main(int    argc,
     char **argv)
{
char        *filein, *fileout, *str, *fname, *filename;
char         buffer[512];
l_int32      i, count, npages, length;
FILE        *fp;
NUMA        *naflags, *nasizes;
PIX         *pix, *pixd;
PIXA        *pixa;
PIXCMAP     *cmap;
SARRAY      *savals, *satypes, *sa;
static char  mainName[] = "mtifftest";

    if (argc != 3)
	exit(ERROR_INT(" Syntax:  mtifftest filein fileout", mainName, 1));

    filein = argv[1];
    fileout = argv[2];

#if 1   /* ------------------  Test multipage I/O  -------------------*/
        /* This puts every image file in the directory with a string
         * match to "weasel" into a multipage tiff file.
         * Images with 1 bpp are coded as g4; the others as zip.
         * It then reads back into a pix and displays.  */
    writeMultipageTiff(".", "weasel", "/tmp/junkout.tif");
    pixa = pixaReadMultipageTiff("/tmp/junkout.tif");
    pixd = pixaDisplayTiledInRows(pixa, 1, 1200, 0.5, 0, 15, 4);
    pixDisplay(pixd, 100, 0);
    pixDestroy(&pixd);
    pixd = pixaDisplayTiledInRows(pixa, 8, 1200, 0.8, 0, 15, 4);
    pixDisplay(pixd, 100, 200);
    pixDestroy(&pixd);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1200, 1.2, 0, 15, 4);
    pixDisplay(pixd, 100, 400);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
#endif

#if 0   /* ------------ Test single-to-multipage I/O  -------------------*/
        /* Use 'filein' to specify a directory of tiff files.
	 * Read them in and generate a multipage tiff file.
	 * Then convert that to a G4 compressed and ascii85 encoded
	 * PS file. */
    sa = getFilenamesInDirectory(filein);
    sarrayWriteStream(stderr, sa);
    sarraySort(sa, sa, L_SORT_INCREASING);
    sarrayWriteStream(stderr, sa);
    npages = sarrayGetCount(sa);
    for (i = 0; i < npages; i++) {
        fname = sarrayGetString(sa, i, 0);
        filename = genPathname(filein, fname);
        pix = pixRead(filename);
	if (!pix) continue;
	if (i == 0)
	    pixWriteTiff(tempmtiff, pix, IFF_TIFF_G4, "w+");
        else
	    pixWriteTiff(tempmtiff, pix, IFF_TIFF_G4, "a");
        pixDestroy(&pix);
        lept_free(filename);
    }

        /* write it out as a PS file */
    convertTiffMultipageToPS(tempmtiff, fileout, NULL, 0.95);
    sarrayDestroy(&sa);
#endif

#if 0   /* ------------------  Test multipage I/O  -------------------*/
        /* read count of tiff multipage */
    fp = lept_fopen(filein, "rb");
    if (fileFormatIsTiff(fp)) {
	tiffGetCount(fp, &npages);
	fprintf(stderr, " Tiff: %d page\n", npages);
    }
    else
	exit(ERROR_INT(" file not tiff", mainName, 1));
    lept_fclose(fp);

        /* split into separate page files */
    for (i = 0; i < npages + 1; i++) {   /* read one beyond to catch error */
	pix = pixReadTiff(filein, i);
	if (!pix) continue;
	sprintf(buffer, "/tmp/junkout.%d.tif", i);
	pixWrite(buffer, pix, IFF_TIFF_G4);
        pixDestroy(&pix);
    }

        /* read separate page files and write reversed file */
    for (i = npages - 1; i >= 0; i--) {
	sprintf(buffer, "/tmp/junkout.%d.tif", i);
        pix = pixRead(buffer);
	if (!pix) continue;
	if (i == npages - 1)
	    pixWriteTiff(tempmtiff, pix, IFF_TIFF_G4, "w+");
        else
	    pixWriteTiff(tempmtiff, pix, IFF_TIFF_G4, "a");
        pixDestroy(&pix);
    }

        /* read reversed file and reverse again */
    pixa = pixaCreate(npages);
    for (i = 0; i < 5; i++) {
	pix = pixReadTiff(tempmtiff, i);
	pixaAddPix(pixa, pix, L_INSERT);
    }
    for (i = npages - 1; i >= 0; i--) {
        pix = pixaGetPix(pixa, i, L_CLONE);
	if (i == npages - 1)
	    pixWriteTiff(tempnewmtiff, pix, IFF_TIFF_G4, "w+");
        else
	    pixWriteTiff(tempnewmtiff, pix, IFF_TIFF_G4, "a");
        pixDestroy(&pix);
    }
    pixaDestroy(&pixa);
#endif


#if 0    /* -----   test adding custom public tags to a tiff header ----- */
    pix = pixRead(filein);
    naflags = numaCreate(10);
    savals = sarrayCreate(10);
    satypes = sarrayCreate(10);
    nasizes = numaCreate(10);

/*    numaAddNumber(naflags, TIFFTAG_XMLPACKET);  */ /* XMP:  700 */
    numaAddNumber(naflags, 700);
    str = "<xmp>This is a Fake XMP packet</xmp>\n<text>Guess what ...?</text>";
    length = strlen(str);
    sarrayAddString(savals, str, 1);
    sarrayAddString(satypes, "char*", 1);
    numaAddNumber(nasizes, length);  /* get it all */

    numaAddNumber(naflags, 269);  /* DOCUMENTNAME */
    sarrayAddString(savals, "One silly title", 1);
    sarrayAddString(satypes, "char*", 1);
    numaAddNumber(naflags, 270);  /* IMAGEDESCRIPTION */
    sarrayAddString(savals, "One page of text", 1);
    sarrayAddString(satypes, "char*", 1);
        /* the max sample is used by rendering programs
         * to scale the dynamic range */
    numaAddNumber(naflags, 281);  /* MAXSAMPLEVALUE */
    sarrayAddString(savals, "4", 1);
    sarrayAddString(satypes, "l_uint16", 1);
        /* note that date is required to be a 20 byte string */
    numaAddNumber(naflags, 306);  /* DATETIME */
    sarrayAddString(savals, "2004:10:11 09:35:15", 1);
    sarrayAddString(satypes, "char*", 1);
        /* note that page number requires 2 l_uint16 input */
    numaAddNumber(naflags, 297);  /* PAGENUMBER */
    sarrayAddString(savals, "1-412", 1);
    sarrayAddString(satypes, "l_uint16-l_uint16", 1);
    pixWriteTiffCustom(fileout, pix, IFF_TIFF_G4, "w", naflags,
                       savals, satypes, nasizes);
    fprintTiffInfo(stderr, fileout);
    numaDestroy(&naflags);
    numaDestroy(&nasizes);
    sarrayDestroy(&savals);
    sarrayDestroy(&satypes);
    pixDestroy(&pix);
#endif

    return 0;
}
Beispiel #11
0
l_int32 main(int    argc,
             char **argv)
{
char         *dir, *path;
char         *str1 = NULL;
char         *chara, *chara2;
char          buf[256];
l_uint8      *data1, *data2, *data3, *data4;
l_int32       w, h, i, n, bx, by, bw, bh, nchar, nbytes, ret;
l_int32      *rtable64;
l_uint32      pixval;
size_t        nbytes1, nbytes2, nout, nout2, nout3;
L_BMF        *bmf;
BOX          *box1, *box2;
BOXA         *boxa;
PIX          *pix, *pixs, *pixm, *pixg, *pixd;
PIX          *pix0, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
PIXA         *pixas, *pixa1, *pixa2, *pixa3;
L_RECOG      *recog;
L_STRCODE    *strc;

    if (argc != 1) {
        fprintf(stderr, " Syntax: recog_bootnum\n");
        return 1;
    }

    lept_mkdir("lept/recog/digits");

    /* ----------------------- Bootnum 1 --------------------- */
        /* Make the bootnum pixa from the images */
    pixa1 = MakeBootnum1();
    pixaWrite("/tmp/lept/recog/digits/bootnum1.pa", pixa1);
    pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000);
    pixDisplay(pix1, 100, 0);
    pixDestroy(&pix1);
    pixaDestroy(&pixa1);

        /* Generate the code to make the bootnum1 pixa.
         * Note: the actual code we use is in bootnumgen1.c, and
         * has already been compiled into the library. */
    strc = strcodeCreate(101);  /* arbitrary integer */
    strcodeGenerate(strc, "/tmp/lept/recog/digits/bootnum1.pa", "PIXA");
    strcodeFinalize(&strc, "/tmp/lept/auto");
    lept_free(strc);

        /* Generate the bootnum1 pixa from the generated code */
    pixa1 = (PIXA *)l_bootnum_gen1();
    pix1 = pixaDisplayTiledWithText(pixa1, 1500, 1.0, 10, 2, 6, 0xff000000);
/*    pix1 = pixaDisplayTiled(pixa1, 1500, 0, 30); */
    pixDisplay(pix1, 100, 0);
    pixDestroy(&pix1);

        /* Extend the bootnum1 pixa by erosion */
    pixa3 = pixaExtendIterative(pixa1, L_MORPH_ERODE, 2, NULL, 1);
    pix1 = pixaDisplayTiledWithText(pixa3, 1500, 1.0, 10, 2, 6, 0xff000000);
    pixDisplay(pix1, 100, 0);
    pixDestroy(&pix1);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa3);

    /* ----------------------- Bootnum 2 --------------------- */
        /* Make the bootnum pixa from the images */
    L_INFO("the 4 errors below are due to bad input\n", "recog_bootnum");
    pixa2 = MakeBootnum2();
    pix1 = pixaDisplayTiledWithText(pixa2, 1500, 1.0, 10, 2, 6, 0xff000000);
    pixDisplay(pix1, 100, 700);
    pixDestroy(&pix1);
    pixaDestroy(&pixa2);

        /* Generate the code to make the bootnum2 pixa.
         * Note: the actual code we use is in bootnumgen2.c. */
    strc = strcodeCreate(102);  /* another arbitrary integer */
    strcodeGenerate(strc, "/tmp/lept/recog/digits/bootnum2.pa", "PIXA");
    strcodeFinalize(&strc, "/tmp/lept/auto");
    lept_free(strc);

        /* Generate the bootnum2 pixa from the generated code */
    pixa2 = (PIXA *)l_bootnum_gen2();
/*    pix1 = pixaDisplayTiled(pixa2, 1500, 0, 30);  */
    pix1 = pixaDisplayTiledWithText(pixa2, 1500, 1.0, 10, 2, 6, 0xff000000);
    pixDisplay(pix1, 100, 700);
    pixDestroy(&pix1);
    pixaDestroy(&pixa2);


#if 0
    pixas = (PIXA *)l_bootnum_gen1();
/*    pixas = pixaRead("recog/digits/bootnum1.pa"); */
    pixaWrite("/tmp/junk.pa", pixas);
    pixa1 = pixaRead("/tmp/junk.pa");
    pixaWrite("/tmp/junk1.pa", pixa1);
    pixa = pixaRead("/tmp/junk1.pa");
    n = pixaGetCount(pixa);
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixa, i, L_CLONE);
        fprintf(stderr, "i = %d, text = %s\n", i, pixGetText(pix));
        pixDestroy(&pix);
    }
#endif

    return 0;
}
Beispiel #12
0
char*
generate_fonts (const JBDATA * data, const struct mapping *maps,
		int num_fonts, char *dir)
{
  int dirnamelen = 0;
  char *dirname = NULL;

  if (dir == NULL)
    {

      /* Create a file in the system temp dir (usually /tmp) */
      /* This may not be portable to Windows */
      char suffix[] = "smoothscan_XXXXXX";
      /* Use the value of environmental var TMPDIR if it is set */
      char *tmpdir = getenv ("TMPDIR");
      if (tmpdir == NULL)
	{
	  /* Load the default temp directory */
	  tmpdir = P_tmpdir;
	}

      int tmpdirlen = strlen (tmpdir);
      int suffixlen = strlen (suffix);

      dirnamelen = tmpdirlen + suffixlen + 1;

      dirname = malloc_guarded (dirnamelen + 1);

      sprintf (dirname, "%s/%s", tmpdir, suffix);

      if (mkdtemp (dirname) == NULL)
	{
	  error_quit ("Failed to create main temp directory.");
	}
    }
  else
    {
      if (mkdir (dir, 0700) == -1)
	{
	  if (errno != EEXIST)
	    {
	      error_quit ("Couldn't make tmpdir.");
	    }
	}
      dirname = dir;
      dirnamelen = strlen (dir);
    }

  int i;

  PIXA *templates =
    pixaCreateFromPix (data->pix, data->nclass, data->latticew,
		       data->latticeh);

  if (templates == NULL)
    {
      error_quit ("Could not create templates from JBDATA.");
    }

  /* Create a temp dir for each font */
  char **fontdirnames = malloc_guarded (num_fonts * sizeof (char *));
  int *fontdirlens = malloc_guarded (num_fonts * sizeof (int *));

  for (i = 0; i < num_fonts; i++)
    {
      /* 1 for / 8 for %08d */
      fontdirlens[i] = dirnamelen + 1 + 8;
      fontdirnames[i] = malloc_guarded (fontdirlens[i] + 1);

      sprintf (fontdirnames[i], "%s/%08d", dirname, i);

      if (mkdir (fontdirnames[i], 0700) == -1)
	{
	  error_quit ("Failed to create font temp directory.");
	}
    }


  for (i = 0; i < templates->n; i++)
    {
      l_int32 iclass;
      l_int32 x;
      l_int32 y;

      numaGetIValue (data->naclass, i, &iclass);
      ptaGetIPt (data->ptaul, i, &x, &y);
      PIX *pix_clone = pixaGetPix (templates, i, L_CLONE);	/* the template */
      double wp1 = pixGetWidth (pix_clone);
      double hp1 = pixGetHeight (pix_clone);
      PIX *pix_padded =
	pixAddBorderGeneral (pix_clone, 0, data->latticew - wp1, 0,
			     data->latticeh - hp1, 0);

      if (pix_padded == NULL)
	{
	  error_quit ("Failed to add border to image.");
	}

      int fontn = maps[i].font_num;
      int code_point = maps[i].code_point;

      /* 1 for '/', 3 for %03d, 4 for '.png' */
      int filenamelen = fontdirlens[fontn] + 1 + 3 + 4;
      char *filename = malloc_guarded (filenamelen + 1);

      sprintf (filename, "%s/%03d.png", fontdirnames[fontn], code_point);

      if (pixWrite (filename, pix_padded, IFF_PNG) == 1)
	{
	  printf ("pixWrite failed to write %s.\n", filename);
	  error_quit ("Could not write to file.");
	}

      pixDestroy (&pix_clone);
      pixDestroy (&pix_padded);
      free (filename);
    }

  pixaDestroy (&templates);

  /* This part probably won't port over to Windows as well */

  /* TODO: parallelize this */
  for (i = 0; i < num_fonts; i++)
    {
      /* 1 for '/', 8 for %08d, 4 for '.ttf' */
      int fontnamelen = dirnamelen + 1 + 8 + 4;
      char *fontnamestr = malloc_guarded (fontnamelen + 1);
      sprintf (fontnamestr, "%s/%08d.ttf", dirname, i);

      create_font_from_dir (fontdirnames[i], fontnamestr, data->latticeh,
			    data->latticew, i);
      free (fontnamestr);
    }

  /* clean up */
  for (i = 0; i < num_fonts; i++)
    {
      free (fontdirnames[i]);
    }
  free (fontdirnames);
  free (fontdirlens);

  return dirname;
}
Beispiel #13
0
main(int    argc,
     char **argv)
{
l_int32     i, n;
l_float32   pi, angle, val;
BOX        *box;
BOXA       *boxa, *boxa1, *boxa2;
NUMA       *na1, *na2;
PIX        *pix, *pix1, *pix2, *pix3, *pixd;
PIXA       *pixa1, *pixa2, *pixa3, *pixa4;
static char     mainName[] = "inserttest";

#if 1
    pi = 3.1415926535;
    na1 = numaCreate(500);
    for (i = 0; i < 500; i++) {
        angle = 0.02293 * i * pi;
        val = (l_float32)sin(angle);
        numaAddNumber(na1, val);
    }
    numaWrite("/tmp/junknuma1", na1);
    na2 = numaCopy(na1);
    n = numaGetCount(na2);
    for (i = 0; i < n; i++) {
      numaGetFValue(na2, i, &val);
      numaRemoveNumber(na2, i);
      numaInsertNumber(na2, i, val);
    }
    numaWrite("/tmp/junknuma2", na2);
    numaDestroy(&na1);
    numaDestroy(&na2);
#endif

#if 1
    pix1 = pixRead("feyn.tif");
    box = boxCreate(1138, 1666, 1070, 380);
    pix2 = pixClipRectangle(pix1, box, NULL);
    boxDestroy(&box);
    boxa1 = pixConnComp(pix2, NULL, 8);
    boxaWrite("/tmp/junkboxa1", boxa1);
    boxa2 = boxaCopy(boxa1, L_COPY);
    n = boxaGetCount(boxa2);
    for (i = 0; i < n; i++) {
      box = boxaGetBox(boxa2, i, L_COPY);
      boxaRemoveBox(boxa2, i);
      boxaInsertBox(boxa2, i, box);
    }
    boxaWrite("/tmp/junkboxa2", boxa2);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
#endif

#if 1
    pix1 = pixRead("feyn.tif");
    box = boxCreate(1138, 1666, 1070, 380);
    pix2 = pixClipRectangle(pix1, box, NULL);
    boxDestroy(&box);
    boxa = pixConnComp(pix2, &pixa1, 8);
    boxaDestroy(&boxa);
    pixaWrite("/tmp/junkpixa1", pixa1);

    pixa2 = pixaCopy(pixa1, L_COPY);
    n = pixaGetCount(pixa2);
        /* Remove and insert each one */
    for (i = 0; i < n; i++) {
      pix = pixaGetPix(pixa2, i, L_COPY);
      box = pixaGetBox(pixa2, i, L_COPY);
      pixaRemovePix(pixa2, i);
      pixaInsertPix(pixa2, i, pix, box);
    }
    pixaWrite("/tmp/junkpixa2", pixa2);

        /* Move the last to the beginning; do it n times */
    pixa3 = pixaCopy(pixa2, L_COPY);
    for (i = 0; i < n; i++) {
      pix = pixaGetPix(pixa3, n - 1, L_CLONE);
      box = pixaGetBox(pixa3, n - 1, L_CLONE);
      pixaInsertPix(pixa3, 0, pix, box);
      pixaRemovePix(pixa3, n);
    }
    pixaWrite("/tmp/junkpixa3", pixa3);

        /* Move the first one to the end; do it n times */
    pixa4 = pixaCopy(pixa3, L_COPY);
    for (i = 0; i < n; i++) {
      pix = pixaGetPix(pixa4, 0, L_CLONE);
      box = pixaGetBox(pixa4, 0, L_CLONE);
      pixaInsertPix(pixa4, n, pix, box);  /* make sure insert works at end */
      pixaRemovePix(pixa4, 0);
    }
    pixaWrite("/tmp/junkpixa4", pixa4);

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    pixaDestroy(&pixa3);
    pixaDestroy(&pixa4);
#endif

    return 0;
}