/*! * \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 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); }