Esempio n. 1
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. 2
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. 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
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. 5
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. 6
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. 7
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. 8
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;
}
Esempio n. 9
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. 10
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;
}