/* pass in a negative number for bandNum if you don't want a band in the name */ char *makeBandName(const char *rootFile, const char* segment, int segmentNum, int bandNum) { char *file = (char *) NITF_MALLOC(NITF_MAX_PATH); int pos; /* find end slash */ for (pos = strlen(rootFile) - 1; pos && rootFile[pos] != '\\' && rootFile[pos] != '/'; pos--); if (bandNum >= 0) NITF_SNPRINTF(file, NITF_MAX_PATH, "%s__%s_%d_band_%d", &rootFile[pos + 1], segment, segmentNum, bandNum); else NITF_SNPRINTF(file, NITF_MAX_PATH, "%s__%s_%d", &rootFile[pos + 1], segment, segmentNum); /* remove decimals */ for (pos = strlen(file) - 1; pos; pos--) { if (file[pos] == '.') { file[pos] = '_'; } } strcat(file, ".man"); printf("File: %s\n", file); return file; }
/* We may want to rethink this function a bit. * The NITF spec. has many fields with a BINARY_INTEGER type * This could mean that the field contains 3 8-bit binary integers * For that example, the length of the field is 3, which isn't an integer size * Thus, that wouldn't work here if we just assumed BINARY_INTEGER has ONE integer in the field */ NITFPRIV(NITF_BOOL) fromIntToString(nitf_Field * field, char *outValue, size_t length, nitf_Error * error) { char buffer[256]; size_t actualLength = 0; /* These are all two-step processes 1) get native int 2) NITF_SNPRINTF */ switch (field->length) { case 2: { nitf_Int16 int16; if (!toInt16(field, &int16, error)) goto CATCH_ERROR; actualLength = NITF_SNPRINTF(buffer, 256, "%d", int16); } break; case 4: { nitf_Int32 int32; if (!toInt32(field, &int32, error)) goto CATCH_ERROR; actualLength = NITF_SNPRINTF(buffer, 256, "%ld", (long) int32); } break; case 8: { nitf_Int64 int64; if (!toInt64(field, &int64, error)) goto CATCH_ERROR; actualLength = NITF_SNPRINTF(buffer, 256, "%lld", int64); } break; default: { /* otherwise, it must not be an integer value */ return fromStringToString(field, outValue, length, error); } } if (actualLength > length) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "Out value too small [%d] size required", strlen(buffer)); return NITF_FAILURE; } strcpy(outValue, buffer); return NITF_SUCCESS; CATCH_ERROR: return NITF_FAILURE; }
NITFPRIV(const char **) doInit(nitf_DLL * dll, const char *prefix, nitf_Error * error) { NITF_PLUGIN_INIT_FUNCTION init; const char **ident; char name[NITF_MAX_PATH]; memset(name, 0, NITF_MAX_PATH); NITF_SNPRINTF(name, NITF_MAX_PATH, "%s%s", prefix, NITF_PLUGIN_INIT_SUFFIX); init = (NITF_PLUGIN_INIT_FUNCTION) nitf_DLL_retrieve(dll, name, error); if (!init) { nitf_Error_print(error, stdout, "Invalid init hook in DSO"); return NULL; } /* Else, call it */ ident = (*init)(error); if (!ident) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_OBJECT, "The plugin [%s] is not retrievable", prefix); return NULL; } return ident; }
NITFPRIV(NITF_BOOL) insertCreator(nitf_DLL* dso, nitf_HashTable* hash, const char* ident, const char* suffix, nitf_Error* error) { /* We are trying to find tre_main */ NITF_DLL_FUNCTION_PTR dsoMain = NULL; /* Get the name of the handler */ char name[NITF_MAX_PATH]; char* p = NULL; if (!nitf_DLL_isValid(dso)) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "DSO is not valid for [%s]", ident); } memset(name, 0, NITF_MAX_PATH); NITF_SNPRINTF(name, NITF_MAX_PATH, "%s%s", ident, suffix); nitf_Utils_replace(name, ' ', '_'); /* No error has occurred (yet) */ #if NITF_DEBUG_PLUGIN_REG printf("Loading function [%s] in dso at [%p]\n", name, dso); #endif /* Retrieve the main */ dsoMain = nitf_DLL_retrieve(dso, name, error); if (!dsoMain) { /* If it didnt work, we are done */ return NITF_FAILURE; } #if NITF_DEBUG_PLUGIN_REG if (nitf_HashTable_exists(hash, ident)) { printf("Warning, overriding [%s] hook", ident); } #endif return nitf_HashTable_insert(hash, ident, dsoMain, error); }
NITFAPI(NITF_BOOL) nitf_Field_setInt64(nitf_Field * field, nitf_Int64 number, nitf_Error * error) { char numberBuffer[20]; /* Holds converted number */ nitf_Uint32 numberLen; /* Length of converted number string */ /* Check the field type */ if (field->type == NITF_BINARY) { nitf_Error_init(error, "Integer set for binary field ", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return (NITF_FAILURE); } /* Convert thte number to a string */ NITF_SNPRINTF(numberBuffer, 20, "%lld", number); numberLen = strlen(numberBuffer); /* if it's resizable and a different length, we resize */ if (field->resizable && numberLen != field->length) { if (!nitf_Field_resizeField(field, numberLen, error)) return NITF_FAILURE; } if (numberLen > field->length) { nitf_Error_init(error, "Value for BCS_N field is too long", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return (NITF_FAILURE); } /* Transfer and pad result */ if (field->type == NITF_BCS_N) copyAndFillZeros(field, numberBuffer, numberLen, error); else copyAndFillSpaces(field, numberBuffer, numberLen, error); return (NITF_SUCCESS); }
NITFAPI(nitf_TRECursor) nitf_TRECursor_begin(nitf_TRE * tre) { nitf_Error error; nitf_TRECursor tre_cursor; nitf_TREDescription *dptr; tre_cursor.loop = nitf_IntStack_construct(&error); tre_cursor.loop_idx = nitf_IntStack_construct(&error); tre_cursor.loop_rtn = nitf_IntStack_construct(&error); tre_cursor.numItems = 0; tre_cursor.index = 0; tre_cursor.looping = 0; /* init the pointers */ tre_cursor.end_ptr = NULL; tre_cursor.prev_ptr = NULL; tre_cursor.desc_ptr = NULL; if (tre) { /* set the start index */ tre_cursor.index = -1; /* count how many descriptions there are */ dptr = ((nitf_TREPrivateData*)tre->priv)->description; while (dptr && (dptr->data_type != NITF_END)) { tre_cursor.numItems++; dptr++; } tre_cursor.end_ptr = dptr; memset(tre_cursor.tag_str, 0, TAG_BUF_LEN); NITF_SNPRINTF(tre_cursor.tag_str, TAG_BUF_LEN, "%s", ((nitf_TREPrivateData*)tre->priv)->description->tag); tre_cursor.tre = tre; } return tre_cursor; }
/* * Take a buffer of memory that we read out of a NITF segment * and write it one of two-ways. * * For non RGB 24-bit true-color data, write each band separately. * This demonstrates the typical, non-accelerated, generic read. * * For 24-bit true-color, if its band interleaved by pixel (mode 'P') * demonstrate accelerated mode, and read without de-interleaving pixels, * then write it to one big image as is. * */ void writeImage(nitf_ImageSegment * segment, char *imageName, nitf_ImageReader * deserializer, int imageNumber, nitf_Uint32 rowSkipFactor, nitf_Uint32 columnSkipFactor, NITF_BOOL optz, nitf_Error * error) { nitf_Uint32 nBits, nBands, xBands, nRows, nColumns; size_t subimageSize; nitf_SubWindow *subimage; unsigned int i; int padded; nitf_Uint8 **buffer = NULL; nitf_Uint32 band; nitf_Uint32 *bandList = NULL; nitf_DownSampler *pixelSkip; /* TODO, replace these macros! */ NITF_TRY_GET_UINT32(segment->subheader->numBitsPerPixel, &nBits, error); NITF_TRY_GET_UINT32(segment->subheader->numImageBands, &nBands, error); NITF_TRY_GET_UINT32(segment->subheader->numMultispectralImageBands, &xBands, error); nBands += xBands; NITF_TRY_GET_UINT32(segment->subheader->numRows, &nRows, error); NITF_TRY_GET_UINT32(segment->subheader->numCols, &nColumns, error); subimageSize = (nRows / rowSkipFactor) * (nColumns / columnSkipFactor) * NITF_NBPP_TO_BYTES(nBits); printf("Image number: %d\n", imageNumber); printf("NBANDS -> %d\n" "XBANDS -> %d\n" "NROWS -> %d\n" "NCOLS -> %d\n" "PVTYPE -> %.*s\n" "NBPP -> %.*s\n" "ABPP -> %.*s\n" "PJUST -> %.*s\n" "IMODE -> %.*s\n" "NBPR -> %.*s\n" "NBPC -> %.*s\n" "NPPBH -> %.*s\n" "NPPBV -> %.*s\n" "IC -> %.*s\n" "COMRAT -> %.*s\n", nBands, xBands, nRows, nColumns, (int)segment->subheader->pixelValueType->length, segment->subheader->pixelValueType->raw, (int)segment->subheader->numBitsPerPixel->length, segment->subheader->numBitsPerPixel->raw, (int)segment->subheader->actualBitsPerPixel->length, segment->subheader->actualBitsPerPixel->raw, (int)segment->subheader->pixelJustification->length, segment->subheader->pixelJustification->raw, (int)segment->subheader->imageMode->length, segment->subheader->imageMode->raw, (int)segment->subheader->numBlocksPerRow->length, segment->subheader->numBlocksPerRow->raw, (int)segment->subheader->numBlocksPerCol->length, segment->subheader->numBlocksPerCol->raw, (int)segment->subheader->numPixelsPerHorizBlock->length, segment->subheader->numPixelsPerHorizBlock->raw, (int)segment->subheader->numPixelsPerVertBlock->length, segment->subheader->numPixelsPerVertBlock->raw, (int)segment->subheader->imageCompression->length, segment->subheader->imageCompression->raw, (int)segment->subheader->compressionRate->length, segment->subheader->compressionRate->raw); if (optz) { /* * There is an accelerated mode for band-interleaved by pixel data. * In that case, we assume that the user doesnt want the data * de-interleaved into separate band buffers. To make this work * you have to tell us that you want only one band back, * and you have to provide us a singular buffer that is the * actual number of bands x the pixel size. Then we will * read the window and not de-interleave. * To demonstrate, for RGB24 images, let's we 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 accelerated 3-band RGB mode pix-interleaved image\n"); } if (nBands == 2 && segment->subheader->NITF_IMODE->raw[0] == 'P' && NITF_NBPP_TO_BYTES(nBits) == 4 && segment->subheader->bandInfo[0]->NITF_ISUBCAT->raw[0] == 'I' && (strncmp("NC", segment->subheader->NITF_IC->raw, 2) || strncmp("NM", segment->subheader->NITF_IC->raw, 2))) { subimageSize *= nBands; nBands = 1; printf("Using accelerated 2-band IQ mode pix-interleaved image\n"); } } subimage = nitf_SubWindow_construct(error); assert(subimage); /* * You need a buffer for each band (unless this is an * accelerated IQ complex or RGB read, in which case, you * can set the number of bands to 1, and size your buffer * accordingly to receive band-interleaved by pixel data) */ buffer = (nitf_Uint8 **) NITF_MALLOC(nBands * sizeof(nitf_Uint8*)); /* An iterator for bands */ band = 0; /* * This tells us what order to give you bands in. Normally * you just want it in the order of the banding. For example, * in a non-accelerated band-interleaved by pixel cases, you might * have a band of magnitude and a band of phase. If you order the * bandList backwards, the phase buffer comes first in the output */ bandList = (nitf_Uint32 *) NITF_MALLOC(sizeof(nitf_Uint32 *) * nBands); /* This example reads all rows and cols starting at 0, 0 */ subimage->startCol = 0; subimage->startRow = 0; /* Request rows is the full rows dividied by pixel skip (usually 1) */ subimage->numRows = nRows / rowSkipFactor; /* Request columns is the full columns divided by pixel skip (usually 1) */ subimage->numCols = nColumns / columnSkipFactor; /* Construct our pixel skip downsampler (does nothing if skips are 1) */ 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; assert(buffer); for (i = 0; i < nBands; i++) { buffer[i] = (nitf_Uint8 *) NITF_MALLOC(subimageSize); assert(buffer[i]); } if (!nitf_ImageReader_read (deserializer, subimage, buffer, &padded, error)) { nitf_Error_print(error, stderr, "Read failed"); goto CATCH_ERROR; } for (i = 0; i < nBands; i++) { nitf_IOHandle toFile; char file[NITF_MAX_PATH]; int pos; /* find end slash */ for (pos = strlen(imageName) - 1; pos && imageName[pos] != '\\' && imageName[pos] != '/'; pos--); pos = pos == 0 ? pos : pos + 1; NITF_SNPRINTF(file, NITF_MAX_PATH, "%s_%d__%d_%d_%d_band_%d", &imageName[pos], imageNumber, nRows / rowSkipFactor, nColumns / columnSkipFactor, nBits, i); /* remove decimals */ for (pos = strlen(file) - 1; pos; pos--) if (file[pos] == '.') file[pos] = '_'; strcat(file, ".out"); printf("File: %s\n", file); toFile = nitf_IOHandle_create(file, NITF_ACCESS_WRITEONLY, NITF_CREATE, error); if (NITF_INVALID_HANDLE(toFile)) { nitf_Error_print(error, stderr, "IO handle creation failed for raw band"); goto CATCH_ERROR; } if (!nitf_IOHandle_write(toFile, (const char *) buffer[i], subimageSize, error)) { nitf_Error_print(error, stderr, "IO handle write failed for raw band"); goto CATCH_ERROR; } nitf_IOHandle_close(toFile); } /* free buffers */ for (i = 0; i < nBands; i++) NITF_FREE(buffer[i]); NITF_FREE(buffer); NITF_FREE(bandList); nitf_SubWindow_destruct(&subimage); nitf_DownSampler_destruct(&pixelSkip); return; CATCH_ERROR: /* free buffers */ for (i = 0; i < nBands; i++) NITF_FREE(buffer[i]); NITF_FREE(buffer); NITF_FREE(bandList); printf("ERROR processing\n"); }
NITFAPI(NITF_BOOL) nitf_Field_setReal(nitf_Field * field, const char *type, NITF_BOOL plus, double value, nitf_Error *error) { nitf_Uint32 precision; /* Format precision */ nitf_Uint32 bufferLen; /* Length of buffer */ char *buffer; /* Holds intermediate and final results */ char fmt[64]; /* Format used */ /* Check type */ if ( (strcmp(type, "f") != 0) && (strcmp(type, "e") != 0) && (strcmp(type, "E") != 0)) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "Invalid conversion type %s", type); return(NITF_FAILURE); } /* Allocate buffer used to build value */ /* The 64 covers the puncuation and exponent and is overkill */ bufferLen = field->length * 2 + 64; buffer = NITF_MALLOC(bufferLen + 1); if (buffer == NULL) { nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); return(NITF_FAILURE); } /* Try a precision that will be too large and then adjust it based on the length of what you get. This results in a left justified string with the maximum number of decmal places. What you are actually figuring is the number of digits in the whole part of the number. */ precision = field->length; /* Must be too big */ if (plus) NITF_SNPRINTF(fmt, 64, "%%+-1.%dl%s", precision, type); else NITF_SNPRINTF(fmt, 64, "%%-1.%dl%s", precision, type); NITF_SNPRINTF(buffer, bufferLen + 1, fmt, value); bufferLen = strlen(buffer); /* if it's resizable and a different length, we resize */ if (field->resizable && bufferLen != field->length) { if (!nitf_Field_resizeField(field, bufferLen, error)) return NITF_FAILURE; } if (bufferLen > field->length) { if (precision > bufferLen - field->length) precision -= bufferLen - field->length; else precision = 0; if (plus) NITF_SNPRINTF(fmt, 64, "%%+-1.%dl%s", precision, type); else NITF_SNPRINTF(fmt, 64, "%%-1.%dl%s", precision, type); NITF_SNPRINTF(buffer, bufferLen + 1, fmt, value); } if (!nitf_Field_setRawData(field, buffer, field->length, error)) { NITF_FREE(buffer); return(NITF_FAILURE); } NITF_FREE(buffer); return(NITF_SUCCESS); }
NITFAPI(int) nitf_TRECursor_iterate(nitf_TRECursor * tre_cursor, nitf_Error * error) { nitf_TREDescription *dptr; int *stack; /* used for in conjuction with the stacks */ int index; /* used for in conjuction with the stacks */ int loopCount = 0; /* tells how many times to loop */ int loop_rtni = 0; /* used for temp storage */ int loop_idxi = 0; /* used for temp storage */ int numIfs = 0; /* used to keep track of nested Ifs */ int numLoops = 0; /* used to keep track of nested Loops */ int done = 0; /* flag used for special cases */ char idx_str[10][10]; /* used for keeping track of indexes */ if (!tre_cursor->loop || !tre_cursor->loop_idx || !tre_cursor->loop_rtn) { /* not initialized */ nitf_Error_init(error, "Unhandled TRE Value data type", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } /* count how many descriptions there are */ dptr = ((nitf_TREPrivateData*)tre_cursor->tre->priv)->description; while (!done) { done = 1; /* set the flag */ /* iterate the index */ tre_cursor->index++; if (tre_cursor->index < tre_cursor->numItems) { memset(tre_cursor->tag_str, 0, TAG_BUF_LEN); tre_cursor->prev_ptr = tre_cursor->desc_ptr; tre_cursor->desc_ptr = &dptr[tre_cursor->index]; /* if already in a loop, prepare the array of values */ if (tre_cursor->looping) { stack = tre_cursor->loop_idx->st; /* assert, because we only prepare for 10 */ assert(tre_cursor->looping <= 10); for (index = 0; index < tre_cursor->looping; index++) { NITF_SNPRINTF(idx_str[index], TAG_BUF_LEN, "[%d]", stack[index]); } } /* check if it is an actual item now */ /* ASCII string */ if ((tre_cursor->desc_ptr->data_type == NITF_BCS_A) || /* ASCII number */ (tre_cursor->desc_ptr->data_type == NITF_BCS_N) || /* raw bytes */ (tre_cursor->desc_ptr->data_type == NITF_BINARY)) { NITF_SNPRINTF(tre_cursor->tag_str, TAG_BUF_LEN, "%s", tre_cursor->desc_ptr->tag); /* check if data is part of an array */ if (tre_cursor->looping) { stack = tre_cursor->loop_idx->st; for (index = 0; index < tre_cursor->looping; index++) { char entry[64]; NITF_SNPRINTF(entry, 64, "[%d]", stack[index]); strcat(tre_cursor->tag_str, entry); } } /* check to see if we don't know the length */ if (tre_cursor->desc_ptr->data_count == NITF_TRE_CONDITIONAL_LENGTH) { /* compute it from the function given */ if (tre_cursor->desc_ptr->special) { /* evaluate the special string as a postfix expression */ tre_cursor->length = nitf_TRECursor_evaluatePostfix( tre_cursor->tre, idx_str, tre_cursor->looping, tre_cursor->desc_ptr->special, error); if (tre_cursor->length < 0) { /* error! */ nitf_Error_print(error, stderr, "TRE expression error:"); return NITF_FAILURE; } } else { /* should we return failure here? */ /* for now, just set the length to 0, which forces an iteration... */ tre_cursor->length = 0; } if (tre_cursor->length == 0) { return nitf_TRECursor_iterate(tre_cursor, error); } } else { /* just set the length that was in the TREDescription */ tre_cursor->length = tre_cursor->desc_ptr->data_count; } } /* NITF_LOOP, NITF_IF, etc. */ else if ((tre_cursor->desc_ptr->data_type >= NITF_LOOP) && (tre_cursor->desc_ptr->data_type < NITF_END)) { done = 0; /* set the flag */ /* start of a loop */ if (tre_cursor->desc_ptr->data_type == NITF_LOOP) { loopCount = nitf_TRECursor_evalLoops(tre_cursor->tre, tre_cursor->desc_ptr, idx_str, tre_cursor->looping, error); if (loopCount > 0) { tre_cursor->looping++; /* record loopcount in @loop stack */ nitf_IntStack_push(tre_cursor->loop, loopCount, error); /* record i in @loop_rtn stack */ nitf_IntStack_push(tre_cursor->loop_rtn, tre_cursor->index, error); /* record a 0 in @loop_idx stack */ nitf_IntStack_push(tre_cursor->loop_idx, 0, error); } else { numLoops = 1; /* skip until we see the matching ENDLOOP */ while (numLoops && (++tre_cursor->index < tre_cursor->numItems)) { tre_cursor->desc_ptr = &dptr[tre_cursor->index]; if (tre_cursor->desc_ptr->data_type == NITF_LOOP) numLoops++; else if (tre_cursor->desc_ptr->data_type == NITF_ENDLOOP) numLoops--; } } } /* end of a loop */ else if (tre_cursor->desc_ptr->data_type == NITF_ENDLOOP) { /* retrieve loopcount from @loop stack */ loopCount = nitf_IntStack_pop(tre_cursor->loop, error); /* retrieve loop_rtn from @loop_rtn stack */ loop_rtni = nitf_IntStack_pop(tre_cursor->loop_rtn, error); /* retrieve loop_idx from @loop_idx stack */ loop_idxi = nitf_IntStack_pop(tre_cursor->loop_idx, error); if (--loopCount > 0) { /* record loopcount in @loop stack */ nitf_IntStack_push(tre_cursor->loop, loopCount, error); /* record i in @loop_rtn stack */ nitf_IntStack_push(tre_cursor->loop_rtn, loop_rtni, error); /* record idx in @loop_idx stack */ nitf_IntStack_push(tre_cursor->loop_idx, ++loop_idxi, error); /* jump to the start of the loop */ tre_cursor->index = loop_rtni; } else { --tre_cursor->looping; } } /* an if clause */ else if (tre_cursor->desc_ptr->data_type == NITF_IF) { if (!nitf_TRECursor_evalIf (tre_cursor->tre, tre_cursor->desc_ptr, idx_str, tre_cursor->looping, error)) { numIfs = 1; /* skip until we see the matching ENDIF */ while (numIfs && (++tre_cursor->index < tre_cursor->numItems)) { tre_cursor->desc_ptr = &dptr[tre_cursor->index]; if (tre_cursor->desc_ptr->data_type == NITF_IF) numIfs++; else if (tre_cursor->desc_ptr->data_type == NITF_ENDIF) numIfs--; } } } } else { nitf_Error_init(error, "Unhandled TRE Value data type", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } } else { /* should return FALSE instead. signifies we are DONE iterating! */ return NITF_FAILURE; } } return NITF_SUCCESS; }