/*! * \brief bbufferCreate() * * \param[in] indata address in memory [optional] * \param[in] nalloc size of byte array to be alloc'd 0 for default * \return bbuffer, or NULL on error * * <pre> * Notes: * (1) If a buffer address is given, you should read all the data in. * (2) Allocates a bbuffer with associated byte array of * the given size. If a buffer address is given, * it then reads the number of bytes into the byte array. * </pre> */ L_BBUFFER * bbufferCreate(l_uint8 *indata, l_int32 nalloc) { L_BBUFFER *bb; PROCNAME("bbufferCreate"); if (nalloc <= 0) nalloc = INITIAL_BUFFER_ARRAYSIZE; if ((bb = (L_BBUFFER *)LEPT_CALLOC(1, sizeof(L_BBUFFER))) == NULL) return (L_BBUFFER *)ERROR_PTR("bb not made", procName, NULL); if ((bb->array = (l_uint8 *)LEPT_CALLOC(nalloc, sizeof(l_uint8))) == NULL) { LEPT_FREE(bb); return (L_BBUFFER *)ERROR_PTR("byte array not made", procName, NULL); } bb->nalloc = nalloc; bb->nwritten = 0; if (indata) { memcpy((l_uint8 *)bb->array, indata, nalloc); bb->n = nalloc; } else { bb->n = 0; } return bb; }
/*! * \brief boxaaQuadtreeRegions() * * \param[in] w, h size of pix that is being quadtree-ized * \param[in] nlevels number of levels in quadtree * \return baa for quadtree regions at each level, or NULL on error * * <pre> * Notes: * (1) The returned boxaa has %nlevels of boxa, each containing * the set of rectangles at that level. The rectangle at * level 0 is the entire region; at level 1 the region is * divided into 4 rectangles, and at level n there are n^4 * rectangles. * (2) At each level, the rectangles in the boxa are in "raster" * order, with LR (fast scan) and TB (slow scan). * </pre> */ BOXAA * boxaaQuadtreeRegions(l_int32 w, l_int32 h, l_int32 nlevels) { l_int32 i, j, k, maxpts, nside, nbox, bw, bh; l_int32 *xstart, *xend, *ystart, *yend; BOX *box; BOXA *boxa; BOXAA *baa; PROCNAME("boxaaQuadtreeRegions"); if (nlevels < 1) return (BOXAA *)ERROR_PTR("nlevels must be >= 1", procName, NULL); if (w < (1 << (nlevels - 1))) return (BOXAA *)ERROR_PTR("w doesn't support nlevels", procName, NULL); if (h < (1 << (nlevels - 1))) return (BOXAA *)ERROR_PTR("h doesn't support nlevels", procName, NULL); baa = boxaaCreate(nlevels); maxpts = 1 << (nlevels - 1); xstart = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32)); xend = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32)); ystart = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32)); yend = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32)); for (k = 0; k < nlevels; k++) { nside = 1 << k; /* number of boxes in each direction */ for (i = 0; i < nside; i++) { xstart[i] = (w - 1) * i / nside; if (i > 0) xstart[i]++; xend[i] = (w - 1) * (i + 1) / nside; ystart[i] = (h - 1) * i / nside; if (i > 0) ystart[i]++; yend[i] = (h - 1) * (i + 1) / nside; #if DEBUG_BOXES fprintf(stderr, "k = %d, xs[%d] = %d, xe[%d] = %d, ys[%d] = %d, ye[%d] = %d\n", k, i, xstart[i], i, xend[i], i, ystart[i], i, yend[i]); #endif /* DEBUG_BOXES */ } nbox = 1 << (2 * k); boxa = boxaCreate(nbox); for (i = 0; i < nside; i++) { bh = yend[i] - ystart[i] + 1; for (j = 0; j < nside; j++) { bw = xend[j] - xstart[j] + 1; box = boxCreate(xstart[j], ystart[i], bw, bh); boxaAddBox(boxa, box, L_INSERT); } } boxaaAddBoxa(baa, boxa, L_INSERT); } LEPT_FREE(xstart); LEPT_FREE(xend); LEPT_FREE(ystart); LEPT_FREE(yend); return baa; }
/*! * \brief sudokuCreate() * * \param[in] array of 81 numbers, 9 rows of 9 numbers each * \return l_sudoku, or NULL on error * * <pre> * Notes: * (1) The input array has 0 for the unknown values, and 1-9 * for the known initial values. It is generated from * a file using sudokuReadInput(), which checks that the file * data has 81 numbers in 9 rows. * </pre> */ L_SUDOKU * sudokuCreate(l_int32 *array) { l_int32 i, val, locs_index; L_SUDOKU *sud; PROCNAME("sudokuCreate"); if (!array) return (L_SUDOKU *)ERROR_PTR("array not defined", procName, NULL); locs_index = 0; /* into locs array */ sud = (L_SUDOKU *)LEPT_CALLOC(1, sizeof(L_SUDOKU)); sud->locs = (l_int32 *)LEPT_CALLOC(81, sizeof(l_int32)); sud->init = (l_int32 *)LEPT_CALLOC(81, sizeof(l_int32)); sud->state = (l_int32 *)LEPT_CALLOC(81, sizeof(l_int32)); for (i = 0; i < 81; i++) { val = array[i]; sud->init[i] = val; sud->state[i] = val; if (val == 0) sud->locs[locs_index++] = i; } sud->num = locs_index; sud->failure = FALSE; sud->finished = FALSE; return sud; }
/*! * \brief recogCreateDid() * * \param[in] recog * \param[in] pixs of 1 bpp image to match * \return 0 if OK, 1 on error */ l_int32 recogCreateDid(L_RECOG *recog, PIX *pixs) { l_int32 i; PIX *pixt; L_RDID *did; PROCNAME("recogCreateDid"); if (!recog) return ERROR_INT("recog not defined", procName, 1); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); recogDestroyDid(recog); did = (L_RDID *)LEPT_CALLOC(1, sizeof(L_RDID)); recog->did = did; did->pixs = pixClone(pixs); did->narray = recog->setsize; did->size = pixGetWidth(pixs); did->natempl = numaCreate(5); did->naxloc = numaCreate(5); did->nadely = numaCreate(5); did->nawidth = numaCreate(5); did->nascore = numaCreate(5); did->natempl_r = numaCreate(5); did->naxloc_r = numaCreate(5); did->nadely_r = numaCreate(5); did->nawidth_r = numaCreate(5); did->nascore_r = numaCreate(5); /* Make the arrays */ did->setwidth = (l_int32 *)LEPT_CALLOC(did->narray, sizeof(l_int32)); did->counta = (l_int32 **)LEPT_CALLOC(did->narray, sizeof(l_int32 *)); did->delya = (l_int32 **)LEPT_CALLOC(did->narray, sizeof(l_int32 *)); did->beta = (l_float32 *)LEPT_CALLOC(5, sizeof(l_float32)); did->gamma = (l_float32 *)LEPT_CALLOC(5, sizeof(l_float32)); did->trellisscore = (l_float32 *)LEPT_CALLOC(did->size, sizeof(l_float32)); did->trellistempl = (l_int32 *)LEPT_CALLOC(did->size, sizeof(l_int32)); for (i = 0; i < did->narray; i++) { did->counta[i] = (l_int32 *)LEPT_CALLOC(did->size, sizeof(l_int32)); did->delya[i] = (l_int32 *)LEPT_CALLOC(did->size, sizeof(l_int32)); } /* Populate the setwidth array */ for (i = 0; i < did->narray; i++) { pixt = pixaGetPix(recog->pixa_u, i, L_CLONE); did->setwidth[i] = (l_int32)(SetwidthFraction * pixGetWidth(pixt)); pixDestroy(&pixt); } return 0; }
/*! * \brief bbufferDestroyAndSaveData() * * \param[in,out] pbb buffer to be nulled * \param[out] pnbytes number of bytes saved in array * \return barray newly allocated array of data * * <pre> * Notes: * (1) Copies data to newly allocated array; then destroys the bbuffer. * </pre> */ l_uint8 * bbufferDestroyAndSaveData(L_BBUFFER **pbb, size_t *pnbytes) { l_uint8 *array; size_t nbytes; L_BBUFFER *bb; PROCNAME("bbufferDestroyAndSaveData"); if (pbb == NULL) { L_WARNING("ptr address is NULL\n", procName); return NULL; } if (pnbytes == NULL) { L_WARNING("&nbytes is NULL\n", procName); bbufferDestroy(pbb); return NULL; } if ((bb = *pbb) == NULL) return NULL; /* write all unwritten bytes out to a new array */ nbytes = bb->n - bb->nwritten; *pnbytes = nbytes; if ((array = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL) { L_WARNING("calloc failure for array\n", procName); return NULL; } memcpy((void *)array, (void *)(bb->array + bb->nwritten), nbytes); bbufferDestroy(pbb); return array; }
/*! * \brief makeMSBitLocTab() * * \param[in] bitval either 0 or 1 * \return table giving, for an input byte, the MS bit location, * starting at 0 with the MSBit in the byte, * or NULL on error. * * <pre> * Notes: * (1) If bitval == 1, it finds the leftmost ON pixel in a byte; * otherwise if bitval == 0, it finds the leftmost OFF pixel. * (2) If there are no pixels of the indicated color in the byte, * this returns 8. * </pre> */ l_int32 * makeMSBitLocTab(l_int32 bitval) { l_int32 i, j; l_int32 *tab; l_uint8 byte, mask; PROCNAME("makeMSBitLocTab"); if ((tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32))) == NULL) return (l_int32 *)ERROR_PTR("tab not made", procName, NULL); for (i = 0; i < 256; i++) { byte = (l_uint8)i; if (bitval == 0) byte = ~byte; tab[i] = 8; mask = 0x80; for (j = 0; j < 8; j++) { if (byte & mask) { tab[i] = j; break; } mask >>= 1; } } return tab; }
static l_uint32 * makeExpandTab4x(void) { l_uint32 *tab; l_int32 i; PROCNAME("makeExpandTab4x"); if ((tab = (l_uint32 *) LEPT_CALLOC(256, sizeof(l_uint32))) == NULL) return (l_uint32 *)ERROR_PTR("tab not made", procName, NULL); for (i = 0; i < 256; i++) { if (i & 0x01) tab[i] = 0xf; if (i & 0x02) tab[i] |= 0xf0; if (i & 0x04) tab[i] |= 0xf00; if (i & 0x08) tab[i] |= 0xf000; if (i & 0x10) tab[i] |= 0xf0000; if (i & 0x20) tab[i] |= 0xf00000; if (i & 0x40) tab[i] |= 0xf000000; if (i & 0x80) tab[i] |= 0xf0000000; } return tab; }
/*! * \brief jpeg_comment_callback() * * Notes: * (1) This is used to read the jpeg comment (JPEG_COM). * See the note above the declaration for why it returns * a "boolean". */ static boolean jpeg_comment_callback(j_decompress_ptr cinfo) { l_int32 length, i; l_uint8 *comment; struct callback_data *pcb_data; /* Get the size of the comment */ length = jpeg_getc(cinfo) << 8; length += jpeg_getc(cinfo); length -= 2; if (length <= 0) return 1; /* Extract the comment from the file */ if ((comment = (l_uint8 *)LEPT_CALLOC(length + 1, sizeof(l_uint8))) == NULL) return 0; for (i = 0; i < length; i++) comment[i] = jpeg_getc(cinfo); /* Save the comment and return */ pcb_data = (struct callback_data *)cinfo->client_data; pcb_data->comment = comment; return 1; }
/*! * barcodeDecode39() * * Input: barstr (of widths, in set {1, 2}) * debugflag * Return: data (string of digits), or null if none found or on error * * Notes: * (1) Ref: http://en.wikipedia.org/wiki/Code39 * http://morovia.com/education/symbology/code39.asp * (2) Each symbol has 5 black and 4 white bars. * The start and stop codes are 121121211 (the asterisk) * (3) This decoder was contributed by Roger Hyde. */ static char * barcodeDecode39(char *barstr, l_int32 debugflag) { char *data, *vbarstr; char code[10]; l_int32 valid, reverse, i, j, len, error, nsymb, start, found; PROCNAME("barcodeDecode39"); if (!barstr) return (char *)ERROR_PTR("barstr not defined", procName, NULL); /* Verify format; reverse if necessary */ barcodeVerifyFormat(barstr, L_BF_CODE39, &valid, &reverse); if (!valid) return (char *)ERROR_PTR("barstr not in code39 format", procName, NULL); if (reverse) vbarstr = stringReverse(barstr); else vbarstr = stringNew(barstr); /* Verify size */ len = strlen(vbarstr); if ((len + 1) % 10 != 0) return (char *)ERROR_PTR("size+1 not divisible by 10: invalid code 39", procName, NULL); /* Decode the symbols */ nsymb = (len - 19) / 10; data = (char *)LEPT_CALLOC(nsymb + 1, sizeof(char)); memset(code, 0, 10); error = FALSE; for (i = 0; i < nsymb; i++) { start = 10 + 10 * i; for (j = 0; j < 9; j++) code[j] = vbarstr[start + j]; if (debugflag) fprintf(stderr, "code: %s\n", code); found = FALSE; for (j = 0; j < C39_START; j++) { if (!strcmp(code, Code39[j])) { data[i] = Code39Val[j]; found = TRUE; break; } } if (!found) error = TRUE; } LEPT_FREE(vbarstr); if (error) { LEPT_FREE(data); return (char *)ERROR_PTR("error in decoding", procName, NULL); } return data; }
/*! * \brief l_productMat4() * * \param[in] mat1 square matrix, as a 1-dimensional size^2 array * \param[in] mat2 square matrix, as a 1-dimensional size^2 array * \param[in] mat3 square matrix, as a 1-dimensional size^2 array * \param[in] mat4 square matrix, as a 1-dimensional size^2 array * \param[in] matd square matrix; product stored here * \param[in] size of matrices * \return 0 if OK, 1 on error */ l_int32 l_productMat4(l_float32 *mat1, l_float32 *mat2, l_float32 *mat3, l_float32 *mat4, l_float32 *matd, l_int32 size) { l_float32 *matt; PROCNAME("l_productMat4"); if (!mat1) return ERROR_INT("matrix 1 not defined", procName, 1); if (!mat2) return ERROR_INT("matrix 2 not defined", procName, 1); if (!mat3) return ERROR_INT("matrix 3 not defined", procName, 1); if (!matd) return ERROR_INT("result matrix not defined", procName, 1); if ((matt = (l_float32 *)LEPT_CALLOC(size * size, sizeof(l_float32))) == NULL) return ERROR_INT("matt not made", procName, 1); l_productMat3(mat1, mat2, mat3, matt, size); l_productMat2(matt, mat4, matd, size); LEPT_FREE(matt); return 0; }
/*! * barcodeDecode2of5() * * Input: barstr (of widths, in set {1, 2}) * debugflag * Return: data (string of digits), or null if none found or on error * * Notes: * (1) Ref: http://en.wikipedia.org/wiki/Two-out-of-five_code (Note: * the codes given here are wrong!) * http://morovia.com/education/symbology/code25.asp * (2) This is a very low density encoding for the 10 digits. * Each digit is encoded with 5 black bars, of which 2 are wide * and 3 are narrow. No information is carried in the spaces * between the bars, which are all equal in width, represented by * a "1" in our encoding. * (3) The mapping from the sequence of five bar widths to the * digit is identical to the mapping used by the interleaved * 2 of 5 code. The start code is 21211, representing two * wide bars and a narrow bar, and the interleaved "1" spaces * are explicit. The stop code is 21112. For all codes * (including start and stop), the trailing space "1" is * implicit -- there is no reason to represent it in the * Code2of5[] array. */ static char * barcodeDecode2of5(char *barstr, l_int32 debugflag) { char *data, *vbarstr; char code[10]; l_int32 valid, reverse, i, j, len, error, ndigits, start, found; PROCNAME("barcodeDecodeI2of5"); if (!barstr) return (char *)ERROR_PTR("barstr not defined", procName, NULL); /* Verify format; reverse if necessary */ barcodeVerifyFormat(barstr, L_BF_CODE2OF5, &valid, &reverse); if (!valid) return (char *)ERROR_PTR("barstr not in 2of5 format", procName, NULL); if (reverse) vbarstr = stringReverse(barstr); else vbarstr = stringNew(barstr); /* Verify size */ len = strlen(vbarstr); if ((len - 11) % 10 != 0) return (char *)ERROR_PTR("size not divisible by 10: invalid 2of5 code", procName, NULL); error = FALSE; ndigits = (len - 11) / 10; data = (char *)LEPT_CALLOC(ndigits + 1, sizeof(char)); memset(code, 0, 10); for (i = 0; i < ndigits; i++) { start = 6 + 10 * i; for (j = 0; j < 9; j++) code[j] = vbarstr[start + j]; if (debugflag) fprintf(stderr, "code: %s\n", code); found = FALSE; for (j = 0; j < 10; j++) { if (!strcmp(code, Code2of5[j])) { data[i] = 0x30 + j; found = TRUE; break; } } if (!found) error = TRUE; } LEPT_FREE(vbarstr); if (error) { LEPT_FREE(data); return (char *)ERROR_PTR("error in decoding", procName, NULL); } return data; }
/*! * recogCreate() * * Input: scalew (scale all widths to this; use 0 for no scaling) * scaleh (scale all heights to this; use 0 for no scaling) * templ_type (L_USE_AVERAGE or L_USE_ALL) * threshold (for binarization; typically ~128) * maxyshift (from nominal centroid alignment; typically 0 or 1) * Return: recog, or null on error * * Notes: * (1) For a set trained on one font, such as numbers in a book, * it is sensible to set scalew = scaleh = 0. * (2) For a mixed training set, scaling to a fixed height, * such as 32 pixels, but leaving the width unscaled, is effective. * (3) The storage for most of the arrays is allocated when training * is finished. */ L_RECOG * recogCreate(l_int32 scalew, l_int32 scaleh, l_int32 templ_type, l_int32 threshold, l_int32 maxyshift) { L_RECOG *recog; PIXA *pixa; PIXAA *paa; PROCNAME("recogCreate"); if (scalew < 0 || scaleh < 0) return (L_RECOG *)ERROR_PTR("invalid scalew or scaleh", procName, NULL); if (templ_type != L_USE_AVERAGE && templ_type != L_USE_ALL) return (L_RECOG *)ERROR_PTR("invalid templ_type flag", procName, NULL); if (threshold < 1 || threshold > 255) return (L_RECOG *)ERROR_PTR("invalid threshold", procName, NULL); if ((recog = (L_RECOG *)LEPT_CALLOC(1, sizeof(L_RECOG))) == NULL) return (L_RECOG *)ERROR_PTR("rec not made", procName, NULL); recog->templ_type = templ_type; recog->threshold = threshold; recog->scalew = scalew; recog->scaleh = scaleh; recog->maxyshift = maxyshift; recog->asperity_fr = DEFAULT_ASPERITY_FRACT; recogSetPadParams(recog, NULL, NULL, NULL, 0, -1, -1, -1, -1); recog->bmf = bmfCreate(NULL, 6); recog->bmf_size = 6; recog->maxarraysize = MAX_EXAMPLES_IN_CLASS; recog->index = -1; /* Generate the LUTs */ recog->centtab = makePixelCentroidTab8(); recog->sumtab = makePixelSumTab8(); recog->sa_text = sarrayCreate(0); recog->dna_tochar = l_dnaCreate(0); /* Input default values for min component size for splitting. * These are overwritten when pixTrainingFinished() is called. */ recog->min_splitw = 6; recog->min_splith = 6; recog->max_splith = 60; /* Generate the storage for the unscaled training bitmaps */ paa = pixaaCreate(recog->maxarraysize); pixa = pixaCreate(1); pixaaInitFull(paa, pixa); pixaDestroy(&pixa); recog->pixaa_u = paa; /* Generate the storage for debugging */ recog->pixadb_boot = pixaCreate(2); recog->pixadb_split = pixaCreate(2); return recog; }
/*! * ptraaCreate() * * Input: size of ptr array to be alloc'd * Return: paa, or null on error * * Notes: * (1) The ptraa is generated with a fixed size, that can not change. * The ptra can be generated and inserted randomly into this array. */ L_PTRAA * ptraaCreate(l_int32 n) { L_PTRAA *paa; PROCNAME("ptraaCreate"); if (n <= 0) return (L_PTRAA *)ERROR_PTR("n must be > 0", procName, NULL); if ((paa = (L_PTRAA *)LEPT_CALLOC(1, sizeof(L_PTRAA))) == NULL) return (L_PTRAA *)ERROR_PTR("paa not made", procName, NULL); if ((paa->ptra = (L_PTRA **)LEPT_CALLOC(n, sizeof(L_PTRA *))) == NULL) return (L_PTRAA *)ERROR_PTR("ptr array not made", procName, NULL); paa->nalloc = n; return paa; }
/*! * \brief lqueueCreate() * * \param[in] nalloc size of ptr array to be alloc'd; 0 for default * \return lqueue, or NULL on error * * <pre> * Notes: * (1) Allocates a ptr array of given size, and initializes counters. * </pre> */ L_QUEUE * lqueueCreate(l_int32 nalloc) { L_QUEUE *lq; PROCNAME("lqueueCreate"); if (nalloc < MIN_BUFFER_SIZE) nalloc = INITIAL_BUFFER_ARRAYSIZE; lq = (L_QUEUE *)LEPT_CALLOC(1, sizeof(L_QUEUE)); if ((lq->array = (void **)LEPT_CALLOC(nalloc, sizeof(void *))) == NULL) { lqueueDestroy(&lq, 0); return (L_QUEUE *)ERROR_PTR("ptr array not made", procName, NULL); } lq->nalloc = nalloc; lq->nhead = lq->nelem = 0; return lq; }
/*! * \brief l_byteaCreate() * * \param[in] nbytes determines initial size of data array * \return l_bytea, or NULL on error * * <pre> * Notes: * (1) The allocated array is n + 1 bytes. This allows room * for null termination. * </pre> */ L_BYTEA * l_byteaCreate(size_t nbytes) { L_BYTEA *ba; PROCNAME("l_byteaCreate"); if (nbytes <= 0) nbytes = INITIAL_ARRAYSIZE; if ((ba = (L_BYTEA *)LEPT_CALLOC(1, sizeof(L_BYTEA))) == NULL) return (L_BYTEA *)ERROR_PTR("ba not made", procName, NULL); if ((ba->data = (l_uint8 *)LEPT_CALLOC(nbytes + 1, sizeof(l_uint8))) == NULL) return (L_BYTEA *)ERROR_PTR("ba array not made", procName, NULL); ba->nalloc = nbytes + 1; ba->refcount = 1; return ba; }
/*! * numaaCreate() * * Input: size of numa ptr array to be alloc'd (0 for default) * Return: naa, or null on error * */ NUMAA * numaaCreate(l_int32 n) { NUMAA *naa; PROCNAME("numaaCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((naa = (NUMAA *)LEPT_CALLOC(1, sizeof(NUMAA))) == NULL) return (NUMAA *)ERROR_PTR("naa not made", procName, NULL); if ((naa->numa = (NUMA **)LEPT_CALLOC(n, sizeof(NUMA *))) == NULL) return (NUMAA *)ERROR_PTR("numa ptr array not made", procName, NULL); naa->nalloc = n; naa->n = 0; return naa; }
/*! * recogaCreate() * * Input: n (initial number of recog ptrs) * Return: recoga, or null on error */ L_RECOGA * recogaCreate(l_int32 n) { L_RECOGA *recoga; PROCNAME("recogaCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((recoga = (L_RECOGA *)LEPT_CALLOC(1, sizeof(L_RECOGA))) == NULL) return (L_RECOGA *)ERROR_PTR("recoga not made", procName, NULL); recoga->n = 0; recoga->nalloc = n; if ((recoga->recog = (L_RECOG **)LEPT_CALLOC(n, sizeof(L_RECOG *))) == NULL) return (L_RECOGA *)ERROR_PTR("recoga ptrs not made", procName, NULL); return recoga; }
/*! * ptraCreate() * * Input: size of ptr array to be alloc'd (0 for default) * Return: pa, or null on error */ L_PTRA * ptraCreate(l_int32 n) { L_PTRA *pa; PROCNAME("ptraCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((pa = (L_PTRA *)LEPT_CALLOC(1, sizeof(L_PTRA))) == NULL) return (L_PTRA *)ERROR_PTR("pa not made", procName, NULL); if ((pa->array = (void **)LEPT_CALLOC(n, sizeof(void *))) == NULL) return (L_PTRA *)ERROR_PTR("ptr array not made", procName, NULL); pa->nalloc = n; pa->imax = -1; pa->nactual = 0; return pa; }
/*! * lstackCreate() * * Input: nalloc (initial ptr array size; use 0 for default) * Return: lstack, or null on error */ L_STACK * lstackCreate(l_int32 nalloc) { L_STACK *lstack; PROCNAME("lstackCreate"); if (nalloc <= 0) nalloc = INITIAL_PTR_ARRAYSIZE; if ((lstack = (L_STACK *)LEPT_CALLOC(1, sizeof(L_STACK))) == NULL) return (L_STACK *)ERROR_PTR("lstack not made", procName, NULL); if ((lstack->array = (void **)LEPT_CALLOC(nalloc, sizeof(void *))) == NULL) return (L_STACK *)ERROR_PTR("lstack array not made", procName, NULL); lstack->nalloc = nalloc; lstack->n = 0; return lstack; }
static node *new_node(RB_TYPE key, RB_TYPE value, l_int32 node_color, node *left, node *right) { node *result = (node *)LEPT_CALLOC(1, sizeof(node)); result->key = key; result->value = value; result->color = node_color; result->left = left; result->right = right; if (left != NULL) left->parent = result; if (right != NULL) right->parent = result; result->parent = NULL; return result; }
/* ------------------------------------------------------------- * * Interface to Map * * ------------------------------------------------------------- */ L_AMAP * l_amapCreate(l_int32 keytype) { PROCNAME("l_amapCreate"); if (keytype != L_INT_TYPE && keytype != L_UINT_TYPE && keytype != L_FLOAT_TYPE) return (L_AMAP *)ERROR_PTR("invalid keytype", procName, NULL); L_AMAP *m = (L_AMAP *)LEPT_CALLOC(1, sizeof(L_AMAP)); m->keytype = keytype; return m; }
/* ------------------------------------------------------------- * * Interface to Set * * ------------------------------------------------------------- */ L_ASET * l_asetCreate(l_int32 keytype) { PROCNAME("l_asetCreate"); if (keytype != L_INT_TYPE && keytype != L_UINT_TYPE && keytype != L_FLOAT_TYPE) return (L_ASET *)ERROR_PTR("invalid keytype", procName, NULL); L_ASET *s = (L_ASET *)LEPT_CALLOC(1, sizeof(L_ASET)); s->keytype = keytype; return s; }
/*! * \brief l_dnaHashCreate() * * \param[in] nbuckets the number of buckets in the hash table, * which should be prime. * \param[in] initsize initial size of each allocated dna; 0 for default * \return ptr to new dnahash, or NULL on error * * <pre> * Notes: * (1) Actual dna are created only as required by l_dnaHashAdd() * </pre> */ L_DNAHASH * l_dnaHashCreate(l_int32 nbuckets, l_int32 initsize) { L_DNAHASH *dahash; PROCNAME("l_dnaHashCreate"); if (nbuckets <= 0) return (L_DNAHASH *)ERROR_PTR("negative hash size", procName, NULL); if ((dahash = (L_DNAHASH *)LEPT_CALLOC(1, sizeof(L_DNAHASH))) == NULL) return (L_DNAHASH *)ERROR_PTR("dahash not made", procName, NULL); if ((dahash->dna = (L_DNA **)LEPT_CALLOC(nbuckets, sizeof(L_DNA *))) == NULL) { LEPT_FREE(dahash); return (L_DNAHASH *)ERROR_PTR("dna ptr array not made", procName, NULL); } dahash->nbuckets = nbuckets; dahash->initsize = initsize; return dahash; }
/*! * \brief pushFillsegBB() * * \param[in] stack * \param[in] xleft, xright * \param[in] y * \param[in] dy * \param[in] ymax * \param[out] pminx minimum x * \param[out] pmaxx maximum x * \param[out] pminy minimum y * \param[out] pmaxy maximum y * \return void * * <pre> * Notes: * (1) This adds a line segment to the stack, and returns its size. * (2) The auxiliary stack is used as a storage area to recycle * fillsegs that are no longer in use. We only calloc new * fillsegs if the auxiliary stack is empty. * </pre> */ static void pushFillsegBB(L_STACK *stack, l_int32 xleft, l_int32 xright, l_int32 y, l_int32 dy, l_int32 ymax, l_int32 *pminx, l_int32 *pmaxx, l_int32 *pminy, l_int32 *pmaxy) { FILLSEG *fseg; L_STACK *auxstack; PROCNAME("pushFillsegBB"); if (!stack) { L_ERROR("stack not defined\n", procName); return; } *pminx = L_MIN(*pminx, xleft); *pmaxx = L_MAX(*pmaxx, xright); *pminy = L_MIN(*pminy, y); *pmaxy = L_MAX(*pmaxy, y); if (y + dy >= 0 && y + dy <= ymax) { if ((auxstack = stack->auxstack) == NULL) { L_ERROR("auxstack not defined\n", procName); return; } /* Get a fillseg to use */ if (lstackGetCount(auxstack) > 0) { fseg = (FILLSEG *)lstackRemove(auxstack); } else { if ((fseg = (FILLSEG *)LEPT_CALLOC(1, sizeof(FILLSEG))) == NULL) { L_ERROR("fillseg not made\n", procName); return; } } fseg->xleft = xleft; fseg->xright = xright; fseg->y = y; fseg->dy = dy; lstackAdd(stack, fseg); } return; }
/*! * gplotCreate() * * Input: rootname (root for all output files) * outformat (GPLOT_PNG, GPLOT_PS, GPLOT_EPS, GPLOT_X11, * GPLOT_LATEX) * title (<optional> overall title) * xlabel (<optional> x axis label) * ylabel (<optional> y axis label) * Return: gplot, or null on error * * Notes: * (1) This initializes the plot. * (2) The 'title', 'xlabel' and 'ylabel' strings can have spaces, * double quotes and backquotes, but not single quotes. */ GPLOT * gplotCreate(const char *rootname, l_int32 outformat, const char *title, const char *xlabel, const char *ylabel) { char *newroot; char buf[L_BUF_SIZE]; GPLOT *gplot; PROCNAME("gplotCreate"); if (!rootname) return (GPLOT *)ERROR_PTR("rootname not defined", procName, NULL); if (outformat != GPLOT_PNG && outformat != GPLOT_PS && outformat != GPLOT_EPS && outformat != GPLOT_X11 && outformat != GPLOT_LATEX) return (GPLOT *)ERROR_PTR("outformat invalid", procName, NULL); if ((gplot = (GPLOT *)LEPT_CALLOC(1, sizeof(GPLOT))) == NULL) return (GPLOT *)ERROR_PTR("gplot not made", procName, NULL); gplot->cmddata = sarrayCreate(0); gplot->datanames = sarrayCreate(0); gplot->plotdata = sarrayCreate(0); gplot->plottitles = sarrayCreate(0); gplot->plotstyles = numaCreate(0); /* Save title, labels, rootname, outformat, cmdname, outname */ newroot = genPathname(rootname, NULL); gplot->rootname = newroot; gplot->outformat = outformat; snprintf(buf, L_BUF_SIZE, "%s.cmd", newroot); gplot->cmdname = stringNew(buf); if (outformat == GPLOT_PNG) snprintf(buf, L_BUF_SIZE, "%s.png", newroot); else if (outformat == GPLOT_PS) snprintf(buf, L_BUF_SIZE, "%s.ps", newroot); else if (outformat == GPLOT_EPS) snprintf(buf, L_BUF_SIZE, "%s.eps", newroot); else if (outformat == GPLOT_LATEX) snprintf(buf, L_BUF_SIZE, "%s.tex", newroot); else /* outformat == GPLOT_X11 */ buf[0] = '\0'; gplot->outname = stringNew(buf); if (title) gplot->title = stringNew(title); if (xlabel) gplot->xlabel = stringNew(xlabel); if (ylabel) gplot->ylabel = stringNew(ylabel); return gplot; }
/* * l_rbtreeCreate() * * Input: keytype (defined by an enum for an RB_TYPE union) * Return: rbtree (container with empty ptr to the root) */ L_RBTREE * l_rbtreeCreate(l_int32 keytype) { PROCNAME("l_rbtreeCreate"); if (keytype != L_INT_TYPE && keytype != L_UINT_TYPE && keytype != L_FLOAT_TYPE && keytype) return (L_RBTREE *)ERROR_PTR("invalid keytype", procName, NULL); L_RBTREE *t = (L_RBTREE *)LEPT_CALLOC(1, sizeof(L_RBTREE)); t->keytype = keytype; verify_properties(t); return t; }
/*! * numaCreate() * * Input: size of number array to be alloc'd (0 for default) * Return: na, or null on error */ NUMA * numaCreate(l_int32 n) { NUMA *na; PROCNAME("numaCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((na = (NUMA *)LEPT_CALLOC(1, sizeof(NUMA))) == NULL) return (NUMA *)ERROR_PTR("na not made", procName, NULL); if ((na->array = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32))) == NULL) return (NUMA *)ERROR_PTR("number array not made", procName, NULL); na->nalloc = n; na->n = 0; na->refcount = 1; na->startx = 0.0; na->delx = 1.0; return na; }
/*! * \brief pixTilingCreate() * * \param[in] pixs pix to be tiled; any depth; colormap OK * \param[in] nx number of tiles across image * \param[in] ny number of tiles down image * \param[in] w desired width of each tile * \param[in] h desired height of each tile * \param[in] xoverlap overlap into neighboring tiles on each side * \param[in] yoverlap overlap into neighboring tiles above and below * \return pixtiling, or NULL on error * * <pre> * Notes: * (1) We put a clone of pixs in the PixTiling. * (2) The input to pixTilingCreate() for horizontal tiling can be * either the number of tiles across the image or the approximate * width of the tiles. If the latter, the actual width will be * determined by making all tiles but the last of equal width, and * making the last as close to the others as possible. The same * consideration is applied independently to the vertical tiling. * To specify tile width, set nx = 0; to specify the number of * tiles horizontally across the image, set w = 0. * (3) If pixs is to be tiled in one-dimensional strips, use ny = 1 for * vertical strips and nx = 1 for horizontal strips. * (4) The overlap must not be larger than the width or height of * the leftmost or topmost tile(s). * </pre> */ PIXTILING * pixTilingCreate(PIX *pixs, l_int32 nx, l_int32 ny, l_int32 w, l_int32 h, l_int32 xoverlap, l_int32 yoverlap) { l_int32 width, height; PIXTILING *pt; PROCNAME("pixTilingCreate"); if (!pixs) return (PIXTILING *)ERROR_PTR("pixs not defined", procName, NULL); if (nx < 1 && w < 1) return (PIXTILING *)ERROR_PTR("invalid width spec", procName, NULL); if (ny < 1 && h < 1) return (PIXTILING *)ERROR_PTR("invalid height spec", procName, NULL); /* Find the tile width and number of tiles. All tiles except the * rightmost ones have the same width. The width of the * rightmost ones are at least the width of the others and * less than twice that width. Ditto for tile height. */ pixGetDimensions(pixs, &width, &height, NULL); if (nx == 0) nx = L_MAX(1, width / w); w = width / nx; /* possibly reset */ if (ny == 0) ny = L_MAX(1, height / h); h = height / ny; /* possibly reset */ if (xoverlap > w || yoverlap > h) { L_INFO("tile width = %d, tile height = %d\n", procName, w, h); return (PIXTILING *)ERROR_PTR("overlap too large", procName, NULL); } if ((pt = (PIXTILING *)LEPT_CALLOC(1, sizeof(PIXTILING))) == NULL) return (PIXTILING *)ERROR_PTR("pt not made", procName, NULL); pt->pix = pixClone(pixs); pt->xoverlap = xoverlap; pt->yoverlap = yoverlap; pt->nx = nx; pt->ny = ny; pt->w = w; pt->h = h; pt->strip = TRUE; return pt; }
/*! * \brief createMatrix2dScale() * * \param[in] scalex horizontal scale factor * \param[in] scaley vertical scale factor * \return 3x3 transform matrix, or NULL on error * * <pre> * Notes: * (1) The scaling is equivalent to: * v' = Av * where v and v' are 1x3 column vectors in the form * v = [x, y, 1]^ ^ denotes transpose * and the affine scaling matrix is * A = [ sx 0 0 * 0 sy 0 * 0 0 1 ] * * (2) We consider scaling as with respect to a fixed origin. * In other words, the origin is the only point that doesn't * move in the scaling transform. * </pre> */ l_float32 * createMatrix2dScale(l_float32 scalex, l_float32 scaley) { l_float32 *mat; PROCNAME("createMatrix2dScale"); if ((mat = (l_float32 *)LEPT_CALLOC(9, sizeof(l_float32))) == NULL) return (l_float32 *)ERROR_PTR("mat not made", procName, NULL); mat[0] = scalex; mat[4] = scaley; mat[8] = 1; return mat; }
/*! * \brief createMatrix2dTranslate() * * \param[in] transx x component of translation wrt. the origin * \param[in] transy y component of translation wrt. the origin * \return 3x3 transform matrix, or NULL on error * * <pre> * Notes: * (1) The translation is equivalent to: * v' = Av * where v and v' are 1x3 column vectors in the form * v = [x, y, 1]^ ^ denotes transpose * and the affine translation matrix is * A = [ 1 0 tx * 0 1 ty * 0 0 1 ] * * (2) We consider translation as with respect to a fixed origin. * In a clipping operation, the origin moves and the points * are fixed, and you use (-tx, -ty) where (tx, ty) is the * translation vector of the origin. * </pre> */ l_float32 * createMatrix2dTranslate(l_float32 transx, l_float32 transy) { l_float32 *mat; PROCNAME("createMatrix2dTranslate"); if ((mat = (l_float32 *)LEPT_CALLOC(9, sizeof(l_float32))) == NULL) return (l_float32 *)ERROR_PTR("mat not made", procName, NULL); mat[0] = mat[4] = mat[8] = 1; mat[2] = transx; mat[5] = transy; return mat; }