/* Copyright 1984-2002 The MathWorks, Inc. */ /* * hdfutils.c --- support file for HDF.MEX * * This module contains utility functions shared by the other modules * in support of the HDF API gateway MEX-file HDF.MEX. The utility * functions are prefixed by ha, as in haGetDoubleScalar(). * * IMPORTANT: this module also maintains linked lists of HDF file and * access identifiers. The HDF API buffers some information about * files and the data sets they contain; this information may not get * written out until the appropriate function is called to terminate * access to that identifier. For example, every call to Hopen() * (which returns a file identifier) must be paired by a call to Hclose(). * The HDF MEX-file makes it particularly easy for a user to call * HDF API functions interactively, but this also makes it particularly * easy to forget to terminate access to identifiers. Also, an * inadvertent "clear mex" or a premature "quit" could cause loss of * data. * * So the strategy is this: every function in the HDF gateway that * opens an identifier must record that identifier in the appropriate * linked list. Every function that terminates access to an identifier * must delete that identifier from the list. The function haCleanup() * is registered as the mexAtExit function, and it will close (in the * right order) any identifiers remaining on the lists. * So far there are four lists: * * file_id_list * access_id_list * gr_id_list * ri_id_list * * More lists may be added as the number of supported interfaces grows. */ /* $Revision: 1.1.6.1 $ $Date: 2003/12/13 03:02:23 $ */ static char rcsid[] = "$Id: hdfutils.c,v 1.1.6.1 2003/12/13 03:02:23 batserve Exp $"; #include #include /* Main HDF library header file */ #include "hdf.h" /* HDF-EOS header file */ #include "HdfEosDef.h" /* Multifile scientific dataset interface header file */ #include "mfhdf.h" /* Multifile generalized raster image interface header file */ #include "mfgr.h" /* Vgroup interface header file */ #include "vg.h" /* MATLAB API header file */ #include "mex.h" /* HDFMEX utility functions */ #include "hdfutils.h" #include "hdfvs.h" /* for hdfVSDetachAndForget */ #include "jerror.h" #include "jpeglib.h" #define BUFLEN 128 struct node { int32 idnum; struct node *previous; struct node *next; }; typedef struct node NodeType; typedef struct { NodeType list; intn (*idCloseFcn)(int32); char *name; } ListInfo; static ListInfo listArray[Num_ID_Lists]; static int HDF_library_initialized = 0; /* Use alternative message handlers for jpeg library.*/ static void my_output_message (j_common_ptr); static void my_error_exit (j_common_ptr); /* * haLibraryInitialized * * Purpose: Indicate that HDF library has been called. This * function should be called just before any HDF library calls * are mode. It sets a flag that controls whether the HDF * at_exit function is called. * * Inputs: none * Outputs: none * Return: none */ void haLibraryInitialized(void) { HDF_library_initialized = 1; } /* * haVdetach * * Purpose: Prototype adapter for Vdetach * * Inputs: vgroup_id * Outputs: none * Return: status as an intn */ static intn haVdetach(int32 vgroup_id) { return (intn) Vdetach(vgroup_id); } /* * haANend * * Purpose: Prototype adapter for ANend * * Inputs: ann_id * Outputs: none * Return: status as an intn */ static intn haANend(int32 ann_id) { return (intn) ANend(ann_id); } /* * haInitializeLists * * Purpose: initialize identifier lists * * Input: none * Output: none * Return: none */ void haInitializeLists(void) { listArray[RI_ID_List].list.idnum = -1; listArray[RI_ID_List].list.next = NULL; listArray[RI_ID_List].list.previous = NULL; listArray[RI_ID_List].idCloseFcn = GRendaccess; listArray[RI_ID_List].name = "RI"; listArray[GR_ID_List].list.idnum = -1; listArray[GR_ID_List].list.next = NULL; listArray[GR_ID_List].list.previous = NULL; listArray[GR_ID_List].idCloseFcn = GRend; listArray[GR_ID_List].name = "GR"; listArray[Access_ID_List].list.idnum = -1; listArray[Access_ID_List].list.next = NULL; listArray[Access_ID_List].list.previous = NULL; listArray[Access_ID_List].idCloseFcn = Hendaccess; listArray[Access_ID_List].name = "access"; listArray[File_ID_List].list.idnum = -1; listArray[File_ID_List].list.next = NULL; listArray[File_ID_List].list.previous = NULL; listArray[File_ID_List].idCloseFcn = Hclose; listArray[File_ID_List].name = "file"; listArray[AN_ID_List].list.idnum = -1; listArray[AN_ID_List].list.next = NULL; listArray[AN_ID_List].list.previous = NULL; listArray[AN_ID_List].idCloseFcn = haANend; listArray[AN_ID_List].name = "AN"; listArray[Annot_ID_List].list.idnum = -1; listArray[Annot_ID_List].list.next = NULL; listArray[Annot_ID_List].list.previous = NULL; listArray[Annot_ID_List].idCloseFcn = ANendaccess; listArray[Annot_ID_List].name = "annotation"; listArray[Point_ID_List].list.idnum = -1; listArray[Point_ID_List].list.next = NULL; listArray[Point_ID_List].list.previous = NULL; listArray[Point_ID_List].idCloseFcn = PTdetach; listArray[Point_ID_List].name = "point"; listArray[Pointfile_ID_List].list.idnum = -1; listArray[Pointfile_ID_List].list.next = NULL; listArray[Pointfile_ID_List].list.previous = NULL; listArray[Pointfile_ID_List].idCloseFcn = PTclose; listArray[Pointfile_ID_List].name = "point file"; listArray[Swath_ID_List].list.idnum = -1; listArray[Swath_ID_List].list.next = NULL; listArray[Swath_ID_List].list.previous = NULL; listArray[Swath_ID_List].idCloseFcn = SWdetach; listArray[Swath_ID_List].name = "swath"; listArray[SWFile_ID_List].list.idnum = -1; listArray[SWFile_ID_List].list.next = NULL; listArray[SWFile_ID_List].list.previous = NULL; listArray[SWFile_ID_List].idCloseFcn = SWclose; listArray[SWFile_ID_List].name = "swath file"; listArray[SDS_ID_List].list.idnum = -1; listArray[SDS_ID_List].list.next = NULL; listArray[SDS_ID_List].list.previous = NULL; listArray[SDS_ID_List].idCloseFcn = SDendaccess; listArray[SDS_ID_List].name = "scientific dataset"; listArray[SD_ID_List].list.idnum = -1; listArray[SD_ID_List].list.next = NULL; listArray[SD_ID_List].list.previous = NULL; listArray[SD_ID_List].idCloseFcn = SDend; listArray[SD_ID_List].name = "scientific data file"; listArray[GD_Grid_List].list.idnum = -1; listArray[GD_Grid_List].list.next = NULL; listArray[GD_Grid_List].list.previous = NULL; listArray[GD_Grid_List].idCloseFcn = GDdetach; listArray[GD_Grid_List].name = "grid"; listArray[GD_File_List].list.idnum = -1; listArray[GD_File_List].list.next = NULL; listArray[GD_File_List].list.previous = NULL; listArray[GD_File_List].idCloseFcn = GDclose; listArray[GD_File_List].name = "grid file"; listArray[Vgroup_ID_List].list.idnum = -1; listArray[Vgroup_ID_List].list.next = NULL; listArray[Vgroup_ID_List].list.previous = NULL; listArray[Vgroup_ID_List].idCloseFcn = haVdetach; listArray[Vgroup_ID_List].name = "Vgroup"; listArray[VSdata_ID_List].list.idnum = -1; listArray[VSdata_ID_List].list.next = NULL; listArray[VSdata_ID_List].list.previous = NULL; listArray[VSdata_ID_List].idCloseFcn = hdfVSDetachAndForget; listArray[VSdata_ID_List].name = "Vdata"; listArray[Vfile_ID_List].list.idnum = -1; listArray[Vfile_ID_List].list.next = NULL; listArray[Vfile_ID_List].list.previous = NULL; listArray[Vfile_ID_List].idCloseFcn = Vfinish; /* The same as Vend */ listArray[Vfile_ID_List].name = "Vfile"; } /* * haAddNodeToList * * Purpose: Insert a new node at the beginning of a list * * Inputs: list --- pointer to list * new --- pointer to node * Outputs: none * Return: none */ static void haAddNodeToList(NodeType *list, NodeType *new) { new->next = list->next; new->previous = list; list->next = new; if (new->next != NULL) { new->next->previous = new; } } /* * haDeleteNodeFromList * * Purpose: Delete node from a list; free node memory * * Inputs: node --- pointer to node (this pointer gets freed) * Outputs: none * Return: none */ static void haDeleteNodeFromList(NodeType *node) { node->previous->next = node->next; if (node->next != NULL) { node->next->previous = node->previous; } free((void *) node); } /* * haFindNodeInList * * Purpose: Find a node containing a given value * * Inputs: list --- pointer to list to search * match --- int32 value to search for * Outputs: none * Return: pointer to node found, or NULL if no match is found */ static NodeType *haFindNodeInList(NodeType *list, int32 match) { NodeType *current; int found = 0; current = list->next; while (current != NULL) { if (current->idnum == match) { found = 1; break; } else { current = current->next; } } if (found == 0) { current = NULL; } return(current); } /* * haAddIDToList * * Purpose: Add an HDF interface identifier to the specified list * * Inputs: id --- int32 interface identifier * Outputs: none * Return: SUCCEED or FAIL */ intn haAddIDToList(int32 id, IDList list) { NodeType *listHead = &(listArray[list].list); NodeType *new = NULL; intn result = SUCCEED; mxAssert(listHead != NULL,""); new = (NodeType *) malloc(sizeof(*new)); if (new != NULL) { new->idnum = id; haAddNodeToList(listHead, new); } else { mexWarnMsgTxt("Out of memory in HDF MEX gateway."); result = FAIL; } return(result); } /* * haDeleteIDFromList * * Purpose: Delete interface identifier from the specified list * * Inputs: id * Outputs: none * Return: none */ void haDeleteIDFromList(int32 id, IDList list) { NodeType *match_node; NodeType *listHead = &(listArray[list].list); mxAssert(listHead != NULL,""); match_node = haFindNodeInList(listHead, id); if (match_node != NULL) { haDeleteNodeFromList(match_node); } } /* * haCleanupList * * Purpose: Close all identifiers in list * * Inputs: listInfo * Output: none * Return: none */ static void haCleanupList(ListInfo *listInfo) { NodeType *list = &(listInfo->list); while (list->next != NULL) { (*listInfo->idCloseFcn)(list->next->idnum); haDeleteNodeFromList(list->next); } } /* * haMexAtExit * * Purpose: Close all open identifiers. Print warnings if any * open identifiers were found. * * Inputs: none * Outputs: none * Return: none */ void haMexAtExit(void) { int i; char buffer[256]; for (i = 0; i < Num_ID_Lists; i++) { if (listArray[i].list.next != NULL) { sprintf(buffer, "Closing %s identifiers left open.", listArray[i].name); mexWarnMsgTxt(buffer); haCleanupList(&listArray[i]); } } if (HDF_library_initialized) HPend(); } /* * haQuietCleanup * * Purpose: Close all open identifiers. Don't print warnings. * * Inputs: none * Outputs: none * Return: none */ void haQuietCleanup(void) { int i; for (i = 0; i < Num_ID_Lists; i++) { haCleanupList(&listArray[i]); } } /* * haPrintIDListInfo * * Purpose: Print information about identifer lists to MATLAB command window * * Inputs: none * Outputs: none * Return: none * Side effect: prints information to command window */ void haPrintIDListInfo(void) { NodeType *current; int i; for (i = 0; i < Num_ID_Lists; i++) { if (listArray[i].list.next == NULL) { mexPrintf("No open %s identifiers\n", listArray[i].name); } else { mexPrintf("Open %s identifiers:\n", listArray[i].name); current = listArray[i].list.next; while (current != NULL) { mexPrintf("\t%5d\n", current->idnum); current = current->next; } } } } /* * haStrcmpi - case-insensitive string compare * code borrowed from src/util/strcmpi.c */ int haStrcmpi(const char *s1, const char *s2) { unsigned char c1, c2; if (s1 == NULL) s1 = ""; if (s2 == NULL) s2 = ""; for ( ; (c1 = tolower(*s1)) == (c2 = tolower(*s2)); s1++, s2++) { if (c1 == '\0') { return 0; } } return (int)c1 - (int)c2; } /* * haNarginChk * * Purpose: Make sure number of input arguments falls within a * valid range; produce an error if it doesn't. * * Inputs: nMin --- minimum acceptable number of input arguments * nMax --- maximum acceptable number of input arguments * nIn --- actual number of input arguments * Outputs: none * Return: none */ void haNarginChk(int nMin, int nMax, int nIn) { if (nIn < nMin) { mexErrMsgTxt("Too few input arguments."); } if (nIn > nMax) { mexErrMsgTxt("Too many input arguments."); } } /* * haNargoutChk * * Purpose: Make sure number of output arguments falls within a * valid range; produce an error if it doesn't. * * Inputs: nMin --- minimum acceptable number of output arguments * nMax --- maximum acceptable number of output arguments * nOut --- actual number of output arguments * Outputs: none * Return: none */ void haNargoutChk(int nMin, int nMax, int nOut) { if (nOut < nMin) { mexErrMsgTxt("Too few output arguments."); } if (nOut > nMax) { mexErrMsgTxt("Too many output arguments."); } } /* * haGetEOSCompressionCode * * Purpose: Given MATLAB string array, return HDF-EOS compression code * * Inputs: inStr --- MATLAB string array * Outputs: none * Return: HDF-EOS compression code; errors out if none found */ int32 haGetEOSCompressionCode(const mxArray *inStr) { static struct { char *compStrLong; char *compStrShort; intn compCode; } compCodes[] = { {"hdfe_comp_rle", "rle", HDFE_COMP_RLE}, {"hdfe_comp_skphuff", "skphuff", HDFE_COMP_SKPHUFF}, {"hdfe_comp_deflate", "deflate", HDFE_COMP_DEFLATE}, {"hdfe_comp_none", "none", HDFE_COMP_NONE} }; static int numCompCodes = sizeof(compCodes) / sizeof(*compCodes); char buffer[BUFLEN]; int32 compCode; int k = 0; bool codeFound = false; if (!mxIsChar(inStr)) { mexErrMsgTxt("Compression code must be a string."); } mxGetString(inStr, buffer, BUFLEN); for (k = 0; k < numCompCodes; k++) { if ((haStrcmpi(buffer, compCodes[k].compStrShort) == 0) || (haStrcmpi(buffer, compCodes[k].compStrLong) == 0)) { compCode = compCodes[k].compCode; codeFound = true; break; } } if (! codeFound) { mexErrMsgTxt("Invalid compression code."); } return(compCode); } /* * haGetEOSCompressionParameters * * Purpose: Get the HDF-EOS Compression parameters from a MATLAB array * * Inputs: array - mxArray containing the code * * Outputs: none * * Returns: Compression Code */ void haGetEOSCompressionParameters(const mxArray *array, intn compparm[NUM_EOS_COMP_PARMS]) { int length; double *data; int i; if (!mxIsDouble(array)) mexErrMsgTxt("Invalid compression parameters, must be of class double."); length = mxGetNumberOfElements(array); if (length > NUM_EOS_COMP_PARMS) { mexErrMsgTxt("Compression parameters vector too large."); } data = mxGetPr(array); for (i = 0; i < length; i++) { compparm[i] = (intn) data[i]; } for (i = length; i < NUM_EOS_COMP_PARMS; i++) { compparm[i] = 0; } } /* * haGetEOSMergeCode * * Purpose: Given MATLAB string array, return HDF-EOS merge code * * Inputs: inStr --- MATLAB string array * Outputs: none * Return: HDF-EOS merge code; errors out if none found */ int32 haGetEOSMergeCode(const mxArray *inStr) { static struct { char *mergeStrLong; char *mergeStrShort; intn mergeCode; } mergeCodes[] = { {"hdfe_nomerge", "nomerge", HDFE_NOMERGE}, {"hdfe_automerge", "automerge", HDFE_AUTOMERGE}, }; static int numMergeCodes = sizeof(mergeCodes) / sizeof(*mergeCodes); char buffer[BUFLEN]; int32 mergeCode; int k = 0; bool codeFound = false; if (!mxIsChar(inStr)) { mexErrMsgTxt("Merge code must be a string."); } mxGetString(inStr, buffer, BUFLEN); for (k = 0; k < numMergeCodes; k++) { if ((haStrcmpi(buffer, mergeCodes[k].mergeStrShort) == 0) || (haStrcmpi(buffer, mergeCodes[k].mergeStrLong) == 0)) { mergeCode = mergeCodes[k].mergeCode; codeFound = true; break; } } if (! codeFound) { mexErrMsgTxt("Invalid merge code."); } return(mergeCode); } /* * haGetCompressFlag * * Purpose: Given a string mxArray, return the corresponding HDF * integer-valued compression flag. * * Inputs: inStr --- mxArray containing one of these strings: * 'none', 'jpeg', 'rle', or 'imcomp' * Outputs: none * Return: compression flag */ uint16_T haGetCompressFlag(const mxArray *inStr) { char *compressStr; uint16_T result; mxAssertS(inStr != NULL, "inStr is NULL"); compressStr = haGetString(inStr, "Compression flag"); if (strlen(compressStr) == 0) { mexErrMsgTxt("Compression flag cannot be empty."); } if (haStrcmpi(compressStr, "none") == 0) { result = COMP_NONE; } else if (haStrcmpi(compressStr, "jpeg") == 0) { result = COMP_JPEG; } else if (haStrcmpi(compressStr, "rle") == 0) { result = COMP_RLE; } else if (haStrcmpi(compressStr, "imcomp") == 0) { result = COMP_IMCOMP; } else { mexErrMsgTxt("Compression flag must be 'none', " "'jpeg', 'rle', or 'imcomp'."); } mxFree(compressStr); return(result); } /* * haGetInterlaceString * * Purpose: Given HDF interlace flag, return the corresponding string * * Inputs: il --- HDF interlace flag * Outputs: none * Return: string: "pixel", "line", "component", or "unknown" */ const char *haGetInterlaceString(int32 il) { const char *result; switch (il) { case MFGR_INTERLACE_PIXEL: result = "pixel"; break; case MFGR_INTERLACE_LINE: result = "line"; break; case MFGR_INTERLACE_COMPONENT: result = "component"; break; default: result = "unknown"; break; } return(result); } /* * haGetInterlaceFlag * * Purpose: Given MATLAB string array, return HDF interlace flag value * * Inputs: inStr --- MATLAB string array * Outputs: none * Return: HDF interlace flag value */ int32 haGetInterlaceFlag(const mxArray *inStr) { char *ilStr; int32 result; mxAssertS(inStr != NULL, "inStr is NULL"); ilStr = haGetString(inStr, "Interlace specifier"); if (haStrcmpi(ilStr, "pixel") == 0) { result = MFGR_INTERLACE_PIXEL; } else if (haStrcmpi(ilStr, "line") == 0) { result = MFGR_INTERLACE_LINE; } else if (haStrcmpi(ilStr, "component") == 0) { result = MFGR_INTERLACE_COMPONENT; } else { mexErrMsgTxt("Interlace specifier must be 'pixel', " "'line', or 'component'."); } mxFree(ilStr); return(result); } static struct { char *accessStrLong; char *accessStrShort; intn accessMode; } accessModes[] = { {"dfacc_read", "read", DFACC_READ}, {"dfacc_write", "write", DFACC_WRITE}, {"dfacc_create", "create", DFACC_CREATE}, {"dfacc_all", "all", DFACC_ALL}, {"dfacc_rdonly", "rdonly", DFACC_RDONLY}, {"dfacc_rdwr", "rdwr", DFACC_RDWR}, {"dfacc_rdwr", "readwrite", DFACC_RDWR}, /* this one for compatibility */ {"dfacc_clobber", "clobber", DFACC_CLOBBER}, {"dfacc_default", "default", DFACC_DEFAULT}, {"dfacc_serial", "serial", DFACC_SERIAL}, {"dfacc_parallel", "parallel", DFACC_PARALLEL} }; static int numAccessModes = sizeof(accessModes) / sizeof(*accessModes); /* * haGetAccessMode * * Purpose: Given MATLAB string array, return HDF access mode flag value * * Inputs: inStr --- MATLAB string array * Outputs: none * Return: HDF access mode flag value; errors out if none found */ intn haGetAccessMode(const mxArray *inStr) { char buffer[BUFLEN]; intn access = -1; bool found = false; int k = 0; if (!mxIsChar(inStr)) { mexErrMsgTxt("Access specifier must be a string."); } mxGetString(inStr, buffer, BUFLEN); for (k = 0; k < numAccessModes; k++) { if ((haStrcmpi(buffer, accessModes[k].accessStrShort) == 0) || (haStrcmpi(buffer, accessModes[k].accessStrLong) == 0)) { access = accessModes[k].accessMode; found = true; break; } } if (! found) { mexErrMsgTxt("Invalid access specifier."); } return(access); } /* * haGetFieldIndex * * Purpose: return double value of input or _HDF_VDATA if input is 'vdata'. * * Inputs: f --- MATLAB string array * Outputs: none * Return: field_index parameter */ int32 haGetFieldIndex(const mxArray *f) { char *field_str; int32 field_index; if (mxIsChar(f)) { field_str = haGetString(f,"Field index"); if (haStrcmpi(field_str,"vdata") != 0) { mxFree(field_str); mexErrMsgTxt("Field index must be a field number or the string 'vdata'."); } mxFree(field_str); field_index = _HDF_VDATA; } else field_index = (int32) haGetDoubleScalar(f, "Field index"); return(field_index); } /* * haGetDirection * * Purpose: Given MATLAB string array, return the corresponding HDF direction * flag * * Inputs: inStr --- MATLAB string array * Outputs: none * Return: HDF direction flag */ intn haGetDirection(const mxArray *inStr) { char *directionStr; intn result; mxAssertS(inStr != NULL, "inStr is NULL"); directionStr = haGetString(inStr, "Direction flag"); if (haStrcmpi(directionStr, "forward") == 0) { result = DF_FORWARD; } else if (haStrcmpi(directionStr, "backward") == 0) { result = DF_BACKWARD; } else { mexErrMsgTxt("Direction flag must be 'forward' or 'backward'."); } mxFree(directionStr); return(result); } /* * haGetDoubleScalar * * Purpose: Get double value from MATLAB array; error out if array is * empty or not double * * Inputs: A --- MATLAB array * name --- string identifying what the input array is supposed * to represent. name is used to construct a * meaningful error message. * Outputs: none * Return: double-precision value * * Note: This function does not insist that the input array be * a scalar or that it be real. It just always returns the first * element of the real part. */ double haGetDoubleScalar(const mxArray *A, char *name) { double result; char error_message[255]; static char trailer[] = " must be a scalar double."; mxAssertS(A != NULL, "NULL mxArray pointer"); mxAssertS(name != NULL, "NULL char pointer"); if (!mxIsDouble(A) || mxIsEmpty(A)) { strncpy(error_message, name, 255-strlen(trailer)-1); strcat(error_message, trailer); mexErrMsgTxt(error_message); } result = *mxGetPr(A); return(result); } /* * haGetNonNegativeDoubleScalar * * Purpose: Get non-negative double value from MATLAB array; * error out if array is not a scalar, negative, * complex, or not double * * Inputs: A --- MATLAB array * name --- string identifying what the input array is supposed * to represent. name is used to construct a * meaningful error message. * Outputs: none * Return: double-precision value */ double haGetNonNegativeDoubleScalar(const mxArray *A, char *name) { double result; char error_message[255]; static char trailer[] = " must be a non-negative scalar double."; mxAssertS(A != NULL, "NULL mxArray pointer"); mxAssertS(name != NULL, "NULL char pointer"); if (!mxIsDouble(A) || mxGetNumberOfElements(A) != 1 || mxIsComplex(A) || (*mxGetPr(A) < 0.0)) { strncpy(error_message, name, 255-strlen(trailer)-1); strcat(error_message, trailer); mexErrMsgTxt(error_message); } result = *mxGetPr(A); return(result); } int haGetNumberOfElements(int rank,const int *siz) { int i; int result = 1; for (i=0; i length(dimsizes). * */ int32 haGetDimensions(const mxArray *rank, const mxArray *dimsizes, int32 *siz) { int32 ndims; double *pr; int i; mxAssertS(rank != NULL, "NULL mxArray pointer"); mxAssertS(dimsizes != NULL, "NULL mxArray pointer"); ndims = (int32) haGetDoubleScalar(rank,"Rank"); if (ndims != mxGetNumberOfElements(dimsizes)) { mexErrMsgTxt("Rank must be == length(dimsizes)."); } if (mxGetNumberOfElements(dimsizes) > MAX_VAR_DIMS) { mexErrMsgTxt("Dimsizes vector too long."); } pr = mxGetPr(dimsizes); for (i=0; ijpeg.quality = (intn) haGetDoubleScalar(v,"JPEG quality parameter"); } else if (haStrcmpi(param,"jpeg_force_baseline")==0) { cinfo->jpeg.force_baseline = (intn) haGetDoubleScalar(v, "JPEG force baseline parameter"); } else if (haStrcmpi(param,"skphuff_skp_size")==0) { cinfo->skphuff.skp_size = (intn) haGetDoubleScalar(v,"Skip size"); } else if (haStrcmpi(param,"deflate_level")==0) { cinfo->deflate.level = (intn) haGetDoubleScalar(v,"Deflate level"); } else mexErrMsgTxt("Unknown or invalid parameter."); mxFree(param); } /* * haCreateCharArray * * Purpose: Create an mxChar MATLAB array from a character buffer. * * Inputs: rank -- rank (ndims) of array. * siz -- vector of dimension sizes * data -- character buffer. * n -- number of characters in buffer. * Outputs: none. * Return: MATLAB mxChar array. */ mxArray *haCreateCharArray(int32 rank,const int *siz,const char *data,int32 n) { mxArray *ret = NULL; mxChar *d; int i; if (n==0) ret = EMPTYSTR; else { ret = mxCreateNumericArray(rank,siz,mxCHAR_CLASS,mxREAL); d = (mxChar *)mxGetData(ret); mxAssertS(n == haGetNumberOfElements(rank,siz), "Buffer length and number of array elements must match"); for (i=0; i rank) /* Simple case -- A has wrong size */ { /* Check for the case of the 1-D vector in MATLAB where ndims==2 */ if ((ndims == 2) && (rank == 1)) { if ((dims[0] == 1) && (dims[1] == siz[0])) return 1; else if ((dims[1] == 1) && (dims[0] == siz[0])) return 1; else return 0; } else { return 0; } } else /* complicated case -- treat A as if it has lots of trailing singletons */ { for (i=0; i i ) /* Only swap if DNFT_UCHAR8 is not first */ { temp = allNumberTypes[i]; allNumberTypes[i] = allNumberTypes[k]; allNumberTypes[k] = temp; } return(result); } /* * haMakeChar8First * * Purpose: Make mxCHAR_CLASS map to DFNT_CHAR8 * * Inputs: None * Outputs: None * Return: SUCCEED or FAIL */ intn haMakeChar8First(void) { int i; int k; bool found = false; intn result=SUCCEED; NumberTypeTable temp; for (i=0; i 0) { buffer = mxCalloc(num_elements, element_size); if (buffer == NULL) { HEpush(DFE_NOSPACE,"haMakeHDFDataBuffer",__FILE__,__LINE__); } } return(buffer); } /* * haMakeHDFDataBufferFromCharArray * * Purpose: Given MATLAB char array, allocate a buffer of the desired * HDF data type and copy/cast the char array data into it. * Caller must free the buffer. */ VOIDP haMakeHDFDataBufferFromCharArray(const mxArray *inStr, int32 datatype) { VOIDP *result; mxChar *in_ptr = (mxChar *) mxGetData(inStr); int num_elems = mxGetNumberOfElements(inStr); int k; if ((datatype == DFNT_UCHAR8) || (datatype == DFNT_UCHAR)) { uint8_T *buf_ptr = mxCalloc(num_elems, sizeof(*buf_ptr)); for (k = 0; k < num_elems; k++) { buf_ptr[k] = (uint8_T) in_ptr[k]; } result = (VOIDP) buf_ptr; } else if ((datatype == DFNT_CHAR8) || (datatype == DFNT_CHAR)) { int8_T *buf_ptr = mxCalloc(num_elems, sizeof(*buf_ptr)); for (k = 0; k < num_elems; k++) { buf_ptr[k] = (int8_T) in_ptr[k]; } result = (VOIDP) buf_ptr; } else if (datatype == DFNT_UCHAR16) { uint16_T *buf_ptr = mxCalloc(num_elems, sizeof(*buf_ptr)); for (k = 0; k < num_elems; k++) { buf_ptr[k] = (uint16_T) in_ptr[k]; } result = (VOIDP) buf_ptr; } else if (datatype == DFNT_CHAR16) { int16_T *buf_ptr = mxCalloc(num_elems, sizeof(*buf_ptr)); for (k = 0; k < num_elems; k++) { buf_ptr[k] = (int16_T) in_ptr[k]; } result = (VOIDP) buf_ptr; } else { mexErrMsgTxt("Unrecognized HDF char data type."); } return(result); } /* * haMakeCharArrayFromHDFDataBuffer * * Purpose: Create a MATLAB char array from any of the HDF char types. * This function copies the data, so the calling function * can free or modify the data buffer after this call. * * Inputs: ndims --- number of dimensions of MATLAB char array * siz --- size vector for MATLAB char array * data_type --- HDF data type flag * data --- data buffer * Outputs: none * Return: array --- might be NULL if memory failure */ static mxArray *haMakeCharArrayFromHDFDataBuffer(int ndims, int siz[], int32 data_type, VOIDP data) { mxArray *array = mxCreateNumericArray(ndims, siz, mxCHAR_CLASS, mxREAL); if (array != NULL) { int num_elements = mxGetNumberOfElements(array); mxChar *array_ptr = mxGetChars(array); int k = 0; uchar8 *uchar8_ptr = NULL; char8 *char8_ptr = NULL; uint16_T *uchar16_ptr = NULL; int16_T *char16_ptr = NULL; switch (data_type) { case DFNT_UCHAR8: /* fall-through */ /* * There should be a DFNT_UCHAR case, but it's defined * to be the same as DFNT_UCHAR8, which causes some * compilers to complain. */ uchar8_ptr = (uchar8 *) data; for (k = 0; k < num_elements; k++) { *array_ptr++ = (mxChar) *uchar8_ptr++; } break; case DFNT_CHAR8: /* fall-through */ /* * There should be a DFNT_CHAR case, but it's defined * to be the same as DFNT_CHAR8, which causes some * compilers to complain. */ char8_ptr = (char8 *) data; for (k = 0; k < num_elements; k++) { *array_ptr++ = (mxChar) *char8_ptr++; } break; case DFNT_UCHAR16: uchar16_ptr = (uint16_T *) data; for (k = 0; k < num_elements; k++) { *array_ptr++ = (mxChar) *uchar16_ptr++; } break; case DFNT_CHAR16: char16_ptr = (int16_T *) data; for (k = 0; k < num_elements; k++) { *array_ptr++ = (mxChar) *char16_ptr++; } break; default: mexErrMsgTxt("Unknown HDF char data type."); } } return(array); } /* * haMakeArrayFromHDFDataBuffer * * Purpose: Given a data buffer, HDF data type, and * MATLAB ndims and size vectors, construct * an mxArray from the data buffer. * Automatically construct a MATLAB string * from any of the HDF char data types. * * Inputs: ndims --- number of dimensions of MATLAB array * siz --- MATLAB array size vector * data_type --- HDF data type flag * data --- data buffer * Outputs: ok_to_free --- boolean indicating whether the * calling function is allowed * to free the data buffer * Return: mxArray --- NULL if memory failure */ mxArray *haMakeArrayFromHDFDataBuffer(int ndims, int siz[], int32 data_type, VOIDP data, bool *ok_to_free) { mxArray *array = NULL; mxClassID classID = haGetClassIDFromDataType(data_type); *ok_to_free = false; if (classID == mxUNKNOWN_CLASS) { mexErrMsgTxt("Unsupported HDF data type."); } if ((classID == mxCHAR_CLASS) && (data_type != DFNT_UCHAR16)) { array = haMakeCharArrayFromHDFDataBuffer(ndims, siz, data_type, data); *ok_to_free = true; } else { int emptySiz[2] = {0, 0}; array = mxCreateNumericArray(2, emptySiz, classID, mxREAL); if (mxSetDimensions(array, siz, ndims) != 0) { /* set dimensions failed */ mxDestroyArray(array); array = NULL; } else { mxSetData(array, data); } } if (array == NULL) { HEpush(DFE_NOSPACE,"MakeArrayFromHDFDataBuffer",__FILE__,__LINE__); *ok_to_free = true; } return(array); } /* * haRegJPGHandler * * Purpose: Register message and error handlers in the JPEG library * * Inputs: none * Outputs: none * Return: void */ void haRegJPGHandler() { init_jpg_error_handler( my_error_exit ); init_jpg_message_handler( my_output_message ); } /* * my_error_exit * * Purpose: Error handler for the JPG library * * Inputs: cinfo --- pointer to the JPEG information struct * Outputs: none * Return: void */ static void my_error_exit (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; /* Let the memory manager delete any temp files before we die */ jpeg_destroy(cinfo); (*cinfo->err->format_message) (cinfo, buffer); /* Return gracefully to MATLAB */ mexErrMsgTxt(buffer); } /* * my_output_message * * Purpose: Message handler for the JPG library * * Inputs: cinfo --- pointer to the JPEG information struct * Outputs: none * Return: void */ static void my_output_message (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); /* Send it to MATLAB Command Window */ mexWarnMsgTxt(buffer); }