/*! * \ingroup JWlz * \brief Free's a temporary 2D array. * \param aDat Array data structure. * \param aSz Array size. * \param dSKey Data structure identification. * \param isCpy Copy flag for JNI functions. */ void WlzJavaArray2DFree(void *aDat, WlzIVertex2 aSz, int dSKey, jboolean isCpy) { if(isCpy && aDat && (aSz.vtX > 0) && (aSz.vtY > 0)) { switch(dSKey) { case WLZ_JPM_KEY_INT_ARY2: /* FALLTHROUGH */ case WLZ_JPM_KEY_SHORT_ARY2: /* FALLTHROUGH */ case WLZ_JPM_KEY_BYTE_ARY2: /* FALLTHROUGH */ case WLZ_JPM_KEY_FLOAT_ARY2: /* FALLTHROUGH */ case WLZ_JPM_KEY_DOUBLE_ARY2: Alc2Free((void **)aDat); break; default: break; } } }
/*! * \return Object read from file. * \ingroup WlzExtFF * \brief Reads a 2D Woolz object from the given file using the given * (2D) file format. * \param fP Given file. * \param fFmt Given file format (must be a 2D file * format). * \param dstErr Destination error number ptr, may be * NULL. */ static WlzObject *WlzEffReadObjStack2D(FILE *fP, WlzEffFormat fFmt, WlzErrorNum *dstErr) { WlzObject *obj = NULL; unsigned char **data = NULL; WlzIVertex2 imgSz, imgOrg; WlzErrorNum errNum = WLZ_ERR_NONE; imgSz.vtX = 0; imgSz.vtY = 0; imgOrg.vtX = 0; imgOrg.vtY = 0; errNum = WlzEffReadObjStackData2D(fP, fFmt, &imgSz, &data); if(errNum == WLZ_ERR_NONE) { obj = WlzFromArray2D((void **)data, imgSz, imgOrg, WLZ_GREY_UBYTE, WLZ_GREY_UBYTE, 0.0, 1.0, 0, 1, &errNum); } if(data) { if(obj) { AlcFree(data); /* **data used by object */ } else { Alc2Free((void **)data); } } if(dstErr) { *dstErr = errNum; } return(obj); }
int main(int argc, char **argv) { FILE *inFile = NULL; /* used to read Woolz object */ /* FILE *outFile = NULL; used to read Woolz object */ int i; int startShell = -10, endShell = -15, startSection = -10, endSection = -15; int startLoop = -10, endLoop = -15; int downOrUp = 0; int option; int numP_in_Z= 10; int numOf2DWlzFiles = 0; int sectionLength_N = 40; int subSubSectionLength_L = sectionLength_N /2; int numberOfSampleP_k = 2; int numOfTrackUpOrDown = 5; int startTrackingFile = 5; int iloop=1, test=0; double DisForInOut = 15, DisForInOutGuid = 15; double minDis = 10.; /* char *outFileStr; unused */ unsigned char **TwoDImageFilesNameList; char *ContourFilesNameList = NULL; char *surfacePointFileName = NULL, *surfaceInPointFileName = NULL, *surfaceOutPointFileName = NULL; /* WlzDVertex3 *SurfacePatchPoints; unused */ WlzErrorNum errNum = WLZ_ERR_NONE; AlcErrno alcErr = ALC_ER_NONE; /* read the argument list and check for an input file */ static char optList[] = "s:t:n:o:O:i:l:L:j:J:a:A:b:B:c:d:e:E:f:F:g:G:h"; while( (option = getopt(argc, argv, optList)) != EOF ) { switch( option ) { case 'h': usage(argv[0]); return(0); case 'L': ContourFilesNameList = optarg; break; case 't': if(sscanf(optarg, "%d", &downOrUp) != 1) { printf("read error"); exit(1); } break; case 'd': if(sscanf(optarg, "%lg", &minDis) != 1) { printf("read error"); exit(1); } break; case 'f': if(sscanf(optarg, "%lg", &DisForInOut) != 1) { printf("read error"); exit(1); } break; case 'F': if(sscanf(optarg, "%lg", &DisForInOutGuid) != 1) { printf("read error"); exit(1); } break; case 'g': if(sscanf(optarg, "%d", &numOfTrackUpOrDown) != 1) { printf("read error"); exit(1); } break; case 'G': if(sscanf(optarg, "%d", &startTrackingFile) != 1) { printf("read error"); exit(1); } break; case 'n': if(sscanf(optarg, "%d", &numP_in_Z) != 1) { printf("read error"); exit(1); } break; case 'l': if(sscanf(optarg, "%d", &iloop) != 1) { printf("read error"); exit(1); } break; case 'j': if(sscanf(optarg, "%d", &numberOfSampleP_k) != 1) { printf("read error"); exit(1); } break; case 'J': if(sscanf(optarg, "%d", §ionLength_N) != 1) { printf("read error"); exit(1); } break; case 'c': if(sscanf(optarg, "%d", &subSubSectionLength_L) != 1) { printf("read error"); exit(1); } break; case 'o': /* outFileStr = optarg; unused */ break; case 's': surfacePointFileName = optarg; break; case 'i': surfaceInPointFileName = optarg; break; case 'O': surfaceOutPointFileName = optarg; break; case 'a': if(sscanf(optarg, "%d", &startShell) != 1) { printf("read error"); exit(1); } break; case 'A': if(sscanf(optarg, "%d", &endShell) != 1) { printf("read error"); exit(1); } break; case 'b': if(sscanf(optarg, "%d", &startSection) != 1) { printf("read error"); exit(1); } break; case 'B': if(sscanf(optarg, "%d", &endSection) != 1) { printf("read error"); exit(1); } case 'e': if(sscanf(optarg, "%d", &startLoop) != 1) { printf("read error"); exit(1); } break; case 'E': if(sscanf(optarg, "%d", &endLoop) != 1) { printf("read error"); exit(1); } break; default: return(0); } } /* allocate memory for the file name list */ alcErr = AlcUnchar2Calloc(&TwoDImageFilesNameList, 50, 120); if(alcErr != ALC_ER_NONE) { printf("allocate memory for 2D array of file list"); exit(1); } /* Read the contour Wlz file name List */ if((inFile = fopen(ContourFilesNameList, "r")) == NULL ) { printf("cannot open the 2D image files list file.\n"); exit(1); } i=0; while(!feof(inFile)) { fscanf(inFile, "%s", *(TwoDImageFilesNameList + i )); /* printf("%s\n", *(TwoDImageFilesNameList + i ) ); */ i++; } fclose(inFile); inFile = NULL; numOf2DWlzFiles = i-1; if( 2 * numOfTrackUpOrDown + 1 > numOf2DWlzFiles) { printf("there are not enough 2D image files to track.\n"); exit(0); } if( ( startTrackingFile - numOfTrackUpOrDown >0 ) || ( startTrackingFile + numOfTrackUpOrDown) > numOf2DWlzFiles ) { printf("there are not enough 2D image files to track if we use the file as a start.\n"); exit(0); } /* ---- output for test ---- */ /* if(test && ( errNum == WLZ_ERR_NONE ) ) { OutPutSectionsForTest(WObjS, WObj2D, outFile, outFileStr, iloop, &errNum); } */ /*---------- extract contour and track down or up to get the surface patch ----------- */ if( (!test) && ( errNum == WLZ_ERR_NONE ) ) { /* SurfacePatchPoints = unused */ (void )WlzGeometryTrackUpAndDown_s( numP_in_Z, startTrackingFile, numOfTrackUpOrDown, DisForInOutGuid, DisForInOut, TwoDImageFilesNameList, numOf2DWlzFiles, downOrUp, sectionLength_N, subSubSectionLength_L, numberOfSampleP_k, surfacePointFileName, surfaceInPointFileName, surfaceOutPointFileName, startShell, endShell, startSection, endSection, minDis, &errNum ); } Alc2Free( (void **)TwoDImageFilesNameList); return ( 0 ); }
/*! * \return Autocorrelated object or NULL on error. * \ingroup WlzRegistration * \brief Computes the autocorrelation of the given 2D object, see * WlzAutoCor(). * \param gObj Given object. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzAutoCor2D(WlzObject *gObj, WlzErrorNum *dstErr) { WlzIVertex2 aSz, wSz, aOrg, wOrg; WlzIBox2 box; double **wAr = NULL, **aAr = NULL; WlzObject *aObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if(gObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(gObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(gObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } if(errNum == WLZ_ERR_NONE) { box = WlzBoundingBox2I(gObj, &errNum); aSz.vtX = box.xMax - box.xMin + 1; aSz.vtY = box.yMax - box.yMin + 1; /* Make sure aSz is even in x and y. */ if((aSz.vtX & 1) != 0) { aSz.vtX += 1; } if((aSz.vtY & 1) != 0) { aSz.vtY += 1; } wOrg.vtX = box.xMin - (aSz.vtX / 2); wOrg.vtY = box.yMin - (aSz.vtY / 2); wSz.vtX = aSz.vtX * 2; wSz.vtY = aSz.vtY * 2; (void )AlgBitNextPowerOfTwo((unsigned int *)&(wSz.vtX), wSz.vtX); (void )AlgBitNextPowerOfTwo((unsigned int *)&(wSz.vtY), wSz.vtY); errNum = WlzToArray2D((void ***)&wAr, gObj, wSz, wOrg, 0, WLZ_GREY_DOUBLE); } if(errNum == WLZ_ERR_NONE) { (void )AlgAutoCorrelate2D(wAr, wSz.vtX, wSz.vtY); if(AlcDouble2Malloc(&aAr, aSz.vtY, aSz.vtX) != ALC_ER_NONE) { errNum = WLZ_ERR_MEM_ALLOC; } } if(errNum == WLZ_ERR_NONE) { WlzAutoCorRearrange2D(aAr, aSz, wAr, wSz); aOrg.vtX = -(aSz.vtX / 2); aOrg.vtY = -(aSz.vtY / 2); aObj = WlzFromArray2D((void **)aAr, aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0, 0, 0, &errNum); } if(errNum != WLZ_ERR_NONE) { if(aObj != NULL) { (void )WlzFreeObj(aObj); } } (void )Alc2Free((void **)wAr); (void )Alc2Free((void **)aAr); if(dstErr) { *dstErr = errNum; } return(aObj); }
/*! * \return Woolz error code. * \ingroup WlzExtFF * \brief Writes the given Woolz object to the given file(s) * using the ANALYZE 7.5 file format. The given file name is * used to generate the '.hdr' and '.img' filenames. * \param gvnFileName Given file name with .hdr, .img or no * extension. * \param obj Given woolz object. */ WlzErrorNum WlzEffWriteObjAnl(const char *gvnFileName, WlzObject *obj) { int cnt = 0; double dMin, dMax; FILE *fP = NULL; void *data = NULL; WlzGreyP dataP; WlzEffAnlDsr dsr; WlzGreyType gType; WlzVertex org, sz; char *fileName = NULL, *hdrFileName = NULL, *imgFileName = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; dataP.v = NULL; if((gvnFileName == NULL) || (*gvnFileName == '\0')) { errNum = WLZ_ERR_PARAM_NULL; } else if(obj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(obj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { errNum = WlzEffAnlFileNames(&fileName, &hdrFileName, &imgFileName, gvnFileName); } /* Fill in the ANALYZE file header data structures. */ if(errNum == WLZ_ERR_NONE) { (void )memset(&dsr, 0, sizeof(WlzEffAnlDsr)); switch(obj->type) { case WLZ_2D_DOMAINOBJ: org.i2.vtX = obj->domain.i->kol1; org.i2.vtY = obj->domain.i->line1; sz.i2.vtX = obj->domain.i->lastkl - org.i2.vtX + 1; sz.i2.vtY = obj->domain.i->lastln - org.i2.vtY + 1; if((sz.i2.vtX <= 0) || (sz.i2.vtY <= 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else { dsr.dim.dim[0] = 2; dsr.dim.dim[1] = sz.i2.vtX; dsr.dim.dim[2] = sz.i2.vtY; dsr.dim.pixdim[0] = 2; dsr.dim.pixdim[1] = 1.0; dsr.dim.pixdim[2] = 1.0; } break; case WLZ_3D_DOMAINOBJ: org.i3.vtX = obj->domain.p->kol1; org.i3.vtY = obj->domain.p->line1; org.i3.vtZ = obj->domain.p->plane1; sz.i3.vtX = obj->domain.p->lastkl - org.i3.vtX + 1; sz.i3.vtY = obj->domain.p->lastln - org.i3.vtY + 1; sz.i3.vtZ = obj->domain.p->lastpl - org.i3.vtZ + 1; if((sz.i3.vtX <= 0) || (sz.i3.vtY <= 0) || (sz.i3.vtZ <= 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else { dsr.dim.dim[0] = 3; dsr.dim.dim[1] = sz.i3.vtX; dsr.dim.dim[2] = sz.i3.vtY; dsr.dim.dim[3] = sz.i3.vtZ; dsr.dim.pixdim[0] = 3; dsr.dim.pixdim[1] = obj->domain.p->voxel_size[0]; dsr.dim.pixdim[2] = obj->domain.p->voxel_size[1]; dsr.dim.pixdim[3] = obj->domain.p->voxel_size[2]; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { (void )WlzGreyStats(obj, &gType, &dMin, &dMax, NULL, NULL, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { dsr.dim.glMax = (int )ceil(dMax); dsr.dim.glMin = (int )floor(dMin); switch(gType) { case WLZ_GREY_INT: dsr.dim.dataType = WLZEFF_ANL_DT_SIGNED_INT; dsr.dim.bitPix = 32; break; case WLZ_GREY_SHORT: dsr.dim.dataType = WLZEFF_ANL_DT_SIGNED_SHORT; dsr.dim.bitPix = 16; break; case WLZ_GREY_UBYTE: dsr.dim.dataType = WLZEFF_ANL_DT_UNSIGNED_CHAR; dsr.dim.bitPix = 8; break; case WLZ_GREY_FLOAT: dsr.dim.dataType = WLZEFF_ANL_DT_FLOAT; dsr.dim.bitPix = 32; break; case WLZ_GREY_DOUBLE: dsr.dim.dataType = WLZEFF_ANL_DT_DOUBLE; dsr.dim.bitPix = 64; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { dsr.hk.hdrSz = 348; dsr.hk.regular = 'r'; dsr.hk.extents = 16384; (void )strcpy(dsr.hist.descrip, "Converted from Woolz"); (void )strcpy(dsr.hist.originator, "Woolz"); (void )strcpy(dsr.hist.generated, "Woolz"); } /* Get Woolz object's values as an array. */ if(WLZ_ERR_NONE == errNum) { switch(obj->type) { case WLZ_2D_DOMAINOBJ: cnt = sz.i2.vtX * sz.i2.vtY; errNum = WlzToArray2D((void ***)&data, obj, sz.i2, org.i2, 0, gType); if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: dataP.inp = *(int **)data; break; case WLZ_GREY_SHORT: dataP.shp = *(short **)data; break; case WLZ_GREY_UBYTE: dataP.ubp = *(WlzUByte **)data; break; case WLZ_GREY_FLOAT: dataP.flp = *(float **)data; break; case WLZ_GREY_DOUBLE: dataP.dbp = *(double **)data; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_3D_DOMAINOBJ: cnt = sz.i3.vtX * sz.i3.vtY * sz.i3.vtZ; errNum = WlzToArray3D((void ****)&data, obj, sz.i3, org.i3, 0, gType); if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: dataP.inp = **(int ***)data; break; case WLZ_GREY_SHORT: dataP.shp = **(short ***)data; break; case WLZ_GREY_UBYTE: dataP.ubp = **(WlzUByte ***)data; break; case WLZ_GREY_FLOAT: dataP.flp = **(float ***)data; break; case WLZ_GREY_DOUBLE: dataP.dbp = **(double ***)data; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Open the ANALYZE .hdr file and write the header information. */ if(errNum == WLZ_ERR_NONE) { if((fP = fopen(hdrFileName, "w")) == NULL) { errNum = WLZ_ERR_WRITE_EOF; } #ifdef _WIN32 else if(_setmode(_fileno(fP), 0x8000) == -1) { errNum = WLZ_ERR_READ_EOF; } #endif } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrKey(fP, &dsr); } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrImageDim(fP, &dsr); } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrDataHistory(fP, &dsr); } if(fP) { (void )fclose(fP); fP = NULL; } /* Open the ANALYZE .img file and write the image data. */ if(errNum == WLZ_ERR_NONE) { if((fP = fopen(imgFileName, "w")) == NULL) { errNum = WLZ_ERR_WRITE_EOF; } #ifdef _WIN32 else if(_setmode(_fileno(fP), 0x8000) == -1) { errNum = WLZ_ERR_READ_EOF; } #endif } if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: errNum = WlzEffWriteAnlInt(fP, cnt, dataP.inp); break; case WLZ_GREY_SHORT: errNum = WlzEffWriteAnlShort(fP, cnt, dataP.shp); break; case WLZ_GREY_UBYTE: errNum = WlzEffWriteAnlChar(fP, cnt, dataP.ubp); break; case WLZ_GREY_FLOAT: errNum = WlzEffWriteAnlFloat(fP, cnt, dataP.flp); break; case WLZ_GREY_DOUBLE: errNum = WlzEffWriteAnlDouble(fP, cnt, dataP.dbp); break; default: break; } } if(fP) { (void )fclose(fP); } if(data) { switch(obj->type) { case WLZ_2D_DOMAINOBJ: Alc2Free((void **)data); break; case WLZ_3D_DOMAINOBJ: Alc3Free((void ***)data); break; default: break; } } (void )AlcFree(fileName); (void )AlcFree(hdrFileName); (void )AlcFree(imgFileName); return(errNum); }
/*! * \return New Woolz domain object with maximal domain and grey * values which encode the gradient's direction or NULL * on error. * \ingroup WlzFeatures * \brief Computes the maximal domain and gradient direction of * given Woolz 2D domain object. * \note All the objects domains are known to be the same. * \param grdM Gradient magnitude. * \param grdY Gradient (partial derivative) * through lines. * \param grdX Gradient (partial derivative) * through columns. * \param minThrV Minimum gradient value to * consider. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzNMSuppress2D(WlzObject *grdM, WlzObject *grdY, WlzObject *grdX, WlzPixelV minThrV, WlzErrorNum *dstErr) { int idN, inLen, outLen, inLnIdx = 0; WlzGreyType gType, bufType; WlzIVertex2 bufSz, inPos, outPos, orgPos; WlzValues tmpVal; WlzDomain dstDom, grdDom; WlzIntervalWSpace tmpIWSp = {0}, grdMIWSp = {0}, grdYIWSp = {0}, grdXIWSp = {0}; WlzGreyWSpace tmpGWSp, grdMGWSp, grdYGWSp, grdXGWSp; WlzPixelV zeroV; WlzGreyP grdMBufGP, grdYBufGP, grdXBufGP; WlzDynItvPool pool; WlzObject *dstObj = NULL, *tmpObj = NULL; void *grdYBuf = NULL, *grdXBuf = NULL; void **grdMBuf = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; tmpVal.core = NULL; pool.itvBlock = NULL; dstDom.core = NULL; if((grdM->type != WLZ_2D_DOMAINOBJ) || (grdY->type != WLZ_2D_DOMAINOBJ) || (grdX->type != WLZ_2D_DOMAINOBJ)) { errNum = WLZ_ERR_OBJECT_NULL; } else if((grdM->domain.core == NULL) || (grdY->domain.core == NULL) || (grdX->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else if((grdM->values.core == NULL) || (grdY->values.core == NULL) || (grdX->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { /* Find required buffer type (WLZ_GREY_DOUBLE or WLZ_GREY_INT). */ bufType = WLZ_GREY_INT; gType = WlzGreyTableTypeToGreyType(grdM->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } else { gType = WlzGreyTableTypeToGreyType(grdY->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } else { gType = WlzGreyTableTypeToGreyType(grdX->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } } } } } } } /* Convert minimum gradient threshold value. */ if(errNum == WLZ_ERR_NONE) { if(bufType == WLZ_GREY_INT) { errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_INT); } else /* bufType == WLZ_GREY_DOUBLE */ { errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_DOUBLE); } } if(errNum == WLZ_ERR_NONE) { grdDom = grdM->domain; /* Make destination object with WLZ_GREY_UBYTE greys. */ zeroV.type = WLZ_GREY_UBYTE; zeroV.v.inv = 0; tmpVal.v = WlzNewValueTb(grdM, WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_UBYTE, NULL), zeroV, &errNum); if(errNum == WLZ_ERR_NONE) { /* Use the input domain while calculating the new maximal domain. */ tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, grdM->domain, tmpVal, NULL, NULL, &errNum); } } /* Initialize the memory pool with some size of block. Any +ve number * greater than the maximum number of intervals in any destination line * would work but the fewer allocations then the more efficient the code, * hence this attempt to guess the required number of intervals in the * destination domain. */ if(errNum == WLZ_ERR_NONE) { pool.itvsInBlock = (((grdDom.i->lastkl - grdDom.i->kol1 + 1) * (grdDom.i->lastln - grdDom.i->line1 + 1)) / 64) + grdDom.i->lastkl - grdDom.i->kol1 + 1024; } /* Make gradient buffers. */ if(errNum == WLZ_ERR_NONE) { bufSz.vtY = 3; bufSz.vtX = grdDom.i->lastkl - grdDom.i->kol1 + 1; if(bufType == WLZ_GREY_INT) { if((AlcInt2Malloc((int ***)&grdMBuf, bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) || ((grdYBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL) || ((grdXBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } else { grdYBufGP.inp = (int *)grdYBuf; grdXBufGP.inp = (int *)grdXBuf; } } else /* bufType == WLZ_GREY_DOUBLE */ { if((AlcDouble2Malloc((double ***)&grdMBuf, bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) || ((grdYBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL) || ((grdXBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } else { grdYBufGP.dbp = (double *)grdYBuf; grdXBufGP.dbp = (double *)grdXBuf; } } } /* Make destination interval domain with interval lines but not intervals. */ if(errNum == WLZ_ERR_NONE) { dstDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL, grdDom.i->line1, grdDom.i->lastln, grdDom.i->kol1, grdDom.i->lastkl, &errNum); } if(errNum == WLZ_ERR_NONE) { /* Scan down through the gradient objects. */ if(((errNum = WlzInitGreyScan(tmpObj, &tmpIWSp, &tmpGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdM, &grdMIWSp, &grdMGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdY, &grdYIWSp, &grdYGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdX, &grdXIWSp, &grdXGWSp)) == WLZ_ERR_NONE)) { orgPos.vtX = grdDom.i->kol1; orgPos.vtY = grdDom.i->line1; while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&grdMIWSp)) == WLZ_ERR_NONE)) { inLen = grdMIWSp.rgtpos - grdMIWSp.lftpos + 1; inPos.vtX = grdMIWSp.lftpos - orgPos.vtX; /* Process any lines between this and the last by clearing the * gradient magnitude buffer . */ if(grdMIWSp.nwlpos > 0) { idN = (grdMIWSp.nwlpos >= 3)? 3: grdMIWSp.nwlpos; while(--idN >= 0) { inPos.vtY = grdMIWSp.linpos - orgPos.vtY - idN; inLnIdx = (3 + inPos.vtY) % 3; if(bufType == WLZ_GREY_INT) { WlzValueSetInt(*((int **)grdMBuf + inLnIdx), 0, bufSz.vtX); } else /* bufType == WLZ_GREY_DOUBLE */ { WlzValueSetDouble(*((double **)grdMBuf + inLnIdx), 0, bufSz.vtX); } } } /* Copy intervals to values buffers. */ if(bufType == WLZ_GREY_INT) { grdMBufGP.inp = *((int **)grdMBuf + inLnIdx); } else /* bufType == WLZ_GREY_DOUBLE */ { grdMBufGP.dbp = *((double **)grdMBuf + inLnIdx); } WlzValueCopyGreyToGrey(grdMBufGP, inPos.vtX, bufType, grdMGWSp.u_grintptr, 0, grdMGWSp.pixeltype, inLen); if(grdMIWSp.intrmn == 0) { while((errNum == WLZ_ERR_NONE) && (tmpIWSp.linpos < grdMIWSp.linpos)) { outPos.vtY = tmpIWSp.linpos - orgPos.vtY; if(outPos.vtY >= 0) { outLen = tmpIWSp.rgtpos - tmpIWSp.lftpos + 1; outPos.vtX = tmpIWSp.lftpos - orgPos.vtX; WlzValueCopyGreyToGrey(grdYBufGP, 0, bufType, grdYGWSp.u_grintptr, 0, grdYGWSp.pixeltype, outLen); WlzValueCopyGreyToGrey(grdXBufGP, 0, bufType, grdXGWSp.u_grintptr, 0, grdXGWSp.pixeltype, outLen); if(bufType == WLZ_GREY_INT) { errNum = WlzNMSuppress2DBufI(dstDom.i, (int **)grdMBuf, (int *)grdYBuf, (int *)grdXBuf, &pool, tmpGWSp.u_grintptr.ubp, outLen, outPos, orgPos, minThrV.v.inv); } else /* bufType == WLZ_GREY_DOUBLE */ { errNum = WlzNMSuppress2DBufD(dstDom.i, (double **)grdMBuf, (double *)grdYBuf, (double *)grdXBuf, &pool, tmpGWSp.u_grintptr.ubp, outLen, outPos, orgPos, minThrV.v.dbv); } } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&tmpIWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&grdYIWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&grdXIWSp); } } } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } if(tmpIWSp.gryptr == &tmpGWSp) { (void )WlzEndGreyScan(&tmpIWSp, &tmpGWSp); } if(grdMIWSp.gryptr == &grdMGWSp) { (void )WlzEndGreyScan(&grdMIWSp, &grdMGWSp); } if(grdYIWSp.gryptr == &grdYGWSp) { (void )WlzEndGreyScan(&grdYIWSp, &grdYGWSp); } if(grdXIWSp.gryptr == &grdXGWSp) { (void )WlzEndGreyScan(&grdXIWSp, &grdXGWSp); } } if(errNum == WLZ_ERR_NONE) { if((errNum = WlzStandardIntervalDomain(dstDom.i)) == WLZ_ERR_NONE) { dstObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, dstDom, tmpVal, NULL, NULL, &errNum); } } if(tmpObj) { WlzFreeObj(tmpObj); } if(errNum != WLZ_ERR_NONE) { if(tmpObj == NULL) { if(dstDom.core) { (void )WlzFreeDomain(dstDom); } if(tmpVal.core) { (void )WlzFreeValues(tmpVal); } } } if(grdMBuf) { Alc2Free(grdMBuf); } if(grdYBuf) { AlcFree(grdYBuf); } if(grdXBuf) { AlcFree(grdXBuf); } if(dstErr) { *dstErr = errNum; } return(dstObj); }
/*! * \return New object with the rojection. * \ingroup WlzTransform * \brief Use the view transform to define a projection from * 3D to 2D and then project the object onto this plane. * The object supplied to this function must be a 3D * spatial domain object (WLZ_3D_DOMAINOBJ) with either * no values or for integration WLZ_GREY_UBYTE values. * Integration will assign each output pixel the sum of * all input voxels mapped via either the domain density * or the voxel density. * The integration is controled by the integrate parameter * with valid values: * WLZ_PROJECT_INT_MODE_NONE - a "shadow domain" without values * is computed, * WLZ_PROJECT_INT_MODE_DOMAIN - the voxels of the domain are * integrated using * \f[ p = \frac{1}{255} n d \f] * WLZ_PROJECT_INT_MODE_VALUES - the voxel values are integrated * using * \f[ p = \frac{1}{255} \sum{l\left[v\right]}. \f] * Where * \f$p\f$ is the projected image value, * \f$n\f$ is the number of voxels projected for \f$p\f$, * \f$d\f$ is the density of domain voxels, * \f$l\f$ is the voxel value density look up table and * \f$v\f$ is a voxel value. * \param obj The given object. * \param vStr Given view structure defining the * projection plane. * \param intMod This may take three values: * WLZ_PROJECT_INT_MODE_NONE, * WLZ_PROJECT_INT_MODE_DOMAIN or * WLZ_PROJECT_INT_MODE_VALUES. * \param denDom Density of domain voxels this value * is not used unless the integration * mode is WLZ_PROJECT_INT_MODE_DOMAIN. * \param denVal Density look up table for object * voxel density values which must be * an array of 256 values. This may be * NULL if the integration mode is not * WLZ_PROJECT_INT_MODE_VALUES. * \param depth If greater than zero, the projection * depth perpendicular to the viewing * plane. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzProjectObjToPlane(WlzObject *obj, WlzThreeDViewStruct *vStr, WlzProjectIntMode intMod, WlzUByte denDom, WlzUByte *denVal, double depth, WlzErrorNum *dstErr) { int nThr = 1, itvVal = 0; WlzIVertex2 prjSz; WlzIBox2 prjBox = {0}; double pln[4]; WlzObject *bufObj = NULL, *prjObj = NULL; WlzThreeDViewStruct *vStr1 = NULL; double **vMat = NULL; WlzValues nullVal; WlzErrorNum errNum = WLZ_ERR_NONE; WlzAffineTransform *rescaleTr = NULL; WlzGreyValueWSpace **gVWSp = NULL; void ***prjAry = NULL; const double eps = 0.000001; #ifdef WLZ_DEBUG_PROJECT3D_TIME struct timeval times[3]; #endif /* WLZ_DEBUG_PROJECT3D_TIME */ nullVal.core = NULL; if(obj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(obj->type != WLZ_3D_DOMAINOBJ) { errNum = WLZ_ERR_OBJECT_TYPE; } else if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) { errNum = WLZ_ERR_DOMAIN_TYPE; } else if(vStr == NULL) { errNum = WLZ_ERR_TRANSFORM_NULL; } else if((intMod == WLZ_PROJECT_INT_MODE_VALUES) && (obj->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } #ifdef WLZ_DEBUG_PROJECT3D_TIME gettimeofday(times + 0, NULL); #endif /* WLZ_DEBUG_PROJECT3D_TIME */ /* Create new view transform without voxel scaling. The voxel scaling * is done after the projection. */ if(errNum == WLZ_ERR_NONE) { if((vStr1 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) != NULL) { vStr1->fixed = vStr->fixed; vStr1->theta = vStr->theta; vStr1->phi = vStr->phi; vStr1->zeta = vStr->zeta; vStr1->dist = vStr->dist; vStr1->scale = vStr->scale; vStr1->voxelSize[0] = 1.0; vStr1->voxelSize[1] = 1.0; vStr1->voxelSize[2] = 1.0; vStr1->voxelRescaleFlg = 0; vStr1->interp = vStr->interp; vStr1->view_mode = vStr->view_mode; vStr1->up = vStr->up; vStr1->initialised = WLZ_3DVIEWSTRUCT_INIT_NONE; vMat = vStr1->trans->mat; errNum = WlzInit3DViewStructAffineTransform(vStr1); if(errNum == WLZ_ERR_NONE) { errNum = Wlz3DViewStructTransformBB(obj, vStr1); } if(errNum != WLZ_ERR_NONE) { WlzFree3DViewStruct(vStr1); vStr1 = NULL; } } } /* Compute bounding box of the projection. */ if(errNum == WLZ_ERR_NONE) { prjBox.xMin = WLZ_NINT(vStr1->minvals.vtX); prjBox.yMin = WLZ_NINT(vStr1->minvals.vtY); prjBox.xMax = WLZ_NINT(vStr1->maxvals.vtX); prjBox.yMax = WLZ_NINT(vStr1->maxvals.vtY); prjSz.vtX = prjBox.xMax - prjBox.xMin + 1; prjSz.vtY = prjBox.yMax - prjBox.yMin + 1; } /* Compute post projection scaling. */ if((errNum == WLZ_ERR_NONE) && (vStr->voxelRescaleFlg != 0)) { WlzIBox2 sBox; WlzIVertex2 sSz; WlzThreeDViewStruct *vStr2; vStr2 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum); if(errNum == WLZ_ERR_NONE) { vStr2->fixed = vStr->fixed; vStr2->theta = vStr->theta; vStr2->phi = vStr->phi; vStr2->zeta = vStr->zeta; vStr2->dist = vStr->dist; vStr2->scale = vStr->scale; vStr2->voxelSize[0] = vStr->voxelSize[0]; vStr2->voxelSize[1] = vStr->voxelSize[1]; vStr2->voxelSize[2] = vStr->voxelSize[2]; vStr2->voxelRescaleFlg = vStr->voxelRescaleFlg; vStr2->interp = vStr->interp; vStr2->view_mode = vStr->view_mode; vStr2->up = vStr->up; vStr2->initialised = WLZ_3DVIEWSTRUCT_INIT_NONE; errNum = WlzInit3DViewStructAffineTransform(vStr2); if(errNum == WLZ_ERR_NONE) { errNum = Wlz3DViewStructTransformBB(obj, vStr2); } if(errNum == WLZ_ERR_NONE) { sBox.xMin = WLZ_NINT(vStr2->minvals.vtX); sBox.yMin = WLZ_NINT(vStr2->minvals.vtY); sBox.xMax = WLZ_NINT(vStr2->maxvals.vtX); sBox.yMax = WLZ_NINT(vStr2->maxvals.vtY); sSz.vtX = sBox.xMax - sBox.xMin + 1; sSz.vtY = sBox.yMax - sBox.yMin + 1; rescaleTr = WlzMakeAffineTransform(WLZ_TRANSFORM_2D_AFFINE, &errNum); } if(errNum == WLZ_ERR_NONE) { double **m; m = rescaleTr->mat; m[0][0] = (sSz.vtX * eps) / (prjSz.vtX * eps); m[1][1] = (sSz.vtY * eps) / (prjSz.vtY * eps); m[0][2] = sBox.xMin - WLZ_NINT(m[0][0] * prjBox.xMin); m[1][2] = sBox.yMin - WLZ_NINT(m[1][1] * prjBox.yMin); } (void )WlzFree3DViewStruct(vStr2); } } /* Compute plane equation, used to clip intervals if depth was given. */ if((errNum == WLZ_ERR_NONE) && (depth > eps)) { Wlz3DViewGetPlaneEqn(vStr1, pln + 0, pln + 1, pln + 2, pln + 3); } /* Create rectangular projection array buffers, one for each thread, * also if integrating values create a grey value workspace per thread. */ if(errNum == WLZ_ERR_NONE) { int idB; #ifdef _OPENMP #pragma omp parallel { #pragma omp master { nThr = omp_get_num_threads(); } } #endif if((prjAry = (void ***)AlcCalloc(nThr, sizeof(void **))) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } else { if(intMod == WLZ_PROJECT_INT_MODE_NONE) { for(idB = 0; idB < nThr; ++idB) { if(AlcUnchar2Calloc((WlzUByte ***)&(prjAry[idB]), prjSz.vtY, prjSz.vtX) != ALC_ER_NONE) { errNum = WLZ_ERR_MEM_ALLOC; break; } } } else { for(idB = 0; idB < nThr; ++idB) { if(AlcInt2Calloc((int ***)&(prjAry[idB]), prjSz.vtY, prjSz.vtX) != ALC_ER_NONE) { errNum = WLZ_ERR_MEM_ALLOC; break; } } } } if((errNum == WLZ_ERR_NONE) && (intMod == WLZ_PROJECT_INT_MODE_VALUES)) { itvVal = (WlzGreyTableIsTiled(obj->values.core->type) == 0); if(itvVal == 0) { if((gVWSp = AlcCalloc(nThr, sizeof(WlzGreyValueWSpace *))) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } else { for(idB = 0; idB < nThr; ++idB) { gVWSp[idB] = WlzGreyValueMakeWSp(obj, &errNum); if(gVWSp[idB]->gType != WLZ_GREY_UBYTE) { errNum = WLZ_ERR_GREY_TYPE; break; } } } } } } /* Scan through the 3D domain setting value in the projection array. */ if(errNum == WLZ_ERR_NONE) { int pIdx, pCnt; WlzDomain *doms; WlzValues *vals = NULL; doms = obj->domain.p->domains; if(itvVal) { vals = obj->values.vox->values; } pCnt = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; #ifdef _OPENMP #pragma omp parallel for #endif for(pIdx = 0; pIdx < pCnt; ++pIdx) { int thrId = 0; if((errNum == WLZ_ERR_NONE) && (doms[pIdx].core != NULL)) { WlzObject *obj2; WlzGreyWSpace gWSp; WlzIntervalWSpace iWSp; WlzErrorNum errNum2 = WLZ_ERR_NONE; #ifdef _OPENMP thrId = omp_get_thread_num(); #endif obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, doms[pIdx], (vals)? vals[pIdx]: nullVal, NULL, NULL, &errNum2); if(errNum2 == WLZ_ERR_NONE) { if(itvVal) { errNum2 = WlzInitGreyScan(obj2, &iWSp, &gWSp); } else { errNum2 = WlzInitRasterScan(obj2, &iWSp, WLZ_RASTERDIR_ILIC); } } if(errNum2 == WLZ_ERR_NONE) { double plnZ, vMZX, vMZY; WlzIVertex3 p0, p1; p0.vtZ = p1.vtZ = obj->domain.p->plane1 + pIdx; vMZX = (vMat[0][2] * p0.vtZ) + vMat[0][3] - prjBox.xMin; vMZY = (vMat[1][2] * p0.vtZ) + vMat[1][3] - prjBox.yMin; plnZ = (pln[2] * p0.vtZ) + pln[3]; while(((itvVal == 0) && ((errNum2 = WlzNextInterval(&iWSp)) == WLZ_ERR_NONE)) || ((itvVal != 0) && ((errNum2 = WlzNextGreyInterval(&iWSp)) == WLZ_ERR_NONE))) { int skip = 0; WlzDVertex2 q0, q1; p0.vtX = iWSp.lftpos; p1.vtX = iWSp.rgtpos; p0.vtY = p1.vtY = iWSp.linpos; if(depth > eps) { int c; double d0, d1, plnYZ; /* Clip the 3D line segment p0,p1 using the plane equation. */ plnYZ = (pln[1] * p0.vtY) + plnZ; d0 = (pln[0] * p0.vtX) + plnYZ; d1 = (pln[0] * p1.vtX) + plnYZ; c = ((d1 > depth) << 3) | ((d0 > depth) << 2) | ((d1 < -depth) << 1) | (d0 < -depth); if(c) { if((c == 3) || (c == 12)) /* 00-- or ++00 */ { /* Both out of range, so don't render. */ skip = 1; } else { if(fabs(pln[0]) > eps) { double plnX; plnX = -1.0 / pln[0]; if((c & 1) != 0) /* x0x- */ { p0.vtX = plnX * (plnYZ + depth); } else if((c & 4) != 0) /* x+x0 */ { p0.vtX = plnX * (plnYZ - depth); } if((c & 2) != 0) /* 0x-x */ { p1.vtX = plnX * (plnYZ + depth); } else if((c & 8) != 0) /* +x0x */ { p1.vtX = plnX * (plnYZ - depth); } } } } } if(skip == 0) { q0.vtX = (vMat[0][0] * p0.vtX) + (vMat[0][1] * p0.vtY) + vMZX; q0.vtY = (vMat[1][0] * p0.vtX) + (vMat[1][1] * p0.vtY) + vMZY; q1.vtX = (vMat[0][0] * p1.vtX) + (vMat[0][1] * p1.vtY) + vMZX; q1.vtY = (vMat[1][0] * p1.vtX) + (vMat[1][1] * p1.vtY) + vMZY; switch(intMod) { case WLZ_PROJECT_INT_MODE_NONE: { WlzIVertex2 u0, u1; WLZ_VTX_2_NINT(u0, q0); WLZ_VTX_2_NINT(u1, q1); WlzProjectObjLine((WlzUByte **)(prjAry[thrId]), u0, u1); } break; case WLZ_PROJECT_INT_MODE_DOMAIN: { int np, nq; WlzDVertex3 dq; WlzIVertex2 u0, u1; WLZ_VTX_2_NINT(u0, q0); WLZ_VTX_2_NINT(u1, q1); WLZ_VTX_2_SUB(dq, q0, q1); np = denDom * (iWSp.rgtpos - iWSp.lftpos + 1); nq = (int )ceil(WLZ_VTX_2_LENGTH(dq) + eps); WlzProjectObjLineDom((int **)(prjAry[thrId]), np / nq, u0, u1); } break; case WLZ_PROJECT_INT_MODE_VALUES: if(itvVal) { WlzProjectObjLineVal((int **)(prjAry[thrId]), denVal, gWSp.u_grintptr.ubp, NULL, vMat, vMZX, vMZY, p0, p1); } else { WlzProjectObjLineVal((int **)(prjAry[thrId]), denVal, NULL, gVWSp[thrId], vMat, vMZX, vMZY, p0, p1); } break; } } } (void )WlzEndGreyScan(&iWSp, &gWSp); if(errNum2 == WLZ_ERR_EOO) { errNum2 = WLZ_ERR_NONE; } } (void )WlzFreeObj(obj2); if(errNum2 != WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2; } #ifdef _OPENMP } #endif } } } } /* Free grey value workspaces if they were created. */ if(gVWSp) { int idB; for(idB = 0; idB < nThr; ++idB) { WlzGreyValueFreeWSp(gVWSp[idB]); } AlcFree(gVWSp); } if(errNum == WLZ_ERR_NONE) { int idB; size_t idC, bufSz; WlzGreyP buf0, buf1; WlzIVertex2 prjOrg; prjOrg.vtX = prjBox.xMin; prjOrg.vtY = prjBox.yMin; bufSz = prjSz.vtX * prjSz.vtY; for(idB = 1; idB < nThr; ++idB) { if(intMod == WLZ_PROJECT_INT_MODE_NONE) { buf0.ubp = ((WlzUByte ***)(prjAry))[0][0], buf1.ubp = ((WlzUByte ***)(prjAry))[idB][0]; for(idC = 0; idC < bufSz; ++idC) { buf0.ubp[idC] += buf1.ubp[idC]; } } else { buf0.inp = ((int ***)(prjAry))[0][0], buf1.inp = ((int ***)(prjAry))[idB][0]; for(idC = 0; idC < bufSz; ++idC) { buf0.inp[idC] += buf1.inp[idC]; } } } switch(intMod != WLZ_PROJECT_INT_MODE_NONE) { buf0.inp = ((int ***)(prjAry))[0][0]; for(idC = 0; idC < bufSz; ++idC) { buf0.inp[idC] /= 256; } } if(intMod == WLZ_PROJECT_INT_MODE_NONE) { bufObj = WlzAssignObject( WlzFromArray2D((void **)(prjAry[0]), prjSz, prjOrg, WLZ_GREY_UBYTE, WLZ_GREY_UBYTE, 0.0, 1.0, 1, 0, &errNum), NULL); } else { bufObj = WlzAssignObject( WlzFromArray2D((void **)(prjAry[0]), prjSz, prjOrg, WLZ_GREY_INT, WLZ_GREY_INT, 0.0, 1.0, 1, 0, &errNum), NULL); } } /* Free the projection array(s). */ if(prjAry) { int idB; for(idB = 0; idB < nThr; ++idB) { (void )Alc2Free((prjAry[idB])); } AlcFree(prjAry); } /* Make return object using threshold. */ if(errNum == WLZ_ERR_NONE) { WlzPixelV tV; WlzObject *tObj = NULL; tV.type = WLZ_GREY_UBYTE; tV.v.ubv = 1; tObj = WlzAssignObject( WlzThreshold(bufObj, tV, WLZ_THRESH_HIGH, &errNum), NULL); if(tObj) { if(intMod == WLZ_PROJECT_INT_MODE_NONE) { prjObj = WlzMakeMain(tObj->type, tObj->domain, nullVal, NULL, NULL, &errNum); } else { prjObj = WlzMakeMain(tObj->type, tObj->domain, tObj->values, NULL, NULL, &errNum); } } (void )WlzFreeObj(tObj); } (void )WlzFreeObj(bufObj); (void )WlzFree3DViewStruct(vStr1); /* Scale image. */ if(rescaleTr != NULL) { if(errNum == WLZ_ERR_NONE) { WlzObject *tObj = NULL; tObj = WlzAffineTransformObj(prjObj, rescaleTr, WLZ_INTERPOLATION_NEAREST, &errNum); (void )WlzFreeObj(prjObj); prjObj = tObj; } (void )WlzFreeAffineTransform(rescaleTr); } #ifdef WLZ_DEBUG_PROJECT3D_TIME gettimeofday(times + 1, NULL); ALC_TIMERSUB(times + 1, times + 0, times + 2); (void )fprintf(stderr, "WlzGetProjectionFromObject: Elapsed time = %g\n", times[2].tv_sec + (0.000001 * times[2].tv_usec)); #endif /* WLZ_DEBUG_PROJECT3D_TIME */ if(dstErr) { *dstErr = errNum; } return(prjObj); }
/*! * \return The value held in the given Java object. * \ingroup JWlz * \brief Returns a 2D array built from the given 2D java array. * \param jEnv Given JNI environment ptr. * \param cObjName The Java woolz C object class string. * \param jObjName The Java woolz Java object class * string. * \param jniObjName The Java woolz JNI object class string. * \param idrCnt Indirection count (ie 1 for *, 2 for * **, ...). * \param pKey Parameter key. * \param jWArray The Java Woolz array. * \param wArraySz The number of elements in the Java * Woolz array. * \param isCpy Destination pointer for JNI copy flag. */ jlong WlzJavaArray2DGet(JNIEnv *jEnv, char *cObjName, char *jObjName, char *jniObjName, int idrCnt, int pKey, jarray jWArray, WlzIVertex2 wArraySz, jboolean *isCpy) { int idY, ok = 0; void *bufJ; jobject aryJ1D; void **aryW2D = NULL; jlong rtnVal = 0; if(jWArray && (wArraySz.vtX > 0) && (wArraySz.vtY > 0)) { switch(pKey) { case WLZ_JPM_KEY_BYTE_ARY2: ok = AlcChar2Malloc((char ***)&aryW2D, wArraySz.vtY, wArraySz.vtX) == ALC_ER_NONE; if(ok) { idY = 0; while(ok && (idY < wArraySz.vtY)) { ok = ((aryJ1D = (*jEnv)->GetObjectArrayElement(jEnv, (jobjectArray )jWArray, idY)) != NULL) && ((bufJ = (void *)(*jEnv)->GetByteArrayElements(jEnv, (jbyteArray )aryJ1D, isCpy)) == NULL); if(ok) { (void )memcpy(*((WlzUByte **)aryW2D + idY), bufJ, wArraySz.vtX * sizeof(jbyte)); if(*isCpy) { (*jEnv)->ReleaseByteArrayElements(jEnv, (jbyteArray )aryJ1D, (jbyte *)bufJ, 0); *isCpy = JNI_FALSE; } } ++idY; } } break; case WLZ_JPM_KEY_SHORT_ARY2: ok = AlcShort2Malloc((short ***)&aryW2D, wArraySz.vtY, wArraySz.vtX) == ALC_ER_NONE; if(ok) { idY = 0; while(ok && (idY < wArraySz.vtY)) { ok = ((aryJ1D = (*jEnv)->GetObjectArrayElement(jEnv, (jobjectArray )jWArray, idY)) != NULL) && ((bufJ = (void *)(*jEnv)->GetShortArrayElements(jEnv, (jshortArray )aryJ1D, isCpy)) != NULL); if(ok) { (void )memcpy(*((WlzUByte **)aryW2D + idY), bufJ, wArraySz.vtX * sizeof(short)); if(*isCpy) { (*jEnv)->ReleaseShortArrayElements(jEnv, (jshortArray )aryJ1D, (jshort *)bufJ, 0); *isCpy = JNI_FALSE; } } ++idY; } } break; case WLZ_JPM_KEY_INT_ARY2: ok = AlcInt2Malloc((int ***)&aryW2D, wArraySz.vtY, wArraySz.vtX) == ALC_ER_NONE; if(ok) { idY = 0; while(ok && (idY < wArraySz.vtY)) { ok = ((aryJ1D = (*jEnv)->GetObjectArrayElement(jEnv, (jobjectArray )jWArray, idY)) != NULL) && ((bufJ = (void *)(*jEnv)->GetIntArrayElements(jEnv, (jintArray )aryJ1D, isCpy)) != NULL); if(ok) { (void )memcpy(*((WlzUByte **)aryW2D + idY), bufJ, wArraySz.vtX * sizeof(int)); if(*isCpy) { (*jEnv)->ReleaseIntArrayElements(jEnv, (jintArray )aryJ1D, (jint *)bufJ, 0); *isCpy = JNI_FALSE; } } ++idY; } } break; case WLZ_JPM_KEY_FLOAT_ARY2: ok = AlcFloat2Malloc((float ***)&aryW2D, wArraySz.vtY, wArraySz.vtX) == ALC_ER_NONE; if(ok) { idY = 0; while(ok && (idY < wArraySz.vtY)) { ok = ((aryJ1D = (*jEnv)->GetObjectArrayElement(jEnv, (jobjectArray )jWArray, idY)) != NULL) && ((bufJ = (void *)(*jEnv)->GetFloatArrayElements(jEnv, (jfloatArray )aryJ1D, isCpy)) != NULL); if(ok) { (void )memcpy(*((WlzUByte **)aryW2D + idY), bufJ, wArraySz.vtX * sizeof(float)); if(*isCpy) { (*jEnv)->ReleaseFloatArrayElements(jEnv, (jfloatArray )aryJ1D, (jfloat *)bufJ, 0); *isCpy = JNI_FALSE; } } ++idY; } } break; case WLZ_JPM_KEY_DOUBLE_ARY2: ok = AlcDouble2Malloc((double ***)&aryW2D, wArraySz.vtY, wArraySz.vtX) == ALC_ER_NONE; if(ok) { idY = 0; while(ok && (idY < wArraySz.vtY)) { ok = ((aryJ1D = (*jEnv)->GetObjectArrayElement(jEnv, (jobjectArray )jWArray, idY)) != NULL) && ((bufJ = (void *)(*jEnv)->GetDoubleArrayElements(jEnv, (jdoubleArray )aryJ1D, isCpy)) != NULL); if(ok) { (void )memcpy(*((WlzUByte **)aryW2D + idY), bufJ, wArraySz.vtX * sizeof(double)); if(*isCpy) { (*jEnv)->ReleaseDoubleArrayElements(jEnv, (jdoubleArray )aryJ1D, (jdouble *)bufJ, 0); *isCpy = JNI_FALSE; } } ++idY; } } break; default: break; } if(ok) { rtnVal = (jlong )aryW2D; *isCpy = JNI_TRUE; } else if(aryW2D) { Alc2Free(aryW2D); } } return(rtnVal); }
/*! * \return New Woolz domain object with gradient grey values or NULL on * error. * \ingroup WlzValuesFilters * \brief Computes the magnitude of the gray values in the * 3 given Woolz 2D domain objects. * \param srcObj0 First object. * \param srcObj1 Second object. * \param srcObj2 Third object. * \param dstErr Destination error pointer, may be null. */ static WlzObject *WlzGreyMagnitude2D3(WlzObject *srcObj0, WlzObject *srcObj1, WlzObject *srcObj2, WlzErrorNum *dstErr) { int idN, itvLen, bufSz; double **iBufA = NULL; WlzObject *tObj0, *istObj = NULL, *dstObj = NULL; WlzObject *iObjA[3], *tObjA[3]; WlzGreyP tGP0; WlzGreyType dstGType = WLZ_GREY_ERROR; WlzGreyType gTypeA[3]; WlzPixelV dstBgd; WlzPixelV bgdA[3]; WlzValues dstVal; WlzIntervalWSpace dstIWSp; WlzGreyWSpace dstGWSp; WlzIntervalWSpace iIWSpA[3]; WlzGreyWSpace iGWSpA[3]; WlzErrorNum errNum = WLZ_ERR_NONE; *(iObjA + 0) = *(iObjA + 1) = *(iObjA + 2) = NULL; /* Check source objects. */ if((srcObj0 == NULL) || (srcObj1 == NULL) ||(srcObj2 == NULL)) { errNum = WLZ_ERR_OBJECT_NULL;; } else if((srcObj0->type != WLZ_2D_DOMAINOBJ) || (srcObj1->type != WLZ_2D_DOMAINOBJ) || (srcObj2->type != WLZ_2D_DOMAINOBJ)) { errNum = WLZ_ERR_OBJECT_TYPE; } else if((srcObj0->domain.core == NULL) || (srcObj1->domain.core == NULL) || (srcObj2->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else if((srcObj0->values.core == NULL) || (srcObj1->values.core == NULL) || (srcObj2->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } /* Compute the intersection of the source objects. */ if(errNum == WLZ_ERR_NONE) { *(tObjA + 0) = srcObj0; *(tObjA + 1) = srcObj1; *(tObjA + 2) = srcObj2; istObj = WlzIntersectN(3, tObjA, 0, &errNum); } if(errNum == WLZ_ERR_NONE) { *(iObjA + 0) = WlzMakeMain(WLZ_2D_DOMAINOBJ, istObj->domain, srcObj0->values, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { *(iObjA + 1) = WlzMakeMain(WLZ_2D_DOMAINOBJ, istObj->domain, srcObj1->values, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { *(iObjA + 2) = WlzMakeMain(WLZ_2D_DOMAINOBJ, istObj->domain, srcObj2->values, NULL, NULL, &errNum); } /* Get background value and grey types */ idN = 0; while((errNum == WLZ_ERR_NONE) && (idN < 3)) { tObj0 = *(iObjA + idN); *(gTypeA + idN) = WlzGreyTableTypeToGreyType(tObj0->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { *(bgdA + idN) = WlzGetBackground(tObj0, &errNum); } ++idN; } /* Promote grey types. */ if(errNum == WLZ_ERR_NONE) { if((*(gTypeA + 0) == WLZ_GREY_DOUBLE) || (*(gTypeA + 1) == WLZ_GREY_DOUBLE) || (*(gTypeA + 2) == WLZ_GREY_DOUBLE)) { dstGType = WLZ_GREY_DOUBLE; } else if((*(gTypeA + 0) == WLZ_GREY_FLOAT) || (*(gTypeA + 1) == WLZ_GREY_FLOAT) || (*(gTypeA + 2) == WLZ_GREY_FLOAT)) { dstGType = WLZ_GREY_FLOAT; } else if((*(gTypeA + 0) == WLZ_GREY_INT) || (*(gTypeA + 1) == WLZ_GREY_INT) || (*(gTypeA + 2) == WLZ_GREY_INT)) { dstGType = WLZ_GREY_INT; } else if((*(gTypeA + 0) == WLZ_GREY_SHORT) || (*(gTypeA + 1) == WLZ_GREY_SHORT) || (*(gTypeA + 2) == WLZ_GREY_SHORT)) { dstGType = WLZ_GREY_SHORT; } else if((*(gTypeA + 0) == WLZ_GREY_UBYTE) || (*(gTypeA + 1) == WLZ_GREY_UBYTE) || (*(gTypeA + 2) == WLZ_GREY_UBYTE)) { dstGType = WLZ_GREY_SHORT; } else { /* RGBA to be done RAB */ errNum = WLZ_ERR_GREY_TYPE; } } /* Make destination object with intersection domain and new values. */ if(errNum == WLZ_ERR_NONE) { (void )WlzValueConvertPixel(&dstBgd, *(bgdA + 0), dstGType); dstVal.v = WlzNewValueTb(*(iObjA + 0), WlzGreyValueTableType(0, WLZ_GREY_TAB_RAGR, dstGType, NULL), dstBgd, &errNum); if(errNum == WLZ_ERR_NONE) { dstObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, istObj->domain, dstVal, NULL, NULL, &errNum); } } if(istObj) { WlzFreeObj(istObj); } /* Make buffers. */ if(errNum == WLZ_ERR_NONE) { bufSz = dstObj->domain.i->lastkl - dstObj->domain.i->kol1 + 1; if(AlcDouble2Malloc(&iBufA, 3, bufSz) != ALC_ER_NONE) { errNum = WLZ_ERR_MEM_ALLOC; } } /* Scan through the objects computing the magnitude. */ if(errNum == WLZ_ERR_NONE) { idN = 0; while((errNum == WLZ_ERR_NONE) && (idN < 3)) { errNum = WlzInitGreyScan(*(iObjA + idN), iIWSpA + idN, iGWSpA + idN); ++idN; } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(dstObj, &dstIWSp, &dstGWSp); } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(iIWSpA + 0)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(iIWSpA + 1)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(iIWSpA + 2)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&dstIWSp)) == WLZ_ERR_NONE)) { itvLen = dstIWSp.rgtpos - dstIWSp.lftpos + 1; /* Copy intervals to double buffers. */ idN = 0; while(idN < 3) { tGP0.dbp = *(iBufA + idN); WlzValueCopyGreyToGrey(tGP0, 0, WLZ_GREY_DOUBLE, (iGWSpA + idN)->u_grintptr, 0, (iGWSpA + idN)->pixeltype, itvLen); ++idN; } /* Compute magnitude. */ WlzBufMagD3(*(iBufA + 0), *(iBufA + 1), *(iBufA + 2), itvLen); /* Clamp into destination interval. */ tGP0.dbp = *(iBufA + 0); WlzValueClampGreyIntoGrey(dstGWSp.u_grintptr, 0, dstGWSp.pixeltype, tGP0, 0, WLZ_GREY_DOUBLE, itvLen); } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } /* Free intersection objects. */ idN = 0; while(idN < 3) { if(iObjA[idN]) { WlzFreeObj(iObjA[idN]); } ++idN; } /* Free buffers. */ if(iBufA) { Alc2Free((void **)iBufA); } /* Tidy up on error. */ if(dstObj && (errNum != WLZ_ERR_NONE)) { WlzFreeObj(dstObj); dstObj = NULL; } /* Pass back error status. */ if(dstErr) { *dstErr = errNum; } return(dstObj); }