Esempio n. 1
0
J2KAPI(j2k_Container*) j2k_Container_construct(nrt_Uint32 gridWidth,
        nrt_Uint32 gridHeight,
        nrt_Uint32 numComponents,
        j2k_Component** components,
        nrt_Uint32 tileWidth,
        nrt_Uint32 tileHeight,
        int imageType,
        nrt_Error *error)
{
    j2k_Container *container = NULL;
    ContainerImpl *impl = NULL;

    container = (j2k_Container*) J2K_MALLOC(sizeof(j2k_Container));
    if (!container)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(container, 0, sizeof(j2k_Container));

    /* create the Container interface */
    impl = (ContainerImpl *) J2K_MALLOC(sizeof(ContainerImpl));
    if (!impl)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(impl, 0, sizeof(ContainerImpl));
    container->data = impl;
    container->iface = &ContainerInterface;

    impl->gridWidth = gridWidth;
    impl->gridHeight = gridHeight;
    impl->nComponents = numComponents;
    impl->components = components;
    impl->tileWidth = tileWidth;
    impl->tileHeight = tileHeight;
    impl->xTiles = gridWidth / tileWidth + (gridWidth % tileWidth == 0 ? 0 : 1);
    impl->yTiles = gridHeight / tileHeight + (gridHeight % tileHeight == 0 ? 0 : 1);
    impl->imageType = imageType;

    return container;

CATCH_ERROR:
    {
        if (container)
        {
            j2k_Container_destruct(&container);
        }
        return NULL;
    }
}
Esempio n. 2
0
J2KAPI(j2k_Component*) j2k_Component_construct(nrt_Uint32 width,
                                               nrt_Uint32 height,
                                               nrt_Uint32 precision,
                                               NRT_BOOL isSigned,
                                               nrt_Uint32 offsetX,
                                               nrt_Uint32 offsetY,
                                               nrt_Uint32 separationX,
                                               nrt_Uint32 separationY,
                                               nrt_Error *error)
{
    j2k_Component *component = NULL;
    ComponentImpl *impl = NULL;

    component = (j2k_Component*) J2K_MALLOC(sizeof(j2k_Component));
    if (!component)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(component, 0, sizeof(j2k_Component));

    /* create the Component interface */
    impl = (ComponentImpl *) J2K_MALLOC(sizeof(ComponentImpl));
    if (!impl)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(impl, 0, sizeof(ComponentImpl));
    component->data = impl;
    component->iface = &ComponentInterface;

    impl->width = width;
    impl->height = height;
    impl->precision = precision;
    impl->isSigned = isSigned;
    impl->x0 = offsetX;
    impl->y0 = offsetY;
    impl->xSeparation = separationX;
    impl->ySeparation = separationY;

    return component;

    CATCH_ERROR:
    {
        if (component)
        {
            j2k_Component_destruct(&component);
        }
        return NULL;
    }
}
Esempio n. 3
0
J2KAPI(j2k_Reader*) j2k_Reader_openIO(nrt_IOInterface *io, nrt_Error *error)
{
    OpenJPEGReaderImpl *impl = NULL;
    j2k_Reader *reader = NULL;

    /* create the Reader interface */
    impl = (OpenJPEGReaderImpl *) J2K_MALLOC(sizeof(OpenJPEGReaderImpl));
    if (!impl)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(impl, 0, sizeof(OpenJPEGReaderImpl));

    reader = (j2k_Reader *) J2K_MALLOC(sizeof(j2k_Reader));
    if (!reader)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(reader, 0, sizeof(j2k_Reader));
    reader->data = impl;
    reader->iface = &ReaderInterface;

    /* initialize the interfaces */
    impl->io = io;
    impl->ioOffset = nrt_IOInterface_tell(io, error);

    if (!OpenJPEG_readHeader(impl, error))
    {
        goto CATCH_ERROR;
    }

    return reader;

    CATCH_ERROR:
    {
        if (reader)
        {
            j2k_Reader_destruct(&reader);
        }
        else if (impl)
        {
            OpenJPEGReader_destruct((J2K_USER_DATA*) impl);
        }
        return NULL;
    }
}
Esempio n. 4
0
NRTAPI(nrt_IOHandle) nrt_IOHandle_create(const char *fname,
                                         nrt_AccessFlags access,
                                         nrt_CreationFlags creation,
                                         nrt_Error * error)
{
    HANDLE handle;

    if (access & NRT_ACCESS_WRITEONLY)
    {
        WIN32_FIND_DATA findData;
        handle = FindFirstFile(fname, &findData);
        if (handle != INVALID_HANDLE_VALUE)
        {
            creation |= TRUNCATE_EXISTING;
            FindClose(handle);
        }
    }

    handle =
        CreateFile(fname, access, FILE_SHARE_READ, NULL, creation,
                   FILE_ATTRIBUTE_NORMAL, NULL);

    if (handle == INVALID_HANDLE_VALUE)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_OPENING_FILE);
    }
    return handle;
}
Esempio n. 5
0
NRTAPI(nrt_ListNode *) nrt_ListNode_construct(nrt_ListNode * prev,
                                              nrt_ListNode * next,
                                              NRT_DATA * data,
                                              nrt_Error * error)
{
    nrt_ListNode *node = (nrt_ListNode *) NRT_MALLOC(sizeof(nrt_ListNode));
    if (node == NULL)
    {
        /* Init the error with the string value of errno */
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        /* Return if we have a problem */
        return NULL;
    }

    /* Attention!! Achtung!! This is a data pointer copy, */
    /* not copying an object.  That means that YOU the user */
    /* of this API MUST allocate it yourself */
    /* And, of course, YOU must delete it as well!! */
    node->data = data;

    /* Attach up our nodes */
    node->next = next;
    node->prev = prev;

    /* Return the new node */
    return node;
}
Esempio n. 6
0
J2KAPI(j2k_Writer*) j2k_Writer_construct(j2k_Container *container,
                                         j2k_WriterOptions *writerOps,
                                         nrt_Error *error)
{
    j2k_Writer *writer = NULL;
    OpenJPEGWriterImpl *impl = NULL;

    writer = (j2k_Writer*) J2K_MALLOC(sizeof(j2k_Container));
    if (!writer)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(writer, 0, sizeof(j2k_Writer));

    /* create the Writer interface */
    impl = (OpenJPEGWriterImpl *) J2K_MALLOC(sizeof(OpenJPEGWriterImpl));
    if (!impl)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(impl, 0, sizeof(OpenJPEGWriterImpl));
    impl->container = container;

    if (!(OpenJPEG_initImage(impl, writerOps, error)))
    {
        goto CATCH_ERROR;
    }

    writer->data = impl;
    writer->iface = &WriterInterface;

    return writer;

    CATCH_ERROR:
    {
        if (writer)
        {
            j2k_Writer_destruct(&writer);
        }
        return NULL;
    }
}
Esempio n. 7
0
NRTAPI(nrt_DLL *) nrt_DLL_construct(nrt_Error * error)
{
    nrt_DLL *dll = (nrt_DLL *) NRT_MALLOC(sizeof(nrt_DLL));
    if (!dll)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);

    }
    dll->libname = NULL;
    dll->lib = NULL;
    return dll;
}
Esempio n. 8
0
NRTPROT(nrt_IntStack *) nrt_IntStack_construct(nrt_Error * error)
{
    nrt_IntStack *stk = (nrt_IntStack *) NRT_MALLOC(sizeof(nrt_IntStack));
    if (!stk)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        return NULL;
    }

    stk->sp = -1;
    return stk;
}
Esempio n. 9
0
NRTAPI(nrt_DateTime *) nrt_DateTime_fromString(const char *string,
                                               const char *format,
                                               nrt_Error * error)
{
    struct tm t;
    nrt_DateTime *dateTime = NULL;
    double millis = 0.0;

    /* NOTE: _NRT_strptime() does not use the tm_isdst flag at all. */
    t.tm_isdst = -1;

    if (!_NRT_strptime(string, format, &t, &millis))
    {
        nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                        "Unknown error caused by the call to strptime with string [%s] and format string [%s]",
                        string, format);
        return NULL;
    }

    /* Create a DateTime object */
    dateTime = (nrt_DateTime *) NRT_MALLOC(sizeof(nrt_DateTime));
    if (!dateTime)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        return NULL;
    }

    /* Initialize it from the tm struct
     * TODO: Update _NRT_strptime() to just use a DateTime directly */
    dateTime->year = t.tm_year + 1900;

    /* 0-based so add 1 */
    dateTime->month = t.tm_mon + 1;
    dateTime->dayOfMonth = t.tm_mday;
    dateTime->dayOfWeek = t.tm_wday + 1;
    dateTime->dayOfYear = t.tm_yday + 1;
    dateTime->hour = t.tm_hour;
    dateTime->minute = t.tm_min;
    dateTime->second = t.tm_sec + millis / 1000.0;

    /* Compute the # of milliseconds */
    if (!nrt_DateTime_updateMillis(dateTime, error))
    {
        NRT_FREE(dateTime);
        return NULL;
    }

    return dateTime;
}
Esempio n. 10
0
NRTAPI(nrt_List *) nrt_List_construct(nrt_Error * error)
{
    /* New allocate a list */
    nrt_List *l;
    l = (nrt_List *) NRT_MALLOC(sizeof(nrt_List));
    if (!l)
    {
        /* Initialize the error and return NULL */
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        return NULL;
    }
    /* Null-initialize the link pointers */
    l->first = l->last = NULL;
    return l;
}
Esempio n. 11
0
NRTAPI(nrt_DateTime *) nrt_DateTime_fromMillis(double millis, nrt_Error * error)
{
    nrt_DateTime *dt = NULL;

    dt = (nrt_DateTime *) NRT_MALLOC(sizeof(nrt_DateTime));
    if (!dt)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        return NULL;
    }

    nrt_DateTime_setTimeInMillis(dt, millis, error);

    return dt;
}
Esempio n. 12
0
NRTAPI(NRT_BOOL) nrt_IOHandle_read(nrt_IOHandle handle, char *buf, size_t size,
                                   nrt_Error * error)
{
    static const DWORD MAX_READ_SIZE = (DWORD)-1;
    size_t bytesRead = 0;
    size_t bytesRemaining = size;

    while (bytesRead < size)
    {
        /* Determine how many bytes to read */
        const DWORD bytesToRead = (bytesRemaining > MAX_READ_SIZE) ?
            MAX_READ_SIZE : (DWORD)bytesRemaining;

        /* Read from file */
        DWORD bytesThisRead = 0;
        if (!ReadFile(handle,
                      buf + bytesRead,
                      bytesToRead,
                      &bytesThisRead,
                      NULL))
        {
            nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                           NRT_ERR_READING_FROM_FILE);
            return NRT_FAILURE;
        }
        else if (bytesThisRead == 0)
        {
            // ReadFile does not fail when finding the EOF --
            // instead it reports 0 bytes read, so this stops an infinite loop
            // from Unexpected EOF
            nrt_Error_init(error, "Unexpected end of file", NRT_CTXT,
                           NRT_ERR_READING_FROM_FILE);
            return NRT_FAILURE;
        }

        bytesRead += bytesThisRead;
        bytesRemaining -= bytesThisRead;
    }

    return NRT_SUCCESS;
}
Esempio n. 13
0
NRTAPI(NRT_BOOL) nrt_DLL_load(nrt_DLL * dll, const char *libname,
                              nrt_Error * error)
{
    dll->libname = (char *) NRT_MALLOC(strlen(libname) + 1);
    if (!dll->libname)
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        return NRT_FAILURE;
    }
    strcpy(dll->libname, libname);
    dll->lib = dlopen(libname, RTLD_LAZY);
    if (!dll->lib)
    {
        nrt_Error_init(error, dlerror(), NRT_CTXT, NRT_ERR_LOADING_DLL);
        NRT_FREE(dll->libname);
        dll->libname = NULL;
        return NRT_FAILURE;
    }

    return NRT_SUCCESS;
}
Esempio n. 14
0
J2K_BOOL readFile(const char* filename, char **buf, nrt_Uint64 *bufSize,
                  nrt_Error *error)
{
    J2K_BOOL rc = J2K_TRUE;
    nrt_IOInterface *io = NULL;

    if (!(io = nrt_IOHandleAdapter_open(filename, NRT_ACCESS_READONLY,
                                        NRT_OPEN_EXISTING, error)))
        goto CATCH_ERROR;

    *bufSize = nrt_IOInterface_getSize(io, error);
    if (!(*buf = (char*)J2K_MALLOC(*bufSize)))
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }

    if (!nrt_IOInterface_read(io, *buf, *bufSize, error))
    {
        goto CATCH_ERROR;
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        rc = J2K_FALSE;
        if (*buf)
            J2K_FREE(*buf);
        *buf = NULL;
    }
    CLEANUP:
    {
        if (io)
            nrt_IOInterface_destruct(&io);
    }
    return rc;
}
Esempio n. 15
0
NRTAPI(NRT_BOOL) nrt_IOHandle_write(nrt_IOHandle handle, const char *buf,
                                    size_t size, nrt_Error * error)
{
    static const DWORD MAX_WRITE_SIZE = (DWORD)-1;
    size_t bytesRemaining = size;
    size_t bytesWritten = 0;

    while (bytesWritten < size)
    {
        /* Determine how many bytes to write */
        const DWORD bytesToWrite = (bytesRemaining > MAX_WRITE_SIZE) ?
            MAX_WRITE_SIZE : (DWORD)bytesRemaining;

        /* Write the data */
        DWORD bytesThisWrite = 0;

        if (!WriteFile(handle,
                       buf + bytesWritten,
                       bytesToWrite,
                       &bytesThisWrite,
                       NULL))
        {
            /* If the function failed, we want to get the last error */
            nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                           NRT_ERR_WRITING_TO_FILE);
            /* And fail */
            return NRT_FAILURE;
        }

        /* Otherwise, we want to accumulate this write until we are done */
        bytesRemaining -= bytesThisWrite;
        bytesWritten += bytesThisWrite;
    }

    return NRT_SUCCESS;
}
Esempio n. 16
0
NRTAPI(nrt_List *) nrt_Utils_splitString(char *str, unsigned int max,
        nrt_Error * error)
{
    unsigned int count = 0;
    nrt_List *parts;
    char *op, *cur, *end;
    size_t strLen;

    parts = nrt_List_construct(error);
    if (!parts)
        return NULL;

    strLen = strlen(str);
    end = str + strLen;

    op = str;

    if (max == 1)
    {
        char *val = NRT_MALLOC(strLen + 1);
        if (!val)
        {
            nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                           NRT_ERR_MEMORY);
            return NULL;
        }
        memset(val, 0, strLen + 1);
        memcpy(val, str, strLen);
        nrt_List_pushBack(parts, val, error);
    }
    else
    {
        /* strtok is not thread safe */
        while (op < end)
        {
            char *val = NULL;
            int sz;
            /* skip past white space */
            while (isspace(*op) && op < end)
                ++op;
            cur = op;

            while (!isspace(*op) && op < end)
                ++op;

            if (cur == op)
                break;

            sz = op - cur;
            val = NRT_MALLOC(sz + 1);
            if (!val)
            {
                nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                               NRT_ERR_MEMORY);
                return NULL;
            }
            memset(val, 0, sz + 1);
            memcpy(val, cur, sz);
            nrt_List_pushBack(parts, val, error);
            count++;

            /* check the count limit */
            if (max != 0 && count == (max - 1) && op < end)
            {
                /* push on the rest of the string - skip spaces first */
                while (isspace(*op) && op < end)
                    ++op;

                if (op < end)
                {
                    sz = end - op;
                    val = NRT_MALLOC(sz + 1);
                    if (!val)
                    {
                        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                                       NRT_ERR_MEMORY);
                        return NULL;
                    }
                    memset(val, 0, sz + 1);
                    memcpy(val, op, sz);
                    nrt_List_pushBack(parts, val, error);
                }
                break;
            }
        }
    }

    return parts;
}
Esempio n. 17
0
NRTAPI(NRT_BOOL) nrt_DateTime_formatMillis(double millis, const char *format,
                                           char *outBuf, size_t maxSize,
                                           nrt_Error * error)
{
    time_t timeInSeconds;
    double fractSeconds;
    struct tm t;
    char *newFmtString = NULL;
    const char *endString = NULL;
    size_t begStringLen = 0;
    size_t formatLength;
    size_t startIndex = 0;
    size_t i, j;
    NRT_BOOL found = 0;

    timeInSeconds = (time_t) (millis / 1000);
    t = *gmtime(&timeInSeconds);
    fractSeconds = (millis / 1000.0) - timeInSeconds;

    /* Search for "%...S" string */
    formatLength = strlen(format);
    for (i = 0; i < formatLength && !found; ++i)
    {
        if (format[i] == '%')
        {
            startIndex = i;
            for (j = startIndex + 1; j < formatLength; ++j)
            {
                if (format[j] == '%')
                {
                    break;
                }

                if (format[j] == 'S')
                {
                    found = 1;
                    formatLength = j - startIndex + 1;
                    begStringLen = startIndex;
                    endString = format + j + 1;
                }
            }
        }
    }

    /* If we found a "%...S" string, parse it */
    /* to find out how many decimal places to use */
    if (found)
    {
        int decimalPlaces = 0;

        /* Figure out how many decimal places we need... */
        for (i = startIndex + 1; i < startIndex + (formatLength - 1); ++i)
        {
            if (format[i] == '.')
            {
                /* The digits that follow should be */
                /* the number of decimal places */
                sscanf(format + i + 1, "%d", &decimalPlaces);
            }
        }

        if (decimalPlaces > 0)
        {
            char buf[256];
            size_t newFmtLen = 0;
            size_t bufIdx = 0;
            size_t endStringLen = endString ? strlen(endString) : 0;

            newFmtLen = begStringLen + 1;
            newFmtString = (char *) NRT_MALLOC(newFmtLen);
            if (!newFmtString)
            {
                nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                               NRT_ERR_MEMORY);
                goto CATCH_ERROR;
            }
            memset(newFmtString, 0, newFmtLen);

            if (begStringLen > 0)
            {
                /* do the first part of the format */
                strncpy(newFmtString, format, begStringLen);

                if (strftime(outBuf, maxSize, newFmtString, &t) == 0)
                {
                    nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                    "Unknown error caused by the call to strftime with format string: [%s]",
                                    format);
                    goto CATCH_ERROR;
                }
                bufIdx = strlen(outBuf);
            }

            /* do the seconds - separately */
            memset(buf, 0, 256);
            if (strftime(buf, 256, "%S", &t) == 0)
            {
                nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                "Unknown error caused by the call to strftime with format string: [%s]",
                                format);
                goto CATCH_ERROR;
            }

            if (strlen(buf) + bufIdx + 1 > maxSize)
            {
                nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                "Format string will cause buffer to overflow: [%s]",
                                format);
                goto CATCH_ERROR;
            }

            /* tack it on the end */
            strcpy(outBuf + bufIdx, buf);
            bufIdx = strlen(outBuf);

            memset(buf, 0, 256);
            NRT_SNPRINTF(buf, 256, "%.*f", decimalPlaces, fractSeconds);

            if (strlen(buf) + bufIdx + 1 > maxSize)
            {
                nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                "Format string will cause buffer to overflow: [%s]",
                                format);
                goto CATCH_ERROR;
            }

            /* tack on the fractional seconds - spare the leading 0 */
            strcpy(outBuf + bufIdx, buf + 1);
            bufIdx = strlen(outBuf);

            if (endStringLen > 0)
            {
                /* tack on the end part */
                memset(buf, 0, 256);
                if (strftime(buf, 256, endString, &t) == 0)
                {
                    nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                    "Unknown error caused by the call to strftime with format string: [%s]",
                                    format);
                    goto CATCH_ERROR;
                }

                if (strlen(buf) + bufIdx + 1 > maxSize)
                {
                    nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                                    "Format string will cause buffer to overflow: [%s]",
                                    format);
                    goto CATCH_ERROR;
                }
                strcpy(outBuf + bufIdx, buf);
            }
        }
    }

    if (newFmtString == NULL)
    {
        if (strftime
            (outBuf, maxSize, newFmtString != NULL ? newFmtString : format,
             &t) == 0)
        {
            nrt_Error_initf(error, NRT_CTXT, NRT_ERR_INVALID_OBJECT,
                            "Unknown error caused by the call to strftime with format string: [%s]",
                            newFmtString != NULL ? newFmtString : format);
            goto CATCH_ERROR;
        }
    }
    else
        NRT_FREE(newFmtString);

    return NRT_SUCCESS;

    CATCH_ERROR:
    if (newFmtString)
        NRT_FREE(newFmtString);

    return NRT_FAILURE;
}
Esempio n. 18
0
OpenJPEG_readHeader(OpenJPEGReaderImpl *impl, nrt_Error *error)
{
    opj_stream_t *stream = NULL;
    opj_image_t *image = NULL;
    opj_codec_t *codec = NULL;
    opj_codestream_info_v2_t* codeStreamInfo = NULL;
    NRT_BOOL rc = NRT_SUCCESS;
    OPJ_UINT32 tileWidth, tileHeight;
    OPJ_UINT32 imageWidth, imageHeight;

    if (!OpenJPEG_setup(impl, &stream, &codec, error))
    {
        goto CATCH_ERROR;
    }

    if (!opj_read_header(stream, codec, &image))
    {
        /*nrt_Error_init(error, "Error reading header", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }

    codeStreamInfo = opj_get_cstr_info(codec);
    if (!codeStreamInfo)
    {
        /*nrt_Error_init(error, "Error reading code stream", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }
    tileWidth = codeStreamInfo->tdx;
    tileHeight = codeStreamInfo->tdy;

    /* sanity checking */
    if (!image)
    {
        nrt_Error_init(error, "NULL image after reading header", NRT_CTXT,
                       NRT_ERR_UNK);
        goto CATCH_ERROR;
    }

    if (image->x0 >= image->x1 || image->y0 >= image->y1)
    {
        nrt_Error_init(error, "Invalid image offsets", NRT_CTXT, NRT_ERR_UNK);
        goto CATCH_ERROR;
    }
    if (image->numcomps == 0)
    {
        nrt_Error_init(error, "No image components found", NRT_CTXT,
                       NRT_ERR_UNK);
        goto CATCH_ERROR;
    }

    /* TODO: We need special handling that's not implemented in readTile() to
     *       accommodate partial tiles with more than one band. */
    imageWidth = image->x1 - image->x0;
    imageHeight = image->y1 - image->y0;
    if (image->numcomps > 1 &&
        (imageWidth % tileWidth != 0 || imageHeight % tileHeight != 0))
    {
        nrt_Error_init(error, "No image components found", NRT_CTXT,
                       NRT_ERR_UNK);
        goto CATCH_ERROR;
    }

    if (!impl->container)
    {
        /* initialize the container */
        nrt_Uint32 idx;
        j2k_Component **components = NULL;
        int imageType;

        if (!(components = (j2k_Component**)J2K_MALLOC(
                sizeof(j2k_Component*) * image->numcomps)))
        {
            nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                           NRT_ERR_MEMORY);
            goto CATCH_ERROR;
        }

        for(idx = 0; idx < image->numcomps; ++idx)
        {
            opj_image_comp_t cmp = image->comps[idx];
            if (!(components[idx] = j2k_Component_construct(cmp.w, cmp.h,
                                                            cmp.prec, cmp.sgnd,
                                                            cmp.x0, cmp.y0,
                                                            cmp.dx, cmp.dy,
                                                            error)))
            {
                goto CATCH_ERROR;
            }
        }

        switch(image->color_space)
        {
        case OPJ_CLRSPC_SRGB:
            imageType = J2K_TYPE_RGB;
            break;
        case OPJ_CLRSPC_GRAY:
            imageType = J2K_TYPE_MONO;
            break;
        default:
            imageType = J2K_TYPE_UNKNOWN;
        }

        if (!(impl->container = j2k_Container_construct(image->x1 - image->x0,
                                                        image->y1 - image->y0,
                                                        image->numcomps,
                                                        components,
                                                        tileWidth, tileHeight,
                                                        imageType, error)))
        {
            goto CATCH_ERROR;
        }
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        rc = NRT_FAILURE;
    }

    CLEANUP:
    {
        opj_destroy_cstr_info(&codeStreamInfo);
        OpenJPEG_cleanup(&stream, &codec, &image);
    }
    return rc;
}
Esempio n. 19
0
J2KPRIV( NRT_BOOL) OpenJPEG_initImage(OpenJPEGWriterImpl *impl,
                                      j2k_WriterOptions *writerOps,
                                      nrt_Error *error)
{
    NRT_BOOL rc = NRT_SUCCESS;
    nrt_Uint32 i, nComponents, height, width, tileHeight, tileWidth;
    nrt_Uint32 nBytes;
    j2k_Component *component = NULL;
    size_t uncompressedSize;
    int imageType;
    opj_cparameters_t encoderParams;
    opj_image_cmptparm_t *cmptParams;
    OPJ_COLOR_SPACE colorSpace;

    nComponents = j2k_Container_getNumComponents(impl->container, error);
    width = j2k_Container_getWidth(impl->container, error);
    height = j2k_Container_getHeight(impl->container, error);
    tileWidth = j2k_Container_getTileWidth(impl->container, error);
    tileHeight = j2k_Container_getTileHeight(impl->container, error);
    imageType = j2k_Container_getImageType(impl->container, error);

    /* Set up the encoder parameters.  This defaults to lossless. */
    /* TODO allow overrides somehow? */
    opj_set_default_encoder_parameters(&encoderParams);

    /* For now we are enforcing lossless compression.  If we have a better
     * way to allow overrides in the future, uncomment out the tcp_rates logic
     * below (tcp_rates[0] == 0 via opj_set_default_encoder_parameters()).
     * Also consider setting encoderParams.irreversible = 1; to use the
     * lossy DWT 9-7 instead of the reversible 5-3.
     */

    /*if (writerOps && writerOps->compressionRatio > 0.0001)
        encoderParams.tcp_rates[0] = 1.0 / writerOps->compressionRatio;
    else
        encoderParams.tcp_rates[0] = 4.0;
    */

    /* TODO: These two lines should not be necessary when using lossless
     *       encoding but appear to be needed (at least in OpenJPEG 2.0) -
     *       otherwise we get a seg fault.
     *       The sample opj_compress.c is doing the same thing with a comment
     *       indicating that it's a bug. */
    ++encoderParams.tcp_numlayers;
    encoderParams.cp_disto_alloc = 1;

    if (writerOps && writerOps->numResolutions > 0)
    {
        encoderParams.numresolution = writerOps->numResolutions;
        /* Note, if this isn't set right (see below) it will error out */
    }
    else
    {
        /* 
           OpenJPEG defaults this to 6, but that causes the compressor 
           to fail if the tile sizes are less than 2^6.  So we adjust this
           down if necessary.
        */
        const double logTwo = log(2);
        const OPJ_UINT32 minX = (OPJ_UINT32)floor(log(tileWidth) / logTwo);
        const OPJ_UINT32 minY = (OPJ_UINT32)floor(log(tileHeight) / logTwo);
        const OPJ_UINT32 minXY = (minX < minY) ? minX : minY;
        if (minXY < encoderParams.numresolution)
        {
            encoderParams.numresolution = minXY;
        }
    }

    /* Turn on tiling */
    encoderParams.tile_size_on = 1;
    encoderParams.cp_tx0 = 0;
    encoderParams.cp_ty0 = 0;
    encoderParams.cp_tdx = tileWidth;
    encoderParams.cp_tdy = tileHeight;

    if (!(cmptParams = (opj_image_cmptparm_t*)J2K_MALLOC(sizeof(
            opj_image_cmptparm_t) * nComponents)))
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    memset(cmptParams, 0, sizeof(opj_image_cmptparm_t) * nComponents);

    for(i = 0; i < nComponents; ++i)
    {
        component = j2k_Container_getComponent(impl->container, i, error);
        cmptParams[i].w = j2k_Component_getWidth(component, error);
        cmptParams[i].h = j2k_Component_getHeight(component, error);
        cmptParams[i].prec = j2k_Component_getPrecision(component, error);
        cmptParams[i].x0 = j2k_Component_getOffsetX(component, error);
        cmptParams[i].y0 = j2k_Component_getOffsetY(component, error);
        cmptParams[i].dx = j2k_Component_getSeparationX(component, error);
        cmptParams[i].dy = j2k_Component_getSeparationY(component, error);
        cmptParams[i].sgnd = j2k_Component_isSigned(component, error);
    }

    nBytes = (j2k_Container_getPrecision(impl->container, error) - 1) / 8 + 1;
    uncompressedSize = width * height * nComponents * nBytes;

    /* this is not ideal, but there is really no other way */
    if (!(impl->compressedBuf = (char*)J2K_MALLOC(uncompressedSize)))
    {
        nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                       NRT_ERR_MEMORY);
        goto CATCH_ERROR;
    }
    if (!(impl->compressed = nrt_BufferAdapter_construct(impl->compressedBuf,
                                                         uncompressedSize, 1,
                                                         error)))
    {
        goto CATCH_ERROR;
    }

    if (!(impl->stream = OpenJPEG_createIO(impl->compressed, &impl->userData,
                                           0, 0, error)))
    {
        goto CATCH_ERROR;
    }


    switch(imageType)
    {
    case J2K_TYPE_RGB:
        colorSpace = OPJ_CLRSPC_SRGB;
        break;
    default:
        colorSpace = OPJ_CLRSPC_GRAY;
    }

    if (!(impl->codec = opj_create_compress(OPJ_CODEC_J2K)))
    {
        nrt_Error_init(error, "Error creating OpenJPEG codec", NRT_CTXT,
                       NRT_ERR_INVALID_OBJECT);
        goto CATCH_ERROR;
    }
    if (!(impl->image = opj_image_tile_create(nComponents, cmptParams,
                                              colorSpace)))
    {
        nrt_Error_init(error, "Error creating OpenJPEG image", NRT_CTXT,
                       NRT_ERR_INVALID_OBJECT);
        goto CATCH_ERROR;
    }

    /* for some reason we must also explicitly specify these in the image... */
    impl->image->numcomps = nComponents;
    impl->image->x0 = 0;
    impl->image->y0 = 0;
    impl->image->x1 = width;
    impl->image->y1 = height;
    impl->image->color_space = colorSpace;

    memset(error->message, 0, NRT_MAX_EMESSAGE);
    if(!opj_set_error_handler(impl->codec,
                              OpenJPEG_errorHandler,
                              error))
    {
        nrt_Error_init(error, "Unable to set OpenJPEG error handler", NRT_CTXT,
                       NRT_ERR_UNK);
        goto CATCH_ERROR;
    }

    if (!opj_setup_encoder(impl->codec, &encoderParams, impl->image))
    {
        /*nrt_Error_init(error, "Error setting up OpenJPEG decoder", NRT_CTXT,
          NRT_ERR_INVALID_OBJECT);*/
        goto CATCH_ERROR;
    }

    if (!opj_start_compress(impl->codec, impl->image, impl->stream))
    {
        /*nrt_Error_init(error, "Error starting OpenJPEG compression", NRT_CTXT,
          NRT_ERR_INVALID_OBJECT);*/
        goto CATCH_ERROR;
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        rc = NRT_FAILURE;
    }

    CLEANUP:
    {
        if (cmptParams)
            J2K_FREE(cmptParams);
    }

    return rc;
}
Esempio n. 20
0
OpenJPEGWriter_setTile(J2K_USER_DATA *data, nrt_Uint32 tileX, nrt_Uint32 tileY,
                       const nrt_Uint8 *buf, nrt_Uint32 tileSize,
                       nrt_Error *error)
{
    OpenJPEGWriterImpl *impl = (OpenJPEGWriterImpl*) data;
    NRT_BOOL rc = NRT_SUCCESS;
    nrt_Uint32 xTiles, yTiles, tileIndex, width, height, tileWidth, tileHeight;
    nrt_Uint32 thisTileWidth, thisTileHeight, thisTileSize, nComponents, nBytes;
    nrt_Uint8* newTileBuf = NULL;

    xTiles = j2k_Container_getTilesX(impl->container, error);
    yTiles = j2k_Container_getTilesY(impl->container, error);
    width  = j2k_Container_getWidth(impl->container, error);
    height = j2k_Container_getHeight(impl->container, error);
    tileWidth  = j2k_Container_getTileWidth(impl->container, error);
    tileHeight = j2k_Container_getTileHeight(impl->container, error);
    nComponents = j2k_Container_getNumComponents(impl->container, error);
    nBytes = (j2k_Container_getPrecision(impl->container, error) - 1) / 8 + 1;
    tileIndex = tileY * xTiles + tileX;

    memset(error->message, 0, NRT_MAX_EMESSAGE);
    if(!opj_set_error_handler(impl->codec,
                              OpenJPEG_errorHandler,
                              error))
    {
        nrt_Error_init(error, "Unable to set OpenJPEG error handler", NRT_CTXT,
                       NRT_ERR_UNK);
        goto CATCH_ERROR;
    }

    /* Check for edge case where we may have partial tile */
    thisTileWidth = tileWidth;
    thisTileHeight = tileHeight;
    if (tileX == xTiles - 1 && width % tileWidth != 0)
        thisTileWidth = width % tileWidth;
    if (tileY == yTiles - 1 && height % tileHeight != 0)
        thisTileHeight = height % tileHeight;

    thisTileSize = thisTileWidth * thisTileHeight * nComponents * nBytes;
    if(thisTileSize != tileSize)
        tileSize = thisTileSize;

    if(thisTileWidth < tileWidth)
    {
        /* TODO: The current approach below only works for single band
         *       imagery.  For RGB data, I believe it is stored as all
         *       red, then all green, then all blue, so we would need
         *       a temp buffer rather than reusing the current buffer.
         */
        if (nComponents != 1)
        {
            nrt_Error_init(
                error,
                "Partial tile width not implemented for multi-band",
                NRT_CTXT, NRT_ERR_UNK);
            goto CATCH_ERROR;
        }
        
        /* We have a tile that is wider than it "should" be
         * Need to create smaller buffer to pass to write function
         */
        {
            OPJ_UINT32 ii;
            size_t srcOffset = 0;
            size_t destOffset = 0;
            const size_t srcStride = tileWidth * nBytes;
            const size_t destStride = thisTileWidth * nBytes;
            
            newTileBuf = (nrt_Uint8*) J2K_MALLOC(thisTileSize);
            if(!newTileBuf)
            {
                nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY);
                goto CATCH_ERROR;
            }
            
            for(ii = 0; ii < thisTileHeight; ++ii, srcOffset += srcStride, 
                    destOffset += destStride)
                memcpy(newTileBuf + destOffset, buf + srcOffset, destStride);

            buf = newTileBuf;
        }
    }

    if (!opj_write_tile(impl->codec,
                        tileIndex,
                        (OPJ_BYTE* )buf,
                        tileSize,
                        impl->stream))
    {
        nrt_Error ioError;
        const nrt_Off currentPos = nrt_IOInterface_tell(impl->compressed, &ioError);
        const nrt_Off ioSize = nrt_IOInterface_getSize(impl->compressed, &ioError);
        if (NRT_IO_SUCCESS(currentPos) &&
            NRT_IO_SUCCESS(ioSize) &&
            currentPos + OPENJPEG_STREAM_SIZE >= ioSize)
        {
            /* The write failed because implStreamWrite() failed because
             * nrt_IOInterface_write() failed because we didn't have enough
             * room left in the buffer that we copy to prior to flushing out
             * to disk in OpenJPEGWriter_write().  The buffer is sized to the
             * uncompressed image size, so this only occurs if the compressed
             * image is actually larger than the uncompressed size.
             * TODO: Handle resizing the buffer on the fly when this occurs
             * inside implStreamWrite().  Long-term if we're able to thread
             * per tile, we won't have to reallocate nearly as much.
             */
            nrt_Error_init(error,
                           "Error writing tile: Compressed image is larger "
                            "than uncompressed image",
                            NRT_CTXT,
                            NRT_ERR_INVALID_OBJECT);
        }

        /*nrt_Error_init(error, "Error writing tile", NRT_CTXT,
          NRT_ERR_INVALID_OBJECT);*/
        goto CATCH_ERROR;
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        rc = NRT_FAILURE;
    }

    CLEANUP:
    {
        if(newTileBuf)
            J2K_FREE(newTileBuf);
    }

    return rc;
}
Esempio n. 21
0
OpenJPEGReader_readRegion(J2K_USER_DATA *data, nrt_Uint32 x0, nrt_Uint32 y0,
                          nrt_Uint32 x1, nrt_Uint32 y1, nrt_Uint8 **buf,
                          nrt_Error *error)
{
    OpenJPEGReaderImpl *impl = (OpenJPEGReaderImpl*) data;

    opj_stream_t *stream = NULL;
    opj_image_t *image = NULL;
    opj_codec_t *codec = NULL;
    nrt_Uint64 bufSize;
    nrt_Uint64 offset = 0;
    nrt_Uint32 componentBytes, nComponents;

    if (!OpenJPEG_setup(impl, &stream, &codec, error))
    {
        goto CATCH_ERROR;
    }

    /* unfortunately, we need to read the header every time ... */
    if (!opj_read_header(stream, codec, &image))
    {
        /*nrt_Error_init(error, "Error reading header", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }

    if (x1 == 0)
        x1 = j2k_Container_getWidth(impl->container, error);
    if (y1 == 0)
        y1 = j2k_Container_getHeight(impl->container, error);

    /* only decode what we want */
    if (!opj_set_decode_area(codec, image, x0, y0, x1, y1))
    {
        /*nrt_Error_init(error, "Error decoding area", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }

    nComponents = j2k_Container_getNumComponents(impl->container, error);
    componentBytes = (j2k_Container_getPrecision(impl->container, error) - 1) / 8 + 1;
    bufSize = (nrt_Uint64)(x1 - x0) * (y1 - y0) * componentBytes * nComponents;
    if (buf && !*buf)
    {
        *buf = (nrt_Uint8*)J2K_MALLOC(bufSize);
        if (!*buf)
        {
            nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                           NRT_ERR_MEMORY);
            goto CATCH_ERROR;
        }
    }

    {
        int keepGoing;
        OPJ_UINT32 tileIndex, reqSize;
        OPJ_INT32 tileX0, tileY0, tileX1, tileY1;

        do
        {
            if (!opj_read_tile_header(codec, stream, &tileIndex, &reqSize, &tileX0,
                                      &tileY0, &tileX1, &tileY1, &nComponents,
                                      &keepGoing))
            {
                /*nrt_Error_init(error, "Error reading tile header", NRT_CTXT,
                  NRT_ERR_UNK);*/
                goto CATCH_ERROR;
            }

            if (keepGoing)
            {
                if (!opj_decode_tile_data(codec, tileIndex, (*buf + offset),
                                          reqSize, stream))
                {
                    /*nrt_Error_init(error, "Error decoding tile", NRT_CTXT,
                      NRT_ERR_UNK);*/
                    goto CATCH_ERROR;
                }
                offset += reqSize;
            }
        }
        while (keepGoing);
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        bufSize = 0;
    }

    CLEANUP:
    {
        OpenJPEG_cleanup(&stream, &codec, &image);
    }
    return bufSize;
}
Esempio n. 22
0
OpenJPEGReader_readTile(J2K_USER_DATA *data, nrt_Uint32 tileX, nrt_Uint32 tileY,
                  nrt_Uint8 **buf, nrt_Error *error)
{
    OpenJPEGReaderImpl *impl = (OpenJPEGReaderImpl*) data;

    opj_stream_t *stream = NULL;
    opj_image_t *image = NULL;
    opj_codec_t *codec = NULL;
    nrt_Uint32 bufSize;
    const OPJ_UINT32 tileWidth = j2k_Container_getTileWidth(impl->container, error);
    const OPJ_UINT32 tileHeight = j2k_Container_getTileHeight(impl->container, error);
    size_t numBitsPerPixel = 0;
    size_t numBytesPerPixel = 0;
    nrt_Uint64 fullBufSize = 0;

    if (!OpenJPEG_setup(impl, &stream, &codec, error))
    {
        goto CATCH_ERROR;
    }

    /* unfortunately, we need to read the header every time ... */
    if (!opj_read_header(stream, codec, &image))
    {
        /*nrt_Error_init(error, "Error reading header", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }

    /* only decode what we want */
    if (!opj_set_decode_area(codec, image, tileWidth * tileX, tileHeight * tileY,
                             tileWidth * (tileX + 1), tileHeight * (tileY + 1)))
    {
        /*nrt_Error_init(error, "Error decoding area", NRT_CTXT, NRT_ERR_UNK);*/
        goto CATCH_ERROR;
    }

    {
        int keepGoing;
        OPJ_UINT32 tileIndex, nComponents;
        OPJ_INT32 tileX0, tileY0, tileX1, tileY1;

        if (!opj_read_tile_header(codec, stream, &tileIndex, &bufSize, &tileX0,
                                  &tileY0, &tileX1, &tileY1, &nComponents,
                                  &keepGoing))
        {
            /*nrt_Error_init(error, "Error reading tile header", NRT_CTXT,
              NRT_ERR_UNK);*/
            goto CATCH_ERROR;
        }

        if (keepGoing)
        {
            /* TODO: The way blockIO->cntl->blockOffsetInc is currently
             *       implemented in ImageIO.c corresponds with how a
             *       non-compressed partial block would be laid out in a
             *       NITF - the actual extra columns would have been read.
             *       Not sure how the J2K data is laid out on disk but
             *       OpenJPEG is hiding this from us if the extra columns are
             *       present there.  So whenever we get a partial tile that
             *       isn't at the full width, we need to add in these extra
             *       columns of 0's ourselves.  Potentially we could update
             *       ImageIO.c to not require this instead.  Note that we
             *       don't need to pad out the extra rows for a partial block
             *       that isn't the full height because ImageIO will never try
             *       to memcpy these in - we only need to get the stride to
             *       work out correctly.
             */
            const OPJ_UINT32 thisTileWidth = tileX1 - tileX0;
            const OPJ_UINT32 thisTileHeight = tileY1 - tileY0;
            if (thisTileWidth < tileWidth)
            {
                /* TODO: The current approach below only works for single band
                 *       imagery.  For RGB data, I believe it is stored as all
                 *       red, then all green, then all blue, so we would need
                 *       a temp buffer rather than reusing the current buffer.
                 */
                if (nComponents != 1)
                {
                    nrt_Error_init(
                        error,
                        "Partial tile width not implemented for multi-band",
                        NRT_CTXT, NRT_ERR_UNK);
                    goto CATCH_ERROR;
                }

                numBitsPerPixel =
                    j2k_Container_getPrecision(impl->container, error);
                numBytesPerPixel =
                    (numBitsPerPixel / 8) + (numBitsPerPixel % 8 != 0);
                fullBufSize = tileWidth * thisTileHeight * numBytesPerPixel;
            }
            else
            {
                fullBufSize = bufSize;
            }

            if (buf && !*buf)
            {
                *buf = (nrt_Uint8*)J2K_MALLOC(fullBufSize);
                if (!*buf)
                {
                    nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT,
                                   NRT_ERR_MEMORY);
                    goto CATCH_ERROR;
                }
            }

            if (!opj_decode_tile_data(codec, tileIndex, *buf, bufSize, stream))
            {
                /*nrt_Error_init(error, "Error decoding tile", NRT_CTXT,
                  NRT_ERR_UNK);*/
                goto CATCH_ERROR;
            }

            if (thisTileWidth < tileWidth)
            {
                /* We have a tile that isn't as wide as it "should" be
                 * Need to add in the extra columns ourselves.  By marching
                 * through the rows backwards, we can do this in place.
                 */
                const size_t srcStride = thisTileWidth * numBytesPerPixel;
                const size_t destStride = tileWidth * numBytesPerPixel;
                const size_t numLeftoverBytes = destStride - srcStride;
                OPJ_UINT32 lastRow = thisTileHeight - 1;
                size_t srcOffset = lastRow * srcStride;
                size_t destOffset = lastRow * destStride;
                OPJ_UINT32 ii;
                nrt_Uint8* bufPtr = *buf;

                for (ii = 0;
                     ii < thisTileHeight;
                     ++ii, srcOffset -= srcStride, destOffset -= destStride)
                {
                    nrt_Uint8* const dest = bufPtr + destOffset;
                    memmove(dest, bufPtr + srcOffset, srcStride);
                    memset(dest + srcStride, 0, numLeftoverBytes);
                }
            }
        }
    }

    goto CLEANUP;

    CATCH_ERROR:
    {
        fullBufSize = 0;
    }

    CLEANUP:
    {
        OpenJPEG_cleanup(&stream, &codec, &image);
    }
    return fullBufSize;
}