Skip to content

ReadImage15C

anna-dodd edited this page Jun 3, 2015 · 1 revision

Reading an Image in C (1.5)


There are many ways to read an image using the library. How you read it will determine the speed of the application and the memory footprint. Internally, the image deblocking code uses block-row caching when reading uncompressed imagery. It would be advantageous to your applications to read as much of the image as possible per read operation (obviously, without running out of memory). However, due to the block caching, reading on a per-row basis doesn't incur much of a penalty (with uncompressed imagery). Below we will walk you through some of the steps (and alternatives) of reading imagery.

First off, we want to create a SubWindow, which is used when conducting the read call.
    ...
    subimage = nitf_SubWindow_construct(error);
    assert(subimage);
   
    /* this is just an integer array of the bands you plan on requesting */
    bandList = (nitf_Uint32 *) NITF_MALLOC(sizeof(nitf_Uint32 *) * nBands);
    subimage->startCol = 0;
    subimage->startRow = 0;
   
    /* create a downsampler, if you want -- this is optional */
    pixelSkip = nitf_PixelSkip_construct(rowSkipFactor, columnSkipFactor, error);
    if (!pixelSkip)
    {
        nitf_Error_print(error, stderr, "Pixel Skip construction failed");
        goto CATCH_ERROR;
    }
    if (!nitf_SubWindow_setDownSampler(subimage, pixelSkip, error))
    {
        nitf_Error_print(error, stderr, "Set down sampler failed");
        goto CATCH_ERROR;
    }

        /* for this example, just setup our SubWindow to request ALL bands -- this is how we do that */
    for (band = 0; band < nBands; band++)
        bandList[band] = band;
    subimage->bandList = bandList;
    subimage->numBands = nBands;
    ...


Next, you will want to decide how you want to read the image.

The first example will read the entire image into memory at once.
    ...
    /* create a buffer, where the data will be stored -- one buffer per band */
    buffer = (nitf_Uint8 **) NITF_MALLOC(nBands * sizeof(nitf_Uint8*));
    assert(buffer);
    /* set the window to read ALL rows -- if downsampling, we must account for that */
    subimage->numRows = nRows / rowSkipFactor;
    /* set the window to read ALL columns -- if downsampling, we must account for that */
    subimage->numCols = nColumns / columnSkipFactor;
   
    /* create a size_t size variable that contains the number of bytes per read request */
    subimageSize = subimage->numCols * subimage->numRows * NITF_NBPP_TO_BYTES(nBits);

    /* initialize each band of the buffer request */
    for (i = 0; i < nBands; i++)
    {
        buffer[i] = (nitf_Uint8 *) NITF_MALLOC(subimageSize);
        assert(buffer[i]);
    }
   
    /* read the entire image! -- the padded variable will say whether the returned data was padded in any way */
    if (!nitf_ImageReader_read
            (imageReader, subimage, buffer, &padded, error))
    {
        nitf_Error_print(error, stderr, "Read failed");
        goto CATCH_ERROR;
    }
    ...



This example shows how to read one row at a time.
    ...
    /* create a buffer, where the data will be stored -- one buffer per band */
    buffer = (nitf_Uint8 **) NITF_MALLOC(nBands * sizeof(nitf_Uint8*));
    assert(buffer);
    /* set the window to read one row at a time */
    subimage->numRows = 1;
    /* set the window to read ALL columns -- if downsampling, we must account for that */
    subimage->numCols = nColumns / columnSkipFactor;
   
    /* create a size_t size variable that contains the number of bytes per read request */
    subimageSize = subimage->numCols * subimage->numRows * NITF_NBPP_TO_BYTES(nBits);

    /* initialize each band of the buffer request */
    for (i = 0; i < nBands; i++)
    {
        buffer[i] = (nitf_Uint8 *) NITF_MALLOC(subimageSize);
        assert(buffer[i]);
    }
   
    /* loop over the rows, skipping if necessary */
    for(i = 0; i < nRows; i += rowSkipFactor)
    {   
        subimage->startRow = i;
        if (!nitf_ImageReader_read
                (imageReader, subimage, buffer, &padded, error))
        {
            nitf_Error_print(error, stderr, "Read failed");
            goto CATCH_ERROR;
        }
        /* do something with the data ... */
    }
    ...


In version 1.5 of the NITF library, an additional feature is available for RGB 24-bit data, and for IQ complex data, when the data is band interleaved by pixel. Instead of asking the library to deinterleave the pixels as it usually, would, you can ask for the data to be treated as a single band of data. For the 24-bit case, for instance, you can set the number of bands in the sub window to 1, and allocating the sub image buffer size to 3 times the usual amount:

    /* for RGB24 images, let's just write out the 1 band
     * - this will be MUCH faster
     */

    if (nBands == 3
        && segment->subheader->imageMode->raw[0] == 'P'
        && strncmp("RGB", segment->subheader->imageRepresentation->raw, 3) == 0
        && NITF_NBPP_TO_BYTES(nBits) == 1
        && (strncmp("NC", segment->subheader->imageCompression->raw, 2)
            || strncmp("NM", segment->subheader->imageCompression->raw, 2)))
    {
        subimageSize *= nBands;
        nBands = 1;
        printf("**Using optimization to write out a 3-band RGB pix-interleaved image**\n");
    }

    subimage = nitf_SubWindow_construct(error);
    assert(subimage);

    buffer = (nitf_Uint8 **) NITF_MALLOC(nBands * sizeof(nitf_Uint8*));
    band = 0;
    bandList = (nitf_Uint32 *) NITF_MALLOC(sizeof(nitf_Uint32 *) * nBands);
    subimage->startCol = 0;
    subimage->startRow = 0;
    subimage->numRows = nRows / rowSkipFactor;
    subimage->numCols = nColumns / columnSkipFactor;

    pixelSkip = nitf_PixelSkip_construct(rowSkipFactor, columnSkipFactor, error);
    if (!pixelSkip)
    {
        nitf_Error_print(error, stderr, "Pixel Skip construction failed");
        goto CATCH_ERROR;
    }
    if (!nitf_SubWindow_setDownSampler(subimage, pixelSkip, error))
    {
        nitf_Error_print(error, stderr, "Set down sampler failed");
        goto CATCH_ERROR;
    }

    for (band = 0; band < nBands; band++)
        bandList[band] = band;
    subimage->bandList = bandList;
    subimage->numBands = nBands;
Clone this wiki locally