/*! * \return Returns a preprocessed object for registration. * \ingroup WlzRegistration * \brief * \param obj Given object. * \param inv Flag, non zero if object values are * to be inverted. * \param dstErr Destination error pointer, * may be NULL. */ static WlzObject *WlzRegCCorNormaliseObj2D(WlzObject *obj, int inv, WlzErrorNum *dstErr) { WlzGreyType gType; WlzPixelV min, max, mean, minN, maxN, zero; WlzObject *obj0 = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; /* Normalise the object inverting the grey values if required -> obj0. */ minN.v.ubv = 0; maxN.v.ubv = 255; zero.v.ubv = 0; min.type = WLZ_GREY_DOUBLE; max.type = WLZ_GREY_DOUBLE; mean.type = WLZ_GREY_UBYTE; minN.type = WLZ_GREY_UBYTE; maxN.type = WLZ_GREY_UBYTE; zero.type = WLZ_GREY_UBYTE; mean.v.ubv = 128; if(inv) { minN.v.ubv = 255; maxN.v.ubv = 0; } (void )WlzGreyStats(obj, &gType, &(min.v.dbv), &(max.v.dbv), NULL, NULL, NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { WlzValueConvertPixel(&min, min, gType); WlzValueConvertPixel(&max, max, gType); WlzValueConvertPixel(&minN, minN, gType); WlzValueConvertPixel(&maxN, maxN, gType); obj0 = WlzCopyObject(obj, &errNum); } if(errNum == WLZ_ERR_NONE) { errNum = WlzSetBackground(obj0, zero); errNum = WlzGreySetRange(obj0, min, max, minN, maxN, 0); } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(obj0); obj0 = NULL; } if(dstErr) { *dstErr = errNum; } return(obj0); }
/*! * \return Resulting pixel value. * \ingroup WlzArithmetic * \brief Promotes the grey type of the given pixel value and then * applies the given scalar function to it's value. * \param sPV Single pixel value. * \param fn Scalar function type. * \param dstErr Destination error pointer, may be NULL. */ static WlzPixelV WlzScalarFnPixel(WlzPixelV sPV, WlzFnType fn, WlzErrorNum *dstErr) { WlzGreyP dGP; WlzPixelV dPV; WlzErrorNum errNum = WLZ_ERR_NONE; dPV.type = WlzScalarFnPromoteGType(fn, sPV.type, &errNum); if(errNum == WLZ_ERR_NONE) { errNum = WlzValueConvertPixel(&dPV, sPV, dPV.type); } if(errNum == WLZ_ERR_NONE) { switch(dPV.type) { case WLZ_GREY_LONG: dGP.lnp = &(dPV.v.lnv); break; case WLZ_GREY_INT: dGP.inp = &(dPV.v.inv); break; case WLZ_GREY_SHORT: dGP.shp = &(dPV.v.shv); break; case WLZ_GREY_UBYTE: dGP.ubp = &(dPV.v.ubv); break; case WLZ_GREY_FLOAT: dGP.flp = &(dPV.v.flv); break; case WLZ_GREY_DOUBLE: dGP.dbp = &(dPV.v.dbv); break; case WLZ_GREY_RGBA: dGP.rgbp = &(dPV.v.rgbv); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { WlzScalarFnItv(dGP, dPV.type, 1, fn); } if(dstErr) { *dstErr = errNum; } return(dPV); }
int main(int argc, char **argv) { WlzObject *obj; FILE *inFile; char optList[] = "l:L:u:U:dhv"; int dither = 0, option; WlzPixelV max, min, Max, Min; WlzPixelV gmin, gmax; int getminFlg=1, getmaxFlg=1, verboseFlg=0; WlzErrorNum errNum = WLZ_ERR_NONE; const char *errMsg; int objCount=0; /* read the argument list and check for an input file */ opterr = 0; Max.type = Min.type = max.type = min.type = WLZ_GREY_DOUBLE; Max.v.dbv = 255.0; Min.v.dbv = 0.0; while( (option = getopt(argc, argv, optList)) != EOF ){ switch( option ){ case 'd': dither = 1; break; case 'l': min.v.dbv = atof(optarg); getminFlg = 0; break; case 'L': Min.v.dbv = atof(optarg); break; case 'u': max.v.dbv = atof(optarg); getmaxFlg = 0; break; case 'U': Max.v.dbv = atof(optarg); break; case 'v': verboseFlg = 1; break; case 'h': default: usage(argv[0]); return 1; } } inFile = stdin; if( optind < argc ){ if( (inFile = fopen(*(argv+optind), "r")) == NULL ){ fprintf(stderr, "%s: can't open file %s\n", argv[0], *(argv+optind)); usage(argv[0]); return 1; } } /* read objects and threshold if possible */ while(((obj = WlzAssignObject(WlzReadObj(inFile, NULL), NULL)) != NULL) && (errNum == WLZ_ERR_NONE)) { objCount++; switch( obj->type ) { case WLZ_2D_DOMAINOBJ: case WLZ_3D_DOMAINOBJ: /* get the existing min and max grey values */ if( (errNum = WlzGreyRange(obj, &gmin, &gmax)) == WLZ_ERR_NONE ){ if( getminFlg ){ WlzValueConvertPixel(&min, gmin, WLZ_GREY_DOUBLE); } if( getmaxFlg ){ WlzValueConvertPixel(&max, gmax, WLZ_GREY_DOUBLE); } if( verboseFlg ){ fprintf(stderr, "%s:\nconverting object %d with parameters:\n" "\tSource (l, u) = (%f, %f)\n" "\tDestination (L, U) = (%f, %f)\n", argv[0], objCount, min.v.dbv, max.v.dbv, Min.v.dbv, Max.v.dbv); } errNum = WlzGreySetRange(obj, min, max, Min, Max, dither); if( errNum == WLZ_ERR_NONE ){ errNum = WlzWriteObj(stdout, obj); } } if( errNum != WLZ_ERR_NONE ){ (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write object (%s).\n", argv[0], errMsg); return(errNum); } break; default: if((errNum = WlzWriteObj(stdout, obj)) != WLZ_ERR_NONE) { (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write object (%s).\n", argv[0], errMsg); return(1); } break; } WlzFreeObj(obj); } return 0; }
/*! * \return Woolz error code. * \ingroup WlzValuesUtils * \brief Sets the backgound value of an image object. * \param obj Given object in which to set the * background value. * \param bgd Required background value. */ WlzErrorNum WlzSetBackground(WlzObject *obj, WlzPixelV bgd) { WlzPlaneDomain *planedmn; WlzVoxelValues *voxtab; WlzObject *obj1; int i; WlzErrorNum errNum=WLZ_ERR_NONE; /* check the object */ if( obj == NULL ){ return( WLZ_ERR_OBJECT_NULL ); } switch( obj->type ){ case WLZ_2D_DOMAINOBJ: case WLZ_3D_DOMAINOBJ: break; case WLZ_TRANS_OBJ: return( WlzSetBackground(obj->values.obj, bgd) ); case WLZ_EMPTY_OBJ: return( WLZ_ERR_NONE ); default: return( WLZ_ERR_OBJECT_TYPE ); } if( obj->domain.core == NULL ){ return( WLZ_ERR_DOMAIN_NULL ); } if( obj->values.core == NULL ){ return( WLZ_ERR_NONE ); } /* check the background type */ switch( bgd.type ){ case WLZ_GREY_INT: case WLZ_GREY_SHORT: case WLZ_GREY_UBYTE: case WLZ_GREY_FLOAT: case WLZ_GREY_DOUBLE: case WLZ_GREY_RGBA: break; default: return( WLZ_ERR_GREY_TYPE ); } (void )WlzValueConvertPixel( &bgd, bgd, WlzGreyTableTypeToGreyType(obj->values.core->type, &errNum)); switch( obj->type ){ case WLZ_2D_DOMAINOBJ: switch( WlzGreyTableTypeToTableType(obj->values.core->type, &errNum) ){ case WLZ_GREY_TAB_RAGR: obj->values.v->bckgrnd = bgd; break; case WLZ_GREY_TAB_RECT: obj->values.r->bckgrnd = bgd; break; case WLZ_GREY_TAB_INTL: obj->values.i->bckgrnd = bgd; break; default: return( errNum ); } break; case WLZ_3D_DOMAINOBJ: planedmn = obj->domain.p; if( planedmn->type != WLZ_PLANEDOMAIN_DOMAIN ){ return( WLZ_ERR_PLANEDOMAIN_TYPE ); } voxtab = obj->values.vox; if( voxtab->type != WLZ_VOXELVALUETABLE_GREY ){ return( WLZ_ERR_VOXELVALUES_TYPE ); } for(i=0; i <= planedmn->lastpl - planedmn->plane1; i++){ if( planedmn->domains[i].core == NULL || voxtab->values[i].core == NULL){ continue; } obj1 = WlzMakeMain(WLZ_2D_DOMAINOBJ, planedmn->domains[i], voxtab->values[i], NULL, NULL, &errNum); WlzSetBackground( obj1, bgd ); WlzFreeObj( obj1 ); } voxtab->bckgrnd = bgd; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } return( errNum ); }
/*! * \return Woolz error code. * \ingroup WlzBinaryOps * \brief Splits the given montage object into component objects * clipped from the montage object. The montage object * must be composed of component images embedded in a * background, with little variation in the background * values. * \param mObj Montage object, which must be either * a WLZ_2D_DOMAINOBJ or a * WLZ_3D_DOMAINOBJ with values. * \param gapV Value for the uniform background. * Must be either WLZ_GREY_INT or * WLZ_GREY_RGBA. * \param tol Tolerance (fraction) for the * variation in background values. * \param bWidth Additional boundary width added * to detected images before they are * clipped. * \param minArea Minimum area for a valid component * image, must be greater than zero. * \param maxComp Maximum number of components. * \param dstNComp Destination pointer for the number of * components extracted, must not be NULL. * \param dstComp Destination pointer for the extracted * components, must not be NULL. */ WlzErrorNum WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV, double tol, int bWidth, int minArea, int maxComp, int *dstNComp, WlzObject ***dstComp) { int id0, id1, area, nLComp = 0; WlzObject *gObj = NULL, *tObj = NULL; WlzObject **lComp; WlzGreyType objG; WlzBox box; WlzPixelV gapLV, gapHV; WlzConnectType lCon; int tI[8]; WlzErrorNum errNum = WLZ_ERR_NONE; tol = WLZ_CLAMP(tol, 0.0, 1.0); if(mObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(minArea < 1) { errNum = WLZ_ERR_PARAM_DATA; } else { switch(mObj->type) { case WLZ_2D_DOMAINOBJ: lCon = WLZ_4_CONNECTED; break; case WLZ_3D_DOMAINOBJ: lCon = WLZ_6_CONNECTED; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { objG = WlzGreyTypeFromObj(mObj, &errNum); } if(errNum == WLZ_ERR_NONE) { switch(gapV.type) { case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_RGBA: break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { if(objG == WLZ_GREY_RGBA) { if(gapV.type != WLZ_GREY_RGBA) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA); } } else { if(gapV.type != WLZ_GREY_INT) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT); } } gapLV.type = gapHV.type = gapV.type; if(gapV.type == WLZ_GREY_INT) { tI[0] = gapV.v.inv * tol; gapLV.v.inv = gapV.v.inv - tI[0]; gapHV.v.inv = gapV.v.inv + tI[0]; tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum); if((errNum == WLZ_ERR_NONE) && (tObj != NULL)) { gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum); } (void )WlzFreeObj(tObj); tObj = NULL; } else /* gapV.type == WLZ_GREY_RGBA */ { tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[2] = tI[0] - tI[1]; tI[5] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[3] = tI[0] - tI[1]; tI[6] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[4] = tI[0] - tI[1]; tI[7] = tI[0] + tI[1]; tI[2] = WLZ_CLAMP(tI[2], 0, 255); tI[3] = WLZ_CLAMP(tI[3], 0, 255); tI[4] = WLZ_CLAMP(tI[4], 0, 255); WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255); tI[5] = WLZ_CLAMP(tI[5], 0, 255); tI[6] = WLZ_CLAMP(tI[6], 0, 255); tI[7] = WLZ_CLAMP(tI[7], 0, 255); WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255); gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum); } } if(errNum == WLZ_ERR_NONE) { tObj = WlzDiffDomain(mObj, gObj, &errNum); } (void )WlzFreeObj(gObj); if(errNum == WLZ_ERR_NONE) { errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon); } (void )WlzFreeObj(tObj); if(errNum == WLZ_ERR_NONE) { /* Get rid of small objects using minArea as the threshold. */ id0 = 0; id1 = 0; while(id0 < nLComp) { switch((*(lComp + id0))->type) { case WLZ_2D_DOMAINOBJ: area = WlzArea(*(lComp + id0), NULL); break; case WLZ_3D_DOMAINOBJ: area = WlzVolume(*(lComp + id0), NULL); break; default: area = 0; break; } if(area >= minArea) { *(lComp + id1) = *(lComp + id0); ++id1; } else { (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = NULL; } ++id0; } nLComp = id1; } if(errNum == WLZ_ERR_NONE) { /* Clip rectangular objects from the montage object. */ id0 = 0; while((errNum == WLZ_ERR_NONE) && (id0 < nLComp)) { if(tObj->type == WLZ_2D_DOMAINOBJ) { box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum); box.i2.xMin -= bWidth; box.i2.yMin -= bWidth; box.i2.xMax += bWidth; box.i2.yMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum); } else /* tObj->type == WLZ_3D_DOMAINOBJ */ { box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum); box.i3.xMin -= bWidth; box.i3.yMin -= bWidth; box.i3.zMin -= bWidth; box.i3.xMax += bWidth; box.i3.yMax += bWidth; box.i3.zMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum); } ++id0; } } *dstNComp = nLComp; *dstComp = lComp; return(errNum); }
/*! * \ingroup WlzValuesUtils * \brief Set the value maskVal within the domain given by the * mask object. The mask object can be a 2D, 3D, polygon * or boundary object. A 3D mask with a 2D object is an * error. A 2D mask with a 3D object will be applied to * each plane in turn. * * \return New object with the same domain as the input object but with values in the intersection with the mask domain set to the mask value. NULL on error. * \param obj Input object * \param mask Mask object. * \param maskVal mask value. * \param dstErr Error return. * \par Source: * WlzGreyMask.c */ WlzObject *WlzGreyMask( WlzObject *obj, WlzObject *mask, WlzPixelV maskVal, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObject *tmpMask, *obj1; WlzValues values; WlzPixelV tmpMaskval; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; int i; WlzErrorNum errNum=WLZ_ERR_NONE; /* check obj */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } break; case WLZ_3D_DOMAINOBJ: return WlzGreyMask3d(obj, mask, maskVal, dstErr); case WLZ_TRANS_OBJ: if((values.obj = WlzGreyMask(obj->values.obj, mask, maskVal, &errNum)) != NULL){ return WlzMakeMain(WLZ_TRANS_OBJ, obj->domain, values, NULL, NULL, dstErr); } break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* check the mask */ if( errNum == WLZ_ERR_NONE ){ if( mask == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { values.core = NULL; switch( mask->type ){ case WLZ_2D_DOMAINOBJ: tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ, mask->domain, values, NULL, NULL, &errNum); break; case WLZ_TRANS_OBJ: tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ, mask->values.obj->domain, values, NULL, NULL, &errNum); break; case WLZ_EMPTY_OBJ: return WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain, obj->values, NULL, NULL, dstErr); case WLZ_2D_POLYGON: tmpMask = WlzPolyToObj(mask->domain.poly, WLZ_SIMPLE_FILL, &errNum); break; case WLZ_BOUNDLIST: tmpMask = WlzBoundToObj(mask->domain.b, WLZ_SIMPLE_FILL, &errNum); break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if( errNum == WLZ_ERR_NONE ){ tmpMask = WlzAssignObject(tmpMask, NULL); } } } /* copy input obj and setvalues in the intersection */ if(errNum == WLZ_ERR_NONE){ if((rtnObj = WlzNewGrey(obj, &errNum)) != NULL){ if((obj1 = WlzIntersect2(obj, tmpMask, &errNum)) != NULL){ obj1->values = WlzAssignValues(rtnObj->values, NULL); errNum = WlzInitGreyScan(obj1, &iwsp, &gwsp); WlzValueConvertPixel(&tmpMaskval, maskVal, gwsp.pixeltype); while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){ gptr = gwsp.u_grintptr; switch( gwsp.pixeltype ){ case WLZ_GREY_INT: for(i=0; i<iwsp.colrmn; i++, gptr.inp++){ *gptr.inp = tmpMaskval.v.inv; } break; case WLZ_GREY_SHORT: for(i=0; i<iwsp.colrmn; i++, gptr.shp++){ *gptr.shp = tmpMaskval.v.shv; } break; case WLZ_GREY_UBYTE: for(i=0; i<iwsp.colrmn; i++, gptr.ubp++){ *gptr.ubp = tmpMaskval.v.ubv; } break; case WLZ_GREY_FLOAT: for(i=0; i<iwsp.colrmn; i++, gptr.flp++){ *gptr.flp = tmpMaskval.v.flv; } break; case WLZ_GREY_DOUBLE: for(i=0; i<iwsp.colrmn; i++, gptr.dbp++){ *gptr.dbp = tmpMaskval.v.dbv; } break; case WLZ_GREY_RGBA: for(i=0; i<iwsp.colrmn; i++, gptr.rgbp++){ *gptr.rgbp = tmpMaskval.v.rgbv; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } WlzFreeObj(obj1); } else { WlzFreeObj(rtnObj); rtnObj = NULL; } } WlzFreeObj(tmpMask); } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \return New woolz object or NULL on error. * \ingroup WlzArithmetic * \brief Scales the values of the given 2D Woolz object so that * \f$v_{new} = m v_{given} + a.\f$ The input object is known * to be a valid 2D domain object with grey values. * \param iObj Given object. * \param m Value to multiply object values by. * \param a Value to add to product. * \param rGType Required grey type for returned object. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzScalarMulAdd2D(WlzObject *iObj, WlzPixelV m, WlzPixelV a, WlzGreyType rGType, WlzErrorNum *dstErr) { WlzValues rValues; WlzObjectType rVType; WlzPixelV bgdV; WlzObject *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; rValues.core = NULL; bgdV = WlzGetBackground(iObj, &errNum); if(errNum == WLZ_ERR_NONE) { rVType = WlzGreyTableTypeToTableType(iObj->values.v->type, &errNum); } if(errNum == WLZ_ERR_NONE) { rVType = WlzGreyTableType(rVType, rGType, &errNum); } if(errNum == WLZ_ERR_NONE) { rValues.v = WlzNewValueTb(iObj, rVType, bgdV, &errNum); } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, iObj->domain, rValues, iObj->plist, iObj->assoc, &errNum); } if(errNum == WLZ_ERR_NONE) { switch(rGType) { case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_UBYTE: /* FALLTHROUGH */ case WLZ_GREY_RGBA: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: WlzValueConvertPixel(&m, m, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&a, a, WLZ_GREY_DOUBLE); errNum = WlzScalarMulAddSet2D(rObj, iObj, m.v.dbv, a.v.dbv); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum != WLZ_ERR_NONE) { if(rObj == NULL) { (void )WlzFreeValueTb(rValues.v); } else { (void )WlzFreeObj(rObj); rObj = NULL; } } if(dstErr != NULL) { *dstErr = errNum; } return(rObj); }
/*! * \return Woolz error number. * \ingroup WlzExtFF * \brief Writes the given 3D Woolz object to the given file(s) * using the given (2D) file format. * \param fPathStr File name base. * \param fBodyStr File body. * \param fExtStr File extension. * \param fCtrStr File control string (ctr). * \param fFmt Given file format (must be a 2D * file format). * \param obj Given woolz object. */ static WlzErrorNum WlzEffWriteObjStack3D(const char *fPathStr, const char *fBodyStr, const char *fExtStr, const char *fCtrStr, WlzEffFormat fFmt, WlzObject *obj) { int tI0, tI1, planeIdx, planeOff; WlzObject *obj2D = NULL; WlzIVertex2 imgSz2D, imgOrg2D; WlzDomain dom2D; WlzValues val2D; WlzPixelV bgdV; unsigned char *data = NULL; char *fNameStr = NULL; FILE *fP = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; imgOrg2D.vtX = obj->domain.p->kol1; imgOrg2D.vtY = obj->domain.p->line1; imgSz2D.vtX = obj->domain.p->lastkl - imgOrg2D.vtX + 1; imgSz2D.vtY = obj->domain.p->lastln - imgOrg2D.vtY + 1; tI0 = strlen(fPathStr) + strlen(fBodyStr) + strlen(fExtStr) + 16; tI1 = imgSz2D.vtX * imgSz2D.vtY; if(((fNameStr = AlcMalloc(tI0 * sizeof(char))) == NULL) || ((data = (unsigned char *)AlcMalloc(tI1 * sizeof(unsigned char))) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } if(errNum == WLZ_ERR_NONE) { sprintf(fNameStr, "%s%s.%s", fPathStr, fBodyStr, fCtrStr); if((fP = fopen(fNameStr, "w")) == NULL) { errNum = WLZ_ERR_WRITE_EOF; } else { #ifdef _WIN32 if (fP != NULL){ if(_setmode(_fileno(fP), 0x8000) == -1) { errNum = WLZ_ERR_READ_EOF; } } #endif if(fprintf(fP, "%s%s%s%s%s\n" "%s%s%d %d %d\n" "%s%s%d %d %d\n" "%s%s%g %g %g\n" "%s\n", WLZEFF_STACK_CTR_IDENT, WLZEFF_STACK_CTR_FIELDSEP, WLZEFF_STACK_CTR_IDENTSTR, WLZEFF_STACK_CTR_FIELDSEP, WLZEFF_STACK_CTR_IDENTVERSION, WLZEFF_STACK_CTR_VOLORIGIN, WLZEFF_STACK_CTR_FIELDSEP, obj->domain.p->kol1, obj->domain.p->line1, obj->domain.p->plane1, WLZEFF_STACK_CTR_VOLSIZE, WLZEFF_STACK_CTR_FIELDSEP, obj->domain.p->lastkl - obj->domain.p->kol1 + 1, obj->domain.p->lastln - obj->domain.p->line1 + 1, obj->domain.p->lastpl - obj->domain.p->plane1 + 1, WLZEFF_STACK_CTR_VOXSIZE, WLZEFF_STACK_CTR_FIELDSEP, obj->domain.p->voxel_size[0], obj->domain.p->voxel_size[1], obj->domain.p->voxel_size[2], WLZEFF_STACK_CTR_FILES) < 16) { errNum = WLZ_ERR_WRITE_INCOMPLETE; } else { planeOff = 0; planeIdx = obj->domain.p->plane1; while((planeIdx <= obj->domain.p->lastpl) && (errNum == WLZ_ERR_NONE)) { if(fprintf(fP, "%*d %s%0*d.%s\n", WLZEFF_STACK_NAMEDIGITS, planeIdx, fBodyStr, WLZEFF_STACK_NAMEDIGITS, planeIdx, fExtStr) < WLZEFF_STACK_NAMEDIGITS) { errNum = WLZ_ERR_WRITE_INCOMPLETE; } ++planeIdx; } } fclose(fP); } } if(errNum == WLZ_ERR_NONE) { planeOff = 0; planeIdx = obj->domain.p->plane1; bgdV = WlzGetBackground(obj, &errNum); } if(errNum == WLZ_ERR_NONE) { (void )WlzValueConvertPixel(&(bgdV), bgdV, WLZ_GREY_UBYTE); while((planeIdx <= obj->domain.p->lastpl) && (errNum == WLZ_ERR_NONE)) { dom2D = *(obj->domain.p->domains + planeOff); val2D = *(obj->values.vox->values + planeOff); sprintf(fNameStr, "%s%s%0*d.%s", fPathStr, fBodyStr, WLZEFF_STACK_NAMEDIGITS, planeIdx, fExtStr); if(dom2D.core && val2D.core) { obj2D = WlzAssignObject(WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2D, val2D, NULL, NULL, &errNum), NULL); } else { obj2D = NULL; } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteObjStack2D(fNameStr, fFmt, obj2D, imgSz2D, imgOrg2D, data, bgdV.v.ubv); } if(obj2D) { WlzFreeObj(obj2D); obj2D = NULL; } ++planeOff; ++planeIdx; } } if(fNameStr) { AlcFree(fNameStr); } if(data) { AlcFree(data); } return(errNum); }
void install_paint_reference_object( WlzObject *obj) { Widget toggle; WlzPixelV bckgrnd; WlzPixelV min, max, Min, Max; WlzErrorNum errNum=WLZ_ERR_NONE; if( globals.orig_obj != NULL ){ WlzFreeObj( globals.orig_obj ); } globals.orig_obj = WlzAssignObject(obj, &errNum); obj = NULL; /* check input object for grey-value type convert if necessary */ if( errNum == WLZ_ERR_NONE ){ bckgrnd = WlzGetBackground(globals.orig_obj, &errNum); Min.type = WLZ_GREY_INT; Max.type = WLZ_GREY_INT; Min.v.inv = 0; Max.v.inv = 255; } if( errNum == WLZ_ERR_NONE ){ switch( bckgrnd.type ){ case WLZ_GREY_LONG: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.lnv < 0) || (max.v.lnv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_INT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.inv < 0) || (max.v.inv > 255) ){ obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum); WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } break; case WLZ_GREY_SHORT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.shv < 0) || (max.v.shv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_SHORT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_FLOAT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.flv < 0) || (max.v.flv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_DOUBLE: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.dbv < 0) || (max.v.dbv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; default: case WLZ_GREY_UBYTE: break; } } /* copy for later transform for display purposes, the original is kept for IP purposes note pixconvert loses the background value */ if( errNum == WLZ_ERR_NONE ){ if( globals.obj != NULL ){ WlzFreeObj( globals.obj ); } if( obj ){ globals.obj = WlzAssignObject(WlzConvertPix(obj, WLZ_GREY_UBYTE, &errNum), NULL); WlzFreeObj(globals.orig_obj); globals.orig_obj = WlzAssignObject(obj, NULL); } else { globals.obj = WlzAssignObject(WlzConvertPix(globals.orig_obj, WLZ_GREY_UBYTE, &errNum), NULL); } } if( errNum == WLZ_ERR_NONE ){ min.type = WLZ_GREY_UBYTE; max.type = WLZ_GREY_UBYTE; Min.type = WLZ_GREY_UBYTE; Max.type = WLZ_GREY_UBYTE; min.v.ubv = 0; max.v.ubv = 255; Min.v.ubv = globals.cmapstruct->gmin; Max.v.ubv = globals.cmapstruct->gmax; errNum = WlzGreySetRange(globals.obj, min, max, Min, Max, 0); } /* also convert the background values */ if( errNum == WLZ_ERR_NONE ){ /* min = WlzGetBackground(globals.orig_obj, NULL);*/ WlzValueConvertPixel(&bckgrnd, bckgrnd, WLZ_GREY_INT); max.type = WLZ_GREY_INT; max.v.inv = ((bckgrnd.v.inv * (Max.v.ubv - Min.v.ubv)) / 255) + Min.v.ubv; WlzSetBackground(globals.obj, max); /* fill blank planes here - should be a resource option */ if( (toggle = XtNameToWidget(read_obj_dialog, "*.fill_blanks")) ){ Boolean fill_blanks, min_domain; XtVaGetValues(toggle, XmNset, &fill_blanks, NULL); if( fill_blanks ){ if( (toggle = XtNameToWidget(read_obj_dialog, "*.min_domain")) ){ XtVaGetValues(toggle, XmNset, &min_domain, NULL); if( min_domain ){ WlzFillBlankPlanes(globals.obj, 1); } else { WlzFillBlankPlanes(globals.obj, 0); } } else { WlzFillBlankPlanes(globals.obj, 1); } } } /* setup the display list and properties dialog */ setup_ref_display_list_cb(read_obj_dialog, NULL, NULL); setup_obj_props_cb(read_obj_dialog, NULL, NULL); } /* log the object size */ if( (errNum == WLZ_ERR_NONE) && globals.logfileFp ){ char strBuf[64]; sprintf(strBuf, "(%d, %d, %d, %d, %d, %d)", globals.obj->domain.p->kol1, globals.obj->domain.p->line1, globals.obj->domain.p->plane1, globals.obj->domain.p->lastkl, globals.obj->domain.p->lastln, globals.obj->domain.p->lastpl); MAPaintLogData("BoundingBox", strBuf, 0, NULL); sprintf(strBuf, "%d", (int) WlzVolume(globals.obj, NULL)); MAPaintLogData("Volume", strBuf, 0, NULL); } if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "install_paint_reference_object", errNum); } return; }
/*! * \return New 3D domain object with corresponding WLZ_GREY_RGBA values. * \ingroup WlzValuesUtils * \brief Creates a WLZ_GREY_RGBA valued object from the given compound * array. This is a static function which will always be called * with valid parameters so they aren't checked. * \param cObj Compound array object. * \param cSpc The colour space. * \param dstErr Destination error pointer may be NULL. */ static WlzObject *WlzCompoundToRGBA2D(WlzCompoundArray *cObj, WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr) { int i, j; WlzObject *rtnObj=NULL; WlzPixelV bckgrnd; WlzObject *objs[4]; WlzObjectType vType; WlzUInt b[4]; WlzErrorNum errNum=WLZ_ERR_NONE; /* Make a copy of the object pointers because WlzUnionN() modifies the * array if it contains empty objects. */ for(i = 0; i < 3; ++i) { objs[i] = cObj->o[i]; } rtnObj = WlzUnionN(3, objs, 0, &errNum); if(errNum == WLZ_ERR_NONE) { /* Add an RGBA valuetable, extract background for each channel */ vType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_RGBA, &errNum); for(i=0; (errNum == WLZ_ERR_NONE) && (i < 3); i++) { bckgrnd = WlzGetBackground(cObj->o[i], &errNum); if(errNum == WLZ_ERR_NONE) { errNum = WlzValueConvertPixel(&bckgrnd, bckgrnd, WLZ_GREY_UBYTE); b[i] = bckgrnd.v.ubv; } } } if(errNum == WLZ_ERR_NONE) { WlzValues values; bckgrnd.type = WLZ_GREY_RGBA; WLZ_RGBA_RGBA_SET(bckgrnd.v.rgbv, b[0], b[1], b[2], 255); values.v = WlzNewValueTb(rtnObj, vType, bckgrnd, &errNum); if(values.v != NULL) { rtnObj->values = WlzAssignValues(values, &errNum); } else { (void )WlzFreeObj(rtnObj); rtnObj = NULL; } } /* Transfer values */ if( errNum == WLZ_ERR_NONE) { WlzGreyValueWSpace *gValWSpc[4]; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyV gval; /* do it dumb fashion for now, rgb only */ gValWSpc[0] = gValWSpc[1] = gValWSpc[2] = gValWSpc[3] = NULL; for(i=0; i < 3; i++) { if((cObj->o[i] != NULL) && (cObj->o[i]->type != WLZ_EMPTY_OBJ)) { gValWSpc[i] = WlzGreyValueMakeWSp(cObj->o[i], &errNum); if(errNum != WLZ_ERR_NONE) { break; } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp); } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)) { WlzPixelV pix; for(j = iwsp.lftpos; j <= iwsp.rgtpos; j++) { for(i = 0; i < 3; i++) { if(gValWSpc[i] == NULL) { pix.v.ubv = (i < 2)? 0: 255; } else { WlzGreyValueGet(gValWSpc[i], 0, iwsp.linpos, j); pix.type = gValWSpc[i]->gType; pix.v = gValWSpc[i]->gVal[0]; WlzValueConvertPixel(&pix, pix, WLZ_GREY_UBYTE); } b[i] = pix.v.ubv; } WLZ_RGBA_RGBA_SET(gval.rgbv, b[0], b[1], b[2], b[3]); *gwsp.u_grintptr.rgbp = gval.rgbv; gwsp.u_grintptr.rgbp++; } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } for(i=0; i < 3; i++) { WlzGreyValueFreeWSp(gValWSpc[i]); } } if(dstErr != NULL) { *dstErr = errNum; } return(rtnObj); }
void getViewDomains( ThreeDViewStruct *view_struct) { int i, j, numOverlays; WlzObject *allDomainsObj=NULL, *tmpObj; WlzPixelV thresh; WlzErrorNum errNum=WLZ_ERR_NONE; /* check initialisation */ if( !view_struct->wlzViewStr->initialised ){ if( init_view_struct( view_struct ) ){ errNum = WLZ_ERR_UNSPECIFIED; } } /* check for painted object */ /* clear any current domains */ numOverlays = globals.cmapstruct->num_overlays + globals.cmapstruct->num_solid_overlays; for(i=0; i <= numOverlays; i++){ if( view_struct->curr_domain[i] ){ errNum = WlzFreeObj(view_struct->curr_domain[i]); view_struct->curr_domain[i] = NULL; } if( errNum != WLZ_ERR_NONE ){ break; } } /* get the union of all domains */ if( errNum == WLZ_ERR_NONE ){ thresh.type = WLZ_GREY_INT; thresh.v.inv = globals.cmapstruct->ovly_cols[DOMAIN_1]; tmpObj = WlzThreshold(view_struct->painted_object, thresh, WLZ_THRESH_HIGH, &errNum); if( (errNum == WLZ_ERR_NONE) && tmpObj ){ if( WlzArea(tmpObj, &errNum) > 0 ){ allDomainsObj = WlzAssignObject(tmpObj, &errNum); } else { errNum = WlzFreeObj(tmpObj); } } } /* segment the painted section image to establish each domain object */ if( (errNum == WLZ_ERR_NONE) && allDomainsObj ){ WlzPixelV min, max; int max_i=numOverlays; /* get maximum number of domains */ WlzGreyRange(allDomainsObj, &min, &max); WlzValueConvertPixel(&max, max, WLZ_GREY_INT); while( (max_i > 0) && (globals.cmapstruct->ovly_cols[max_i] > max.v.inv) ){ max_i--; } for(i=1; i <= max_i; i++){ tmpObj = get_domain_from_object(view_struct->painted_object, i); if( tmpObj ){ view_struct->curr_domain[i] = WlzAssignObject(tmpObj, NULL); } } } /* propogate from previous section asking for confirmation if a domain will be changed by propogation. This will either be if the current domain exists or if the propogating domain overlaps the union of all existing domains */ if( (errNum == WLZ_ERR_NONE) && (globals.propogate||globals.propogate_sel) ){ for(i=1; (i <= numOverlays) && (errNum == WLZ_ERR_NONE); i++){ /* test for propogate currently selected domain only */ if((!globals.propogate) && (i != globals.current_domain)){ continue; } if((view_struct->prev_domain[i]) && (view_struct->prev_domain[i]->type != WLZ_EMPTY_OBJ)){ if( allDomainsObj ){ /* first check if there is a curr_domain */ int needConfirm = 0; if((view_struct->curr_domain[i]) && (view_struct->curr_domain[i]->type != WLZ_EMPTY_OBJ)){ needConfirm = 1; } else { tmpObj = WlzIntersect2(view_struct->prev_domain[i], allDomainsObj, &errNum); if( tmpObj && (WlzArea(tmpObj, &errNum) > 0) ){ needConfirm = 1; WlzFreeObj(tmpObj); } } if( (errNum == WLZ_ERR_NONE) && needConfirm ){ if( HGU_XmUserConfirm(view_struct->dialog, "Warning: propogation may modify\n" " one or more existing domains.\n" " Propogate anyway?", "Yes", "No", 0) ){ if( view_struct->curr_domain[i] ){ tmpObj = WlzUnion2(view_struct->curr_domain[i], view_struct->prev_domain[i], &errNum); WlzFreeObj(view_struct->curr_domain[i]); view_struct->curr_domain[i] = WlzAssignObject(tmpObj, NULL); } else { view_struct->curr_domain[i] = WlzAssignObject(view_struct->prev_domain[i], NULL); } globals.domain_changed_since_saved[i] = 1; } } else { view_struct->curr_domain[i] = WlzAssignObject(view_struct->prev_domain[i], NULL); globals.domain_changed_since_saved[i] = 1; } } else { view_struct->curr_domain[i] = WlzAssignObject(view_struct->prev_domain[i], &errNum); globals.domain_changed_since_saved[i] = 1; } } } } /* put all objects onto painted image in reverse dominance order */ for(j=numOverlays; (j > 0) && (errNum == WLZ_ERR_NONE); j--){ i = globals.priority_to_domain_lut[j]; if( view_struct->curr_domain[i] ){ if( i > globals.cmapstruct->num_overlays ) { if( set_grey_values_from_domain(view_struct->curr_domain[i], view_struct->painted_object, globals.cmapstruct->ovly_cols[i], 255) ){ break; } } else { if( set_grey_values_from_domain(view_struct->curr_domain[i], view_struct->painted_object, globals.cmapstruct->ovly_cols[i], globals.cmapstruct->ovly_planes) ){ break; } } } } /* redisplay the view */ if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "getViewDomains", errNum); } else{ redisplay_view_cb(view_struct->canvas, view_struct, NULL); } return; }
WlzErrorNum WlzGreyScalarDivValue( WlzObject *obj, WlzPixelV val) { WlzObject *tmpObj; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzPixelV tmpVal; WlzDomain *domains; WlzValues *values; int i, nplanes; int red = 0, green = 0, blue = 0, alpha = 0; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->values.v == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if( obj->values.vox == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else { /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; (errNum == WLZ_ERR_NONE) && (i < nplanes); i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } if((tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, NULL)) != NULL){ errNum = WlzGreyScalarDivValue(tmpObj, val); WlzFreeObj( tmpObj ); } } } return errNum; case WLZ_TRANS_OBJ: return WlzGreyScalarDivValue(obj->values.obj, val); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); WlzValueConvertPixel(&tmpVal, val, WLZ_GREY_DOUBLE); while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++) *gptr.inp /= tmpVal.v.dbv; break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++) *gptr.shp /= tmpVal.v.dbv; break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++) *gptr.ubp /= tmpVal.v.dbv; break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++) *gptr.flp /= tmpVal.v.dbv; break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++) *gptr.dbp /= tmpVal.v.dbv; break; case WLZ_GREY_RGBA: for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++) red = WLZ_RGBA_RED_GET(*gptr.rgbp) / tmpVal.v.dbv; green = WLZ_RGBA_GREEN_GET(*gptr.rgbp) / tmpVal.v.dbv; blue = WLZ_RGBA_BLUE_GET(*gptr.rgbp) / tmpVal.v.dbv; alpha = WLZ_RGBA_ALPHA_GET(*gptr.rgbp); red = WLZ_CLAMP(red, 0, 255); green = WLZ_CLAMP(red, 0, 255); blue = WLZ_CLAMP(red, 0, 255); WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } 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); }
int main(int argc, char **argv) { int option, ok = 1, sep = 0, usage = 0, verbose = 0; double padVal = 0.0; WlzDVertex3 param[] = {{1.0, 1.0, 1.0}, {0.0, 0.0, 0.0}}; WlzIVertex3 order = {0, 0, 0}; AlgPadType pad = ALG_PAD_NONE; WlzGreyType gType = WLZ_GREY_ERROR; WlzIVertex3 action = {1, 1, 1}; WlzObject *inObj = NULL, *outObj = NULL; struct timeval times[3]; const char *errMsgStr; WlzErrorNum errNum = WLZ_ERR_NONE; char *outFileStr, *inObjFileStr; static char optList[] = "Ghvg:o:m:n:P:p:t:S:", defFile[] = "-"; opterr = 0; outFileStr = defFile; inObjFileStr = defFile; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'o': outFileStr = optarg; break; case 'h': usage = 1; break; case 'v': verbose = 1; break; case 'g': switch(*optarg) { case 'i': gType = WLZ_GREY_INT; break; case 's': gType = WLZ_GREY_SHORT; break; case 'u': gType = WLZ_GREY_UBYTE; break; case 'f': gType = WLZ_GREY_FLOAT; break; case 'd': gType = WLZ_GREY_DOUBLE; break; default: usage = 1; break; } break; case 'm': if((optarg == NULL) || (sscanf(optarg, "%lg,%lg,%lg", &(param[0].vtX), &(param[0].vtY), &(param[0].vtZ)) < 1)) { usage = 1; } break; case 'n': if((optarg == NULL) || (sscanf(optarg, "%d,%d,%d", &(order.vtX), &(order.vtY), &(order.vtZ)) < 1)) { usage = 1; } break; case 'P': switch(*optarg) { case 'b': pad = ALG_PAD_NONE; break; case 'e': pad = ALG_PAD_END; break; case 'v': pad = ALG_PAD_VALUE; break; case 'z': pad = ALG_PAD_ZERO; break; default: usage = 1; break; } break; case 'p': if((optarg == NULL) || (sscanf(optarg, "%lg", &padVal) != 1)) { usage = 1; } break; case 'G': /* Only have Gaussian implemented. */ break; case 't': if(optarg) { char *actStr; action.vtX = 0; action.vtY = 0; action.vtZ = 0; actStr = strtok(optarg, ","); while(actStr && ok) { if(strcmp(actStr, "x") == 0) { action.vtX = 1; } else if(strcmp(actStr, "y") == 0) { action.vtY = 1; } else if(strcmp(actStr, "z") == 0) { action.vtZ = 1; } else { usage = 1; } actStr = strtok(NULL, ","); } } break; case 'S': if(!optarg || (strlen(optarg) > 1)) { usage = 1; } else { switch(*optarg) { case 'c': sep = 1; break; case 'a': sep = 2; break; case 's': sep = 3; break; default: usage = 1; break; } } break; default: usage = 1; break; } } if(!usage) { if(optind < argc) { if((optind + 1) != argc) { usage = 1; } else { inObjFileStr = *(argv + optind); } } } ok = !usage; if(ok) { FILE *fP = NULL; if(verbose) { (void )fprintf(stderr, "%s: Reading object from %s\n", *argv, strcmp(inObjFileStr, "-")? inObjFileStr: "stdin"); } if(((fP = (strcmp(inObjFileStr, "-")? fopen(inObjFileStr, "r"): stdin)) == NULL) || ((inObj= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) || (errNum != WLZ_ERR_NONE)) { ok = 0; (void )fprintf(stderr, "%s: Failed to read object from file %s\n", *argv, inObjFileStr); } if(fP && strcmp(inObjFileStr, "-")) { fclose(fP); } } if(ok && (pad == ALG_PAD_NONE)) { WlzPixelV bgd; bgd = WlzGetBackground(inObj, &errNum); if(errNum == WLZ_ERR_NONE) { WlzValueConvertPixel(&bgd, bgd, WLZ_GREY_DOUBLE); padVal = bgd.v.dbv; pad = ALG_PAD_VALUE; } else { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to get object background value (%s).\n", *argv, errMsgStr); } } if(ok) { if(verbose) { (void )fprintf(stderr, "%s: Filtering object with:\n" " param[0] = (%g, %g, %g)\n" " param[1] = (%g, %g, %g)\n" " order = (%d, %d, %d)\n" " action = (%d, %d, %d)\n" " gType = %d\n" " pad = %d\n" " padVal = %lg\n" " sep = %d\n", *argv, param[0].vtX, param[0].vtY, param[0].vtZ, param[1].vtX, param[1].vtY, param[1].vtZ, order.vtX, order.vtY, order.vtZ, action.vtX, action.vtY, action.vtZ, gType, pad, padVal, sep); gettimeofday(times + 0, NULL); } outObj = WlzAssignObject( WlzGaussFilter(inObj, param[0], order, action, gType, pad, padVal, sep, &errNum), NULL); if(verbose) { gettimeofday(times + 1, NULL); ALC_TIMERSUB(times + 1, times + 0, times + 2); (void )fprintf(stderr, "%s: Elapsed time for WlzGaussFilter() %gus\n", argv[0], (1.0e06 * times[2].tv_sec) + times[2].tv_usec); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to filter object (%s).\n", *argv, errMsgStr); } } if(ok) { FILE *fP = NULL; if(verbose) { (void )fprintf(stderr, "%s: Writing object to %s\n", *argv, strcmp(outFileStr, "-")? outFileStr: "stdout"); } errNum = WLZ_ERR_FILE_OPEN; if(((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL) || ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to write output object (%s).\n", *argv, errMsgStr); } if(fP && strcmp(outFileStr, "-")) { fclose(fP); } } (void )WlzFreeObj(inObj); (void )WlzFreeObj(outObj); if(usage) { (void )fprintf(stderr, "Usage: %s%s%s%sExample: %s%s", *argv, " [-h] [-o<output object>] [-m#,#,#] [-n#,#,#]\n" "\t[-g <t>] [-t <flags>] [-P <p>] [-p#] [-G]\n" "\t[-S a|c|s] [-v] [<input object>]\n" "Version: ", WlzVersion(), "\n" "Options:\n" " -h Prints this usage information\n" " -o Output object file name.\n" " -m Filter parameters; for a Gaussian these are the sigma values\n" " for each orthogonal direction (x, y and z). Default values are\n" " 1,1,1.\n" " -n Order parameters; for a Gaussian these are the order of the\n" " Gaussian's derivatives (eg 0 for no derivative, 1 for 1st\n" " derivative), default 0,0,0.\n" " -g Required grey type, default is the same as the input object's,\n" " with 'i', 's', 'u', 'f' and 'd' used to request int, short,\n" " unsigned byte, float or double grey values.\n" " -P Type of padding to use, default is to use the background value,\n" " with 'b', 'e', 'v' and 'z' used to select background, end, given\n" " value and zero padding.\n" " -p Used to supply given padding value, default 0.0.\n" " -G Use a Gaussain filter (default).\n" " -S Use the input object for each of the directional filters rather\n" " than the output of the previous directional filter. The seperate\n" " filter outputs are then combined to form a compound object (c),\n" " the sum (a) or the square root of the sum of the squared values\n" " of the filter passes (s).\n" " -t Filter directions, eg x filter along lines and x, y filter\n" " along lines then through columns.\n" " -v Verbose output with parameter values and execution time.\n" "Applies a seperable filter to a Woolz domain object with grey values.\n" "The input object is read from stdin and the filtered object is\n" "written to stdout unless the filenames are given.\n", *argv, " -m ,3.0,2.0 -t x,y,z -o smooth.wlz in.wlz\n" "The input Woolz object is read from in.wlz, and filtered using a\n" "Gaussian filter with sigma values of 1.0, 3.0 and 2.0 in the x, y\n" "and z directions. The filtered object is then written to the file\n" "smoothed.wlz.\n"); } return(!ok); }
/*! * \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); }
int main(int argc, char **argv) { int idx, option, dither = 0, overwrite = 1, ok = 1, usage = 0; WlzImArNorm norm = WLZ_IMARNORM_NONE; WlzErrorNum errNum = WLZ_ERR_NONE; FILE *fP = NULL; WlzObject *outObj = NULL; WlzObject *inObj[2]; WlzBinaryOperatorType operator = WLZ_BO_ADD; char *outObjFileStr; char *inObjFileStr[2]; WlzPixelV gMin[3], gMax[3]; const char *errMsg; static char optList[] = "O:o:ab:dgilmsnNh", outObjFileStrDef[] = "-", inObjFileStrDef[] = "-"; opterr = 0; inObj[0] = NULL; inObj[1] = NULL; outObjFileStr = outObjFileStrDef; inObjFileStr[0] = inObjFileStrDef; inObjFileStr[1] = inObjFileStrDef; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'O': if((sscanf(optarg, "%d", &overwrite) != 1) || (overwrite < 0) || (overwrite > 2)) { usage = 1; ok = 0; } break; case 'o': outObjFileStr = optarg; break; case 'a': operator = WLZ_BO_ADD; break; case 'b': operator = atoi(optarg); switch( operator ){ case WLZ_BO_ADD: case WLZ_BO_SUBTRACT: case WLZ_BO_MULTIPLY: case WLZ_BO_DIVIDE: case WLZ_BO_MODULUS: case WLZ_BO_EQ: case WLZ_BO_NE: case WLZ_BO_GT: case WLZ_BO_GE: case WLZ_BO_LT: case WLZ_BO_LE: case WLZ_BO_AND: case WLZ_BO_OR: case WLZ_BO_XOR: case WLZ_BO_MAX: case WLZ_BO_MIN: case WLZ_BO_MAGNITUDE: break; default: usage = 1; ok = 0; break; } break; case 'd': operator = WLZ_BO_DIVIDE; break; case 'g': operator = WLZ_BO_MAGNITUDE; break; case 'l': operator = WLZ_BO_MODULUS; break; case 'm': operator = WLZ_BO_MULTIPLY; break; case 's': operator = WLZ_BO_SUBTRACT; break; case 'n': norm = WLZ_IMARNORM_INPUT; break; case 'N': norm = WLZ_IMARNORM_256; break; case 'i': dither = 1; break; case 'h': default: usage = 1; ok = 0; break; } } if((inObjFileStr[0] == NULL) || (*inObjFileStr[0] == '\0') || (inObjFileStr[1] == NULL) || (*inObjFileStr[1] == '\0') || (outObjFileStr == NULL) || (*outObjFileStr == '\0')) { ok = 0; usage = 1; } if(ok && (optind < argc)) { idx = 0; while((idx < 2) && (optind < argc)) { inObjFileStr[idx] = *(argv + optind); ++optind; ++idx; } } if(ok && (optind != argc)) { usage = 1; ok = 0; } if(ok) { idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < 2)) { errNum = WLZ_ERR_READ_EOF; if((inObjFileStr[idx] == NULL) || (*inObjFileStr[idx] == '\0') || ((fP = (strcmp(inObjFileStr[idx], "-")? fopen(inObjFileStr[idx], "r"): stdin)) == NULL) || ((inObj[idx]= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read object %d from file %s (%s)\n", *argv, idx, inObjFileStr[idx], errMsg); } if(fP && strcmp(inObjFileStr[idx], "-")) { fclose(fP); } ++idx; } } if(ok) { idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < 2)) { if((inObj[idx]->type != WLZ_2D_DOMAINOBJ) && (inObj[idx]->type != WLZ_3D_DOMAINOBJ)) { ok = 0; (void )fprintf(stderr, "%s: input object %d is not a domain object\n", *argv, idx); } ++idx; } } if(ok && (norm == WLZ_IMARNORM_INPUT)) { if(((errNum = WlzGreyRange(inObj[0], gMin, gMax)) != WLZ_ERR_NONE) || ((errNum = WlzGreyRange(inObj[1], gMin + 1, gMax + 1)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to find input objects grey range (%s)\n", *argv, errMsg); } } if(ok) { if( WlzGreyTypeFromObj(inObj[0], &errNum) == WLZ_GREY_RGBA ){ if((outObj = WlzRGBAImageArithmetic(inObj[0], inObj[1], operator, 1, &errNum)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute new object (%s).\n", *argv, errMsg); } } else if((outObj = WlzImageArithmetic(inObj[0], inObj[1], operator, 0, &errNum)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute new object (%s).\n", *argv, errMsg); } } if(ok && (norm != WLZ_IMARNORM_NONE) && (WlzGreyTypeFromObj(inObj[0], &errNum) != WLZ_GREY_RGBA) ) { if((errNum = WlzGreyRange(outObj, gMin+ 2, gMax + 2)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to find output object's grey range (%s)\n", *argv, errMsg); } if(ok) { if(norm == WLZ_IMARNORM_256) { gMin[0].type = WLZ_GREY_UBYTE; gMin[0].v.ubv = 0; gMax[0].type = WLZ_GREY_UBYTE; gMax[0].v.ubv = 255; (void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type); (void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type); } else { (void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type); (void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type); (void )WlzValueConvertPixel(gMin + 1, gMin[1], gMin[2].type); (void )WlzValueConvertPixel(gMax + 1, gMax[1], gMax[2].type); switch(gMin[2].type) { case WLZ_GREY_INT: if(gMin[1].v.inv < gMin[0].v.inv) { gMin[0].v.inv = gMin[1].v.inv; } if(gMax[1].v.inv > gMax[0].v.inv) { gMax[0].v.inv = gMax[1].v.inv; } break; case WLZ_GREY_SHORT: if(gMin[1].v.shv < gMin[0].v.shv) { gMin[0].v.shv = gMin[1].v.shv; } if(gMax[1].v.shv > gMax[0].v.shv) { gMax[0].v.shv = gMax[1].v.shv; } break; case WLZ_GREY_UBYTE: if(gMin[1].v.ubv < gMin[0].v.ubv) { gMin[0].v.ubv = gMin[1].v.ubv; } if(gMax[1].v.ubv > gMax[0].v.ubv) { gMax[0].v.ubv = gMax[1].v.ubv; } break; case WLZ_GREY_FLOAT: if(gMin[1].v.flv < gMin[0].v.flv) { gMin[0].v.flv = gMin[1].v.flv; } if(gMax[1].v.flv > gMax[0].v.flv) { gMax[0].v.flv = gMax[1].v.flv; } break; case WLZ_GREY_DOUBLE: if(gMin[1].v.dbv < gMin[0].v.dbv) { gMin[0].v.dbv = gMin[1].v.dbv; } if(gMax[1].v.dbv > gMax[0].v.dbv) { gMax[0].v.dbv = gMax[1].v.dbv; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } if((errNum = WlzGreySetRange(outObj, gMin[2], gMax[2], gMin[0], gMax[0], dither)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to set output object's grey range (%s)\n", *argv, errMsg); } } if(ok) { errNum = WLZ_ERR_WRITE_EOF; if(((fP = (strcmp(outObjFileStr, "-")? fopen(outObjFileStr, "w"): stdout)) == NULL) || ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write output object (%s).\n", *argv, errMsg); } if(fP && strcmp(outObjFileStr, "-")) { fclose(fP); } } WlzFreeObj(inObj[0]); WlzFreeObj(inObj[1]); WlzFreeObj(outObj); if(usage) { fprintf(stderr, "Usage: %s" " [-O#] [-o<out file>] [-a] [-b <op>] [-d] [-g] [-i] [-l] [-m] [-s] [-h] " "[<in object 0>] [<in object 1>]\n" "Options:\n" " -O Overwrite option (only useful for debugging)\n" " -o Output file name.\n" " -a Add the object's grey values.\n" " -b <op> Apply binary operation to the grey-values.\n" " op = %d - Add\n" " = %d - SUBTRACT\n" " = %d - MULTIPLY\n" " = %d - DIVIDE\n" " = %d - MODULUS\n" " = %d - EQ\n" " = %d - NE\n" " = %d - GT\n" " = %d - GE\n" " = %d - LT\n" " = %d - LE\n" " = %d - AND\n" " = %d - OR\n" " = %d - XOR\n" " = %d - MAX\n" " = %d - MIN\n" " = %d - MAGNITUDE\n" " -d Divide the grey values of the 1st object by those of the 2nd.\n" " -g Vector magnitude of horizontal and vertical component objects\n" " -i Dither values if setting range\n" " -l Compute the modulus of the grey values of the 1st object wrt\n" " those of the 2nd.\n" " -m Multiply the object's grey values.\n" " -s Subtract the grey values of the 2nd object from those of the 1st.\n" " -n Normalises the output object to the range of the input objects.\n" " -N Normalises the output objects to the range [0-255].\n" " -h Help, prints this usage message.\n" "Computes an arithmetic binary (two objects) operation on two domain\n" "objects. The default operator is add.\n" "The input objects are read from stdin and values are written to stdout\n" "unless the filenames are given.\n" "Example:\n%s%s%s", *argv, WLZ_BO_ADD, WLZ_BO_SUBTRACT, WLZ_BO_MULTIPLY, WLZ_BO_DIVIDE, WLZ_BO_MODULUS, WLZ_BO_EQ, WLZ_BO_NE, WLZ_BO_GT, WLZ_BO_GE, WLZ_BO_LT, WLZ_BO_LE, WLZ_BO_AND, WLZ_BO_OR, WLZ_BO_XOR, WLZ_BO_MAX, WLZ_BO_MIN, WLZ_BO_MAGNITUDE, "cat obj1.wlz | ", *argv, " -o obj3.wlz -a obj2.wlz\n" "A new object 'obj3.wlz is formed by adding the grey values of obj1 and\n" "obj2.wlz.\n"); } return(!ok); }
/*! * \return Thresholded object or NULL on error. * \ingroup WlzThreshold * \brief Hysteresis thresholds the given Woolz object. * Values are in the domain of the hysteresis threshold'd * object if they are above/below the primary threshold * or above/below the secondary threshold and connected * to values above/below the primary threshold. * \param srcObj Object to be thresholded. * \param pThrV Primary hysteresis threshold * value. * \param sThrV Threshold for above or below * values. * \param hilo Threshold for above or below * values. * \param con Connectivity to examine for * hysteresis. * \param dstErr Destination error pointer, may * be null. */ WlzObject *WlzHyThreshold(WlzObject *srcObj, WlzPixelV pThrV, WlzPixelV sThrV, WlzThresholdType hilo, WlzConnectType con, WlzErrorNum *dstErr) { int simpleThr = 0; WlzPixelV tmpV; WlzObject *dstObj = NULL, *pThrObj = NULL, *sThrObj = NULL, *dThrObj = NULL, *iThrObj = NULL, *uThrObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if(srcObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(srcObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(srcObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { if(con == WLZ_0_CONNECTED) { simpleThr = 1; } else { if((errNum = WlzValueConvertPixel(&tmpV, sThrV, pThrV.type)) == WLZ_ERR_NONE) { switch(pThrV.type) { case WLZ_GREY_INT: if(tmpV.v.inv == pThrV.v.inv) { simpleThr = 1; } break; case WLZ_GREY_SHORT: if(tmpV.v.shv == pThrV.v.shv) { simpleThr = 1; } break; case WLZ_GREY_UBYTE: if(tmpV.v.ubv == pThrV.v.ubv) { simpleThr = 1; } break; case WLZ_GREY_FLOAT: if(fabs(tmpV.v.flv - pThrV.v.flv) <= FLT_EPSILON) { simpleThr = 1; } break; case WLZ_GREY_DOUBLE: if(fabs(tmpV.v.dbv - pThrV.v.dbv) <= DBL_EPSILON) { simpleThr = 1; } break; case WLZ_GREY_RGBA: if( tmpV.v.rgbv == pThrV.v.rgbv ) { simpleThr = 1; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } } if(errNum == WLZ_ERR_NONE) { if(simpleThr) { dstObj = WlzThreshold(srcObj, pThrV, hilo, &errNum); } else { pThrObj = WlzThreshold(srcObj, pThrV, hilo, &errNum); if(errNum == WLZ_ERR_NONE) { if(pThrObj->type == WLZ_EMPTY_OBJ) { dstObj = pThrObj; pThrObj = NULL; } else { sThrObj = WlzThreshold(srcObj, sThrV, hilo, &errNum); if(errNum == WLZ_ERR_NONE) { if(sThrObj->type == WLZ_EMPTY_OBJ) { dstObj = pThrObj; pThrObj = NULL; } else { dThrObj = WlzDilation(pThrObj, con, &errNum); if(errNum == WLZ_ERR_NONE) { iThrObj = WlzIntersect2(dThrObj, sThrObj, &errNum); } if(errNum == WLZ_ERR_NONE) { uThrObj = WlzUnion2(pThrObj, iThrObj, &errNum); } if(errNum == WLZ_ERR_NONE) { dstObj = WlzMakeMain(uThrObj->type, uThrObj->domain, srcObj->values, srcObj->plist, srcObj, &errNum); } if(dThrObj) { WlzFreeObj(dThrObj); } if(iThrObj) { WlzFreeObj(iThrObj); } if(uThrObj) { WlzFreeObj(uThrObj); } } if(sThrObj) { WlzFreeObj(sThrObj); } if(pThrObj) { WlzFreeObj(pThrObj); } } } } } } if(dstErr) { *dstErr = errNum; } return(dstObj); }
/*! * \ingroup WlzValuesFilters * \brief Set new grey-range by simple linear interpolation. It assumes that the min and max values enclose the true range of grey-values in the object. Failure to check this could result in a segmentation fault. The transform function is: \f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta \f] Here \f$\delta\f$ is the dither value. * * \return Woolz error number * \param obj Input grey-level object whose values are to be reset. * \param min Initial minimum value * \param max Initial maximum value * \param Min Final minimum value * \param Max Final maximum value * \param Dither values if destination range is greater than source range * and this flag is non-zero. * \par Source: * WlzGreySetRange.c */ WlzErrorNum WlzGreySetRange( WlzObject *obj, WlzPixelV min, WlzPixelV max, WlzPixelV Min, WlzPixelV Max, int dither) { double gMin = 0.0, gMax = 0.0, sigma = 0.0, factor, val; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzObject *tempobj; WlzValues *values; WlzDomain *domains; int i, j, nplanes; WlzErrorNum errNum = WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->values.core == NULL ){ return WLZ_ERR_VALUES_NULL; } if( WlzGreyTableIsTiled(obj->values.core->type) ){ return WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ return WLZ_ERR_PLANEDOMAIN_TYPE; } if( obj->values.vox == NULL ){ return WLZ_ERR_VALUES_NULL; } if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ return WLZ_ERR_VOXELVALUES_TYPE; } /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; i < nplanes; i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, &errNum); if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){ errNum = WLZ_ERR_UNSPECIFIED; break; } errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither); WlzFreeObj( tempobj ); if( errNum != WLZ_ERR_NONE ){ break; } } return errNum; case WLZ_TRANS_OBJ: return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ /* get conversion function - should use LUT use 4 LUTS for rgb type since bounded */ if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){ WlzUByte rgbaLut[4][256]; WlzUInt rgbamin[4], rgbaMin[4]; double rgbaFactor[4], val1; WlzUInt red, green, blue, alpha; rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv); rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv); if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){ rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - WLZ_RGBA_RED_GET(Min.v.rgbv))/ (WLZ_RGBA_RED_GET(max.v.rgbv) - WLZ_RGBA_RED_GET(min.v.rgbv))); } else { rgbaFactor[0] = 0.0; } rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv); rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv); if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){ rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - WLZ_RGBA_GREEN_GET(Min.v.rgbv))/ (WLZ_RGBA_GREEN_GET(max.v.rgbv) - WLZ_RGBA_GREEN_GET(min.v.rgbv))); } else { rgbaFactor[1] = 0.0; } rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv); rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv); if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){ rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - WLZ_RGBA_BLUE_GET(Min.v.rgbv))/ (WLZ_RGBA_BLUE_GET(max.v.rgbv) - WLZ_RGBA_BLUE_GET(min.v.rgbv))); } else { rgbaFactor[2] = 0.0; } rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv); rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv); if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){ rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/ (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - WLZ_RGBA_ALPHA_GET(min.v.rgbv))); } else { rgbaFactor[3] = 0.0; } /* now set up the LUTS */ for(i=0; i < 4; i++){ for(j=0; j < 256; j++){ val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i]; rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255); } } /* set values - can assume rgba grey-type */ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){ red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)]; green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)]; blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)]; alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)]; WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } else { WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE); if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){ return WLZ_ERR_FLOAT_DATA; } errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv); if(dither) { if(fabs(factor) < 1.0 + DBL_EPSILON) { dither = 0; } else { sigma = fabs(2.0 / factor); AlgRandSeed(101); switch(gwsp.pixeltype) { case WLZ_GREY_INT: gMin = ALG_MAX(Min.v.dbv, INT_MIN); gMax = ALG_MIN(Max.v.dbv, INT_MAX); break; case WLZ_GREY_SHORT: gMin = ALG_MAX(Min.v.dbv, SHRT_MIN); gMax = ALG_MIN(Max.v.dbv, SHRT_MAX); break; case WLZ_GREY_UBYTE: gMin = ALG_MAX(Min.v.dbv, 0); gMax = ALG_MIN(Max.v.dbv, 255); break; case WLZ_GREY_FLOAT: gMin = ALG_MAX(Min.v.dbv, FLT_MIN); gMax = ALG_MIN(Max.v.dbv, FLT_MAX); break; case WLZ_GREY_DOUBLE: gMin = Min.v.dbv; gMax = Max.v.dbv; break; default: break; } } } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++){ if(dither){ val = factor * (*gptr.inp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv; } *gptr.inp = WLZ_NINT(val); } break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++){ if(dither){ val = factor * (*gptr.shp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv; } *gptr.shp = (short )WLZ_NINT(val); } break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){ if(dither){ val = factor * (*gptr.ubp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv; } *gptr.ubp = (WlzUByte )WLZ_NINT(val); } break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++){ if(dither){ val = factor * (*gptr.flp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv; } *gptr.flp = (float )val; } break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){ if(dither){ val = factor * (*gptr.dbp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv; } *gptr.dbp = val; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } } return errNum; }
/*! * \return Woolz error number. * \ingroup WlzExtFF * \brief Writes the given Woolz object to the given file(s) using the * given (2D) file format. * \param gvnFileName Given file name. * \param fFmt Given file format (must be a 2D file * format). * \param obj Given woolz object. */ WlzErrorNum WlzEffWriteObjStack(const char *gvnFileName, WlzEffFormat fFmt, WlzObject *obj) { int tI0; char *fPathStr = NULL, *fBodyStr = NULL, *fExtStr = NULL, *fCtrStr = NULL; unsigned char *data = NULL; WlzPixelV bgdV; WlzIVertex2 imgSz2D, imgOrg2D; WlzErrorNum errNum = WLZ_ERR_NONE; if(gvnFileName == NULL) { 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 { switch(obj->type) { case WLZ_2D_DOMAINOBJ: if((obj->domain.core->type != WLZ_INTERVALDOMAIN_INTVL) && (obj->domain.core->type != WLZ_INTERVALDOMAIN_RECT)) { errNum = WLZ_ERR_DOMAIN_TYPE; } else { imgOrg2D.vtX = obj->domain.i->kol1; imgOrg2D.vtY = obj->domain.i->line1; imgSz2D.vtX = obj->domain.i->lastkl - imgOrg2D.vtX + 1; imgSz2D.vtY = obj->domain.i->lastln - imgOrg2D.vtY + 1; tI0 = imgSz2D.vtX * imgSz2D.vtY; if((data = (unsigned char *)AlcMalloc(tI0 * sizeof(unsigned char))) == NULL) { errNum = WLZ_ERR_NONE; } } if(errNum == WLZ_ERR_NONE) { bgdV = WlzGetBackground(obj, &errNum); } if(errNum == WLZ_ERR_NONE) { (void )WlzValueConvertPixel(&bgdV, bgdV, WLZ_GREY_UBYTE); errNum = WlzEffWriteObjStack2D(gvnFileName, fFmt, obj, imgSz2D, imgOrg2D, data, bgdV.v.ubv); } break; case WLZ_3D_DOMAINOBJ: if(obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) { errNum = WLZ_ERR_DOMAIN_TYPE; } else if(obj->values.core->type != WLZ_VOXELVALUETABLE_GREY) { errNum = WLZ_ERR_VALUES_TYPE; } else { errNum = WlzEffStackFileNameParse(gvnFileName, fFmt, &fPathStr, &fBodyStr, &fExtStr, &fCtrStr); } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteObjStack3D(fPathStr, fBodyStr, fExtStr, fCtrStr, fFmt, obj); } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(data) { AlcFree(data); } if(fPathStr) { AlcFree(fPathStr); } if(fBodyStr) { AlcFree(fBodyStr); } if(fExtStr) { AlcFree(fExtStr); } if(fCtrStr) { AlcFree(fCtrStr); } return(errNum); }