/*!
 *  sarraySelectBySubstring()
 *
 *      Input:  sain (input sarray)
 *              substr (<optional> substring for matching; can be NULL)
 *      Return: saout (output sarray, filtered with substring) or null on error
 *
 *  Notes:
 *      (1) This selects all strings in sain that have substr as a substring.
 *          Note that we can't use strncmp() because we're looking for
 *          a match to the substring anywhere within each filename.
 *      (2) If substr == NULL, returns a copy of the sarray.
 */
SARRAY *
sarraySelectBySubstring(SARRAY      *sain,
                        const char  *substr)
{
char    *str;
l_int32  n, i, offset, found;
SARRAY  *saout;

    PROCNAME("sarraySelectBySubstring");

    if (!sain)
        return (SARRAY *)ERROR_PTR("sain not defined", procName, NULL);

    n = sarrayGetCount(sain);
    if (!substr || n == 0)
        return sarrayCopy(sain);

    saout = sarrayCreate(n);
    for (i = 0; i < n; i++) {
        str = sarrayGetString(sain, i, L_NOCOPY);
        arrayFindSequence((l_uint8 *)str, strlen(str), (l_uint8 *)substr,
                          strlen(substr), &offset, &found);
        if (found)
            sarrayAddString(saout, str, L_COPY);
    }

    return saout;
}
Esempio n. 2
0
/*
 *  fgetJp2kResolution()
 *
 *      Input:  stream (opened for read)
 *              &xres, &yres (<return> resolution in ppi)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) If the capture resolution field is not set, this is not an error;
 *          the returned resolution values are 0 (designating 'unknown').
 *      (2) Side-effect: this rewinds the stream.
 *      (3) The capture resolution box is optional in the jp2 spec, and
 *          it is usually not written.
 *      (4) The big-endian data fields that follow the 4 bytes of 'resc' are:
 *             ynum:    2 bytes
 *             ydenom:  2 bytes
 *             xnum:    2 bytes
 *             xdenom:  2 bytes
 *             yexp:    1 byte
 *             xexp:    1 byte
 */
l_int32
fgetJp2kResolution(FILE     *fp,
                   l_int32  *pxres,
                   l_int32  *pyres)
{
l_uint8    xexp, yexp;
l_uint8   *data;
l_uint16   xnum, ynum, xdenom, ydenom;  /* these jp2k fields are 2-byte */
l_int32    loc, found;
l_uint8    resc[4] = {0x72, 0x65, 0x73, 0x63};  /* 'resc' */
size_t     nbytes;
l_float64  xres, yres;

    PROCNAME("fgetJp2kResolution");

    if (pxres) *pxres = 0;
    if (pyres) *pyres = 0;
    if (!pxres || !pyres)
        return ERROR_INT("&xres and &yres not both defined", procName, 1);
    if (!fp)
        return ERROR_INT("stream not opened", procName, 1);

    rewind(fp);
    data = l_binaryReadStream(fp, &nbytes);
    rewind(fp);

        /* Search for the start of the first capture resolution box: 'resc' */
    arrayFindSequence(data, nbytes, resc, 4, &loc, &found);
    if (!found) {
        L_WARNING("image resolution not found\n", procName);
        FREE(data);
        return 0;
    }

        /* Extract the fields and calculate the resolution in pixels/meter.
         * See section 1.5.3.7.1 of JPEG 2000 ISO/IEC 15444-1 spec.  */
    ynum = data[loc + 5] << 8 | data[loc + 4];
    ynum = convertOnLittleEnd16(ynum);
    ydenom = data[loc + 7] << 8 | data[loc + 6];
    ydenom = convertOnLittleEnd16(ydenom);
    xnum = data[loc + 9] << 8 | data[loc + 8];
    xnum = convertOnLittleEnd16(xnum);
    xdenom = data[loc + 11] << 8 | data[loc + 10];
    xdenom = convertOnLittleEnd16(xdenom);
    yexp = data[loc + 12];
    xexp = data[loc + 13];
    yres = ((l_float64)ynum / (l_float64)ydenom) * pow(10.0, (l_float64)yexp);
    xres = ((l_float64)xnum / (l_float64)xdenom) * pow(10.0, (l_float64)xexp);

        /* Convert from pixels/meter to ppi */
    yres *= (300.0 / 11811.0);
    xres *= (300.0 / 11811.0);
    *pyres = (l_int32)(yres + 0.5);
    *pxres = (l_int32)(xres + 0.5);

    FREE(data);
    return 0;
}
Esempio n. 3
0
/*!
 *  readHeaderMemJp2k()
 *
 *      Input:  data
 *              size (at least 80)
 *              &w (<optional return>)
 *              &h (<optional return>)
 *              &bps (<optional return>, bits/sample)
 *              &spp (<optional return>, samples/pixel)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The ISO/IEC reference for jpeg2000 is
 *               http://www.jpeg.org/public/15444-1annexi.pdf
 *          and the file format syntax begins at page 127.
 *      (2) The Image Header Box begins with 'ihdr' = 0x69686472 in
 *          big-endian order.  This typically, but not always, starts
 *          byte 44, with the big-endian data fields beginning at byte 48:
 *               h:    4 bytes
 *               w:    4 bytes
 *               spp:  2 bytes
 *               bps:  1 byte   (contains bps - 1)
 */
l_int32
readHeaderMemJp2k(const l_uint8  *data,
                  size_t          size,
                  l_int32        *pw,
                  l_int32        *ph,
                  l_int32        *pbps,
                  l_int32        *pspp)
{
l_int32  format, val, w, h, bps, spp, loc, found, windex;
l_uint8  ihdr[4] = {0x69, 0x68, 0x64, 0x72};  /* 'ihdr' */

    PROCNAME("readHeaderMemJp2k");

    if (pw) *pw = 0;
    if (ph) *ph = 0;
    if (pbps) *pbps = 0;
    if (pspp) *pspp = 0;
    if (!data)
        return ERROR_INT("data not defined", procName, 1);
    if (size < 80)
        return ERROR_INT("size < 80", procName, 1);
    findFileFormatBuffer(data, &format);
    if (format != IFF_JP2)
        return ERROR_INT("not jp2 file", procName, 1);

        /* Search for beginning of the Image Header Box: 'ihdr' */
    arrayFindSequence(data, size, ihdr, 4, &loc, &found);
    if (!found)
        return ERROR_INT("image parameters not found", procName, 1);
    if (loc != 44)
        L_INFO("Beginning of ihdr is at byte %d\n", procName, loc);

    windex = loc / 4 + 1;
    val = *((l_uint32 *)data + windex);
    h = convertOnLittleEnd32(val);
    val = *((l_uint32 *)data + windex + 1);
    w = convertOnLittleEnd32(val);
    val = *((l_uint16 *)data + 2 * (windex + 2));
    spp = convertOnLittleEnd16(val);
    bps = *(data + 4 * (windex + 2) + 2) + 1;
    if (w > MAX_JP2K_WIDTH || h > MAX_JP2K_HEIGHT)
        return ERROR_INT("unrealistically large sizes", procName, 1);
    if (pw) *pw = w;
    if (ph) *ph = h;
    if (pbps) *pbps = bps;
    if (pspp) *pspp = spp;
    return 0;
}
/*!
 *  sarrayParseRange()
 *
 *      Input:  sa (input sarray)
 *              start (index to start range search)
 *             &actualstart (<return> index of actual start; may be > 'start')
 *             &end (<return> index of end)
 *             &newstart (<return> index of start of next range)
 *              substr (substring for matching at beginning of string)
 *              loc (byte offset within the string for the pattern; use
 *                   -1 if the location does not matter);
 *      Return: 0 if valid range found; 1 otherwise
 *
 *  Notes:
 *      (1) This finds the range of the next set of strings in SA,
 *          beginning the search at 'start', that does NOT have
 *          the substring 'substr' either at the indicated location
 *          in the string or anywhere in the string.  The input
 *          variable 'loc' is the specified offset within the string;
 *          use -1 to indicate 'anywhere in the string'.
 *      (2) Always check the return value to verify that a valid range
 *          was found.
 *      (3) If a valid range is not found, the values of actstart,
 *          end and newstart are all set to the size of sa.
 *      (4) If this is the last valid range, newstart returns the value n.
 *          In use, this should be tested before calling the function.
 *      (5) Usage example.  To find all the valid ranges in a file
 *          where the invalid lines begin with two dashes, copy each
 *          line in the file to a string in an sarray, and do:
 *             start = 0;
 *             while (!sarrayParseRange(sa, start, &actstart, &end, &start,
 *                    "--", 0))
 *                 fprintf(stderr, "start = %d, end = %d\n", actstart, end);
 */
l_int32
sarrayParseRange(SARRAY      *sa,
                 l_int32      start,
                 l_int32     *pactualstart,
                 l_int32     *pend,
                 l_int32     *pnewstart,
                 const char  *substr,
		 l_int32      loc)
{
char    *str;
l_int32  n, i, offset, found;

    PROCNAME("sarrayParseRange");

    if (!sa)
        return ERROR_INT("sa not defined", procName, 1);
    if (!pactualstart || !pend || !pnewstart)
        return ERROR_INT("not all range addresses defined", procName, 1);
    n = sarrayGetCount(sa);
    *pactualstart = *pend = *pnewstart = n;
    if (!substr)
        return ERROR_INT("substr not defined", procName, 1);

        /* Look for the first string without the marker */
    if (start < 0 || start >= n)
        return 1;
    for (i = start; i < n; i++) {
        str = sarrayGetString(sa, i, L_NOCOPY);
        arrayFindSequence((l_uint8 *)str, strlen(str), (l_uint8 *)substr,
                          strlen(substr), &offset, &found);
	if (loc < 0) {
            if (!found) break;
	} else {
            if (!found || offset != loc) break;
	}
    }
    start = i;
    if (i == n)  /* couldn't get started */
        return 1;

        /* Look for the last string without the marker */
    *pactualstart = start;
    for (i = start + 1; i < n; i++) {
        str = sarrayGetString(sa, i, L_NOCOPY);
        arrayFindSequence((l_uint8 *)str, strlen(str), (l_uint8 *)substr,
                          strlen(substr), &offset, &found);
	if (loc < 0) {
            if (found) break;
	} else {
            if (found && offset == loc) break;
	}
    }
    *pend = i - 1;
    start = i;
    if (i == n)  /* no further range */
        return 0;

        /* Look for the first string after *pend without the marker.
         * This will start the next run of strings, if it exists. */
    for (i = start; i < n; i++) {
        str = sarrayGetString(sa, i, L_NOCOPY);
        arrayFindSequence((l_uint8 *)str, strlen(str), (l_uint8 *)substr,
                          strlen(substr), &offset, &found);
	if (loc < 0) {
            if (!found) break;
	} else {
            if (!found || offset != loc) break;
	}
    }
    if (i < n)
        *pnewstart = i;

    return 0;
}