/*! * \return Shade corrected object or NULL on error. * \ingroup WlzValueFilters * \brief Shade corrects the given 2D domain object with grey * values. Grey value types known to be the same. * \param srcObj Given object to be shade * corrected. * \param shdObj Given bright field object. * \param nrmVal Normalization value. * \param inPlace Modify the grey values of the * given object if non-zero. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzShadeCorrect2DG(WlzObject *srcObj, WlzObject *shdObj, double nrmVal, int inPlace, WlzErrorNum *dstErr) { int tI0, iCnt, red, green, blue; double tD0; WlzUInt tUI0, tUI1; WlzObject *uObj = NULL, *uSrcObj = NULL, *uShdObj = NULL, *rtnObj = NULL; WlzGreyP srcPix, shdPix, rtnPix; WlzValues newVal; WlzIntervalWSpace srcIWSp, shdIWSp, rtnIWSp; WlzGreyWSpace srcGWSp, shdGWSp, rtnGWSp; WlzErrorNum errNum = WLZ_ERR_NONE; /* Find intersection of the given and shade objects. */ uObj = WlzIntersect2(srcObj, shdObj, &errNum); /* Make new objects with the values of the given and shade objects * but the domain of their intersection. */ if(errNum == WLZ_ERR_NONE) { uSrcObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { uShdObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, shdObj->values, NULL, NULL, &errNum); } /* Make a new object, again using the union for the domain, but this time * either sharing the given objects values or creating a new value table. */ if(errNum == WLZ_ERR_NONE) { if(inPlace) { rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values, NULL, NULL, &errNum); } else { newVal.v = WlzNewValueTb(uObj, srcObj->values.core->type, WlzGetBackground(srcObj, NULL), &errNum); if(errNum == WLZ_ERR_NONE) { if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, newVal, NULL, NULL, &errNum)) == NULL) { (void )WlzFreeValueTb(newVal.v); } } } } /* Work through the intervals setting the grey values. */ if(errNum == WLZ_ERR_NONE) { if(((errNum = WlzInitGreyScan(uSrcObj, &srcIWSp, &srcGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(uShdObj, &shdIWSp, &shdGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(rtnObj, &rtnIWSp, &rtnGWSp)) == WLZ_ERR_NONE)) { while(((errNum = WlzNextGreyInterval(&srcIWSp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&shdIWSp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&rtnIWSp)) == WLZ_ERR_NONE)) { srcPix = srcGWSp.u_grintptr; shdPix = shdGWSp.u_grintptr; rtnPix = rtnGWSp.u_grintptr; iCnt = rtnIWSp.rgtpos - rtnIWSp.lftpos + 1; switch(rtnGWSp.pixeltype) { case WLZ_GREY_INT: while(iCnt-- > 0) { tD0 = (*(srcPix.inp)++ * nrmVal) / (*(shdPix.inp)++ + 1.0); *(rtnPix.inp)++ = WLZ_NINT(tD0); } break; case WLZ_GREY_SHORT: while(iCnt-- > 0) { tD0 = (*(srcPix.shp)++ * nrmVal) / (*(shdPix.shp)++ + 1.0); tI0 = WLZ_NINT(tD0); *(rtnPix.shp)++ = (short )WLZ_CLAMP(tI0, SHRT_MIN, SHRT_MAX); } break; case WLZ_GREY_UBYTE: while(iCnt-- > 0) { tD0 = (*(srcPix.ubp)++ * nrmVal) / (*(shdPix.ubp)++ + 1.0); tI0 = WLZ_NINT(tD0); *(rtnPix.ubp)++ = (WlzUByte )WLZ_CLAMP(tI0, 0, 255); } break; case WLZ_GREY_FLOAT: while(iCnt-- > 0) { tD0 = (*(srcPix.flp)++ * nrmVal) / (*(shdPix.flp)++ + 1.0); *(rtnPix.flp)++ = (float )tD0; } break; case WLZ_GREY_DOUBLE: while(iCnt-- > 0) { tD0 = (*(srcPix.dbp)++ * nrmVal) / (*(shdPix.dbp)++ + 1.0); *(rtnPix.dbp)++ = tD0; } break; case WLZ_GREY_RGBA: while(iCnt-- > 0) { /* slightly different logic here. Avoid divide by zero by explicit check */ tUI0 = *(srcPix.rgbp)++; tUI1 = *(shdPix.rgbp)++; red = WLZ_RGBA_RED_GET(tUI1); red = (red)? (int )(((WLZ_RGBA_RED_GET(tUI0) * nrmVal))/red): (int )nrmVal; red = WLZ_CLAMP(red, 0, 255); green = WLZ_RGBA_GREEN_GET(tUI1); green = (green)? (int )(((WLZ_RGBA_GREEN_GET(tUI0) * nrmVal))/green): (int )nrmVal; green = WLZ_CLAMP(green, 0, 255); blue = WLZ_RGBA_BLUE_GET(tUI1); blue = (blue)? (int )(((WLZ_RGBA_BLUE_GET(tUI0) * nrmVal))/blue): (int )nrmVal; blue = WLZ_CLAMP(blue, 0, 255); WLZ_RGBA_RGBA_SET(tUI0, red, green, blue, 255); *(rtnPix.rgbp)++ = tUI0; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_EOO) /* Reset error from end of intervals */ { errNum = WLZ_ERR_NONE; } } } (void )WlzFreeObj(uObj); (void )WlzFreeObj(uSrcObj); (void )WlzFreeObj(uShdObj); if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rtnObj); rtnObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rtnObj); }
void read_reference_object_cb( Widget w, XtPointer client_data, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *) call_data; WlzEffFormat image_type; WlzObject *obj; String icsfile; WlzDomain domain; WlzValues values; WlzObject *newObj; WlzErrorNum errNum=WLZ_ERR_NONE; /* set hour glass cursor */ HGU_XmSetHourGlassCursor(globals.topl); /* read the new reference object note the switch is to allow direct read given the image type to include the model input options */ if( client_data ){ image_type = (WlzEffFormat) client_data; if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value, cbs->dir))){ obj = WlzEffReadObj(NULL, icsfile, image_type, 0, 0, 0, &errNum); AlcFree(icsfile); } else { obj = NULL; } } else { obj = HGU_XmReadExtFFObject(read_obj_dialog, cbs, &image_type, &errNum); } if( obj == NULL){ HGU_XmUserError(globals.topl, "Read Reference Object:\n" " No reference object read - either the\n" " selected file is empty or it is not the\n" " correct object type - please check the\n" " file or make a new selection", XmDIALOG_FULL_APPLICATION_MODAL); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } if( obj->values.core == NULL ){ HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must have a grey-\n" " value table. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } /* install the new reference object */ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, &errNum))){ domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, &errNum))){ values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, obj->plist, NULL, &errNum); WlzFreeObj(obj); obj = newObj; } } globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } globals.origObjExtType = image_type; /* set title and reference file list */ if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value, cbs->dir))) { Widget cascade; HGU_XmFileListAddFile(globals.fileList, icsfile, image_type); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } if( XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &icsfile) ) { set_topl_title(icsfile); globals.file = icsfile; } } MAPaintLogData("ReferenceFile", globals.file, 0, NULL); /* clear feedback object and install new reference object */ if( errNum == WLZ_ERR_NONE ){ if( globals.fb_obj ){ WlzFreeObj(globals.fb_obj); globals.fb_obj = NULL; } install_paint_reference_object( obj ); } /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "read_reference_object_cb", errNum); } return; }
/*! * \return New 3D object. * \ingroup WlzAllocation * \brief Constructs a 3D domain object from 2D domain objects. Each * 2D object is assigned in turn to the 3D object no domains * or values are copied. An empty can be specified by * setting the 2D object to NULL. Either all or none of * the 2D objects must have values. When the 2D objects * have values then the background value of the first 2D * object is set to be the background value of the 3D object. * \param nObjs Number of objects. * \param objs The 2D objects, the first of which * MUST not be NULL. * \param plane1 The plane coordinate of the first * 2D object. * \param xSz Column voxel size. * \param ySz Line voxel size. * \param zSz Plane voxel size. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzConstruct3DObjFromObj(int nObjs, WlzObject **objs, int plane1, float xSz, float ySz, float zSz, WlzErrorNum *dstErr) { int idx, lastpl; WlzDomain dom3D; WlzValues val3D; WlzObject *obj2D, *obj3D = NULL; WlzPixelV bgd; WlzErrorNum errNum = WLZ_ERR_NONE; dom3D.core = NULL; val3D.core = NULL; lastpl = plane1 + nObjs - 1; if((nObjs <= 0) || (objs == NULL)) { errNum = WLZ_ERR_PARAM_NULL; } else if((obj2D = *objs) == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Make a plane domain, set column and line bounds later. */ if(errNum == WLZ_ERR_NONE) { dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, plane1, lastpl, 0, 1, 0, 1, &errNum); } if(errNum == WLZ_ERR_NONE) { dom3D.p->voxel_size[0] = xSz; dom3D.p->voxel_size[1] = ySz; dom3D.p->voxel_size[2] = zSz; } /* Make a voxel value table. */ if(errNum == WLZ_ERR_NONE) { if(obj2D->values.core) { bgd = WlzGetBackground(obj2D, &errNum); if(errNum == WLZ_ERR_NONE) { val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, plane1, lastpl, bgd, NULL, &errNum); } } } for(idx = 0; (errNum == WLZ_ERR_NONE) && (idx < nObjs); ++idx) { obj2D = *(objs + idx); if(obj2D) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE) { *(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL); if(val3D.core) { if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL); } } } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox); } if(errNum == WLZ_ERR_NONE) { obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum); } if(errNum != WLZ_ERR_NONE) { if(dom3D.core) { (void )WlzFreeDomain(dom3D); } if(val3D.core) { (void )WlzFreeValues(val3D); } } if(dstErr) { *dstErr = errNum; } return(obj3D); }
/*! * \return The background value. If the returned pixel value type is * WLZ_GREY_ERROR then an error has occurred. * \ingroup WlzValuesUtils * \brief Gets the background value of the given object. * \param obj Given object. * \param dstErr Destination error pointer, may be NULL. */ WlzPixelV WlzGetBackground( WlzObject *obj, WlzErrorNum *dstErr) { WlzPlaneDomain *planedmn; WlzPixelV bgd; WlzErrorNum errNum=WLZ_ERR_NONE; /* set up an invalid background return */ bgd.type = WLZ_GREY_ERROR; bgd.v.inv = 0; 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 ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( obj->values.v == NULL ){ bgd.type = WLZ_GREY_INT; bgd.v.inv = 0; break; } switch( WlzGreyTableTypeToTableType(obj->values.core->type, NULL) ){ case WLZ_GREY_TAB_RAGR: bgd = obj->values.v->bckgrnd; break; case WLZ_GREY_TAB_RECT: bgd = obj->values.r->bckgrnd; break; case WLZ_GREY_TAB_INTL: bgd = obj->values.i->bckgrnd; break; default: errNum = WLZ_ERR_VALUES_TYPE; break; } break; case WLZ_3D_DOMAINOBJ: if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( obj->values.core == NULL ){ bgd.type = WLZ_GREY_INT; bgd.v.inv = 0; errNum = WLZ_ERR_NONE; break; } planedmn = obj->domain.p; if( planedmn->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_PLANEDOMAIN_TYPE; break; } if(WlzGreyTableIsTiled(obj->values.core->type)) { bgd = obj->values.t->bckgrnd; } else if(obj->values.core->type == WLZ_VOXELVALUETABLE_GREY) { bgd = obj->values.vox->bckgrnd; } else { errNum = WLZ_ERR_VALUES_TYPE; } break; case WLZ_TRANS_OBJ: return( WlzGetBackground(obj->values.obj, dstErr) ); case WLZ_EMPTY_OBJ: bgd.type = WLZ_GREY_INT; bgd.v.inv = 0; errNum = WLZ_ERR_NONE; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( dstErr ){ *dstErr = errNum; } return bgd; }
void referenceFileListCb( Widget w, XtPointer client_data, XtPointer call_data) { HGU_XmFileListCallbackStruct *cbs= (HGU_XmFileListCallbackStruct *) client_data; WlzObject *obj; Widget cascade; WlzErrorNum errNum=WLZ_ERR_NONE; HGU_XmSetHourGlassCursor(globals.topl); if( cbs == NULL ){ /* clear list selection */ HGU_XmFileListClearList(globals.fileList); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } else if((obj = HGU_XmFileListReadObject(w, cbs, &errNum))){ WlzDomain domain; WlzValues values; WlzObject *newObj; switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, &errNum))){ domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, &errNum))){ values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, NULL); WlzFreeObj(obj); obj = newObj; } } globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } MAPaintLogData("ReferenceFile", refFileList[0], 0, NULL); install_paint_reference_object( obj ); /* set the title of the top-level window */ set_topl_title(cbs->file); globals.file = AlcStrDup(cbs->file); globals.origObjExtType = cbs->format; /* add to the file list and write file */ HGU_XmFileListAddFile(globals.fileList, cbs->file, cbs->format); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } HGU_XmUnsetHourGlassCursor(globals.topl); if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "ReferenceFileListCb", errNum); } return; }
/*! * \return New Woolz object. * \ingroup WlzAllocation * \brief Creates a new 2D spatial domain object by adding a * rectangular buffer of values to the given current * object (which may be NULL or empty). * \param cObj Given current object. * \param og Origin of rectangular buffer. * \param sz Buffer size. * \param gType Grey type which must be consistent * with the current object and the * buffer of values. * \param bufSz Number of values in the buffer. * \param bufP Given buffer of values. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzBuildObj2(WlzObject *cObj, WlzIVertex2 og, WlzIVertex2 sz, WlzGreyType gType, int bufSz, WlzGreyP bufP, WlzErrorNum *dstErr) { WlzDomain bDom; WlzValues bVal, nVal; WlzObject *bObj = NULL, *nObj = NULL; WlzPixelV bgdV; WlzErrorNum errNum = WLZ_ERR_NONE; bDom.core = NULL; bVal.core = NULL; nVal.core = NULL; bgdV.type = WLZ_GREY_INT; bgdV.v.inv = 0; if(cObj) { WlzGreyType cGType = WLZ_GREY_ERROR;; switch(cObj->type) { case WLZ_EMPTY_OBJ: cObj = NULL; break; case WLZ_2D_DOMAINOBJ: if(cObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(cObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { cGType = WlzGreyTypeFromObj(cObj, &errNum); bgdV = WlzGetBackground(cObj, &errNum); } if((errNum == WLZ_ERR_NONE) && (cGType != gType)) { errNum = WLZ_ERR_GREY_TYPE; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Create new object with domain and values of given rectangular buffer. */ if(errNum == WLZ_ERR_NONE) { bDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT, og.vtY, og.vtY + sz.vtY - 1, og.vtX, og.vtX + sz.vtX - 1, &errNum); } if(errNum == WLZ_ERR_NONE) { WlzObjectType gTT; gTT = WlzGreyTableType(WLZ_GREY_TAB_RECT, gType, NULL); bVal.r = WlzMakeRectValueTb(gTT, bDom.i->line1, bDom.i->lastln, bDom.i->kol1, sz.vtX, bgdV, bufP.inp, &errNum); } if(errNum == WLZ_ERR_NONE) { bObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, bDom, bVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { if(cObj == NULL) { /* Just copy the buffer object. */ nObj = WlzCopyObject(bObj, &errNum); } else { /* Compute union of current and buffer objects. */ nObj = (cObj)? WlzUnion2(cObj, bObj, &errNum): WlzMakeMain(WLZ_2D_DOMAINOBJ, bDom, nVal, NULL, NULL, &errNum); /* Create new value table. */ if(errNum == WLZ_ERR_NONE) { WlzObjectType gTT; gTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gType, NULL); nVal.v = WlzNewValueTb(nObj, gTT, bgdV, &errNum); } if(errNum == WLZ_ERR_NONE) { nObj->values = WlzAssignValues(nVal, NULL); } if(errNum == WLZ_ERR_NONE) { WlzObject *tObj; /* Copy existing values to new object. */ tObj = WlzGreyTransfer(nObj, cObj, &errNum); (void )WlzFreeObj(nObj); nObj = tObj; /* Then copy buffer values to new object. */ if(errNum == WLZ_ERR_NONE) { tObj = WlzGreyTransfer(nObj, bObj, &errNum); (void )WlzFreeObj(nObj); nObj = tObj; } } } } (void )WlzFreeObj(bObj); if(dstErr) { *dstErr = errNum; } return(nObj); }
/*! * \return Rescaled object. * \ingroup WlzTransform * \brief Rescales the given 3D domain object using an integer scale. * \param gObj Given object. * \param scale Integer scale factor. * \param expand If zero use \f$\frac{1}{scale}\f$. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzIntRescaleObj3D(WlzObject *gObj, int scale, int expand, WlzErrorNum *dstErr) { int gPIdx, nPIdx; WlzDomain gDom, nDom; WlzValues gVal, nVal, dumVal; WlzObject *gTObj = NULL, *nTObj = NULL, *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; WlzIBox3 nBox; nDom.core = NULL; nVal.core = NULL; dumVal.core = NULL; gDom = gObj->domain; gVal = gObj->values; if(expand) { nBox.xMin = gDom.p->kol1 * scale; nBox.xMax = ((gDom.p->lastkl + 1) * scale) - 1; nBox.yMin = gDom.p->line1 * scale; nBox.yMax = ((gDom.p->lastln + 1) * scale) - 1; nBox.zMin = gDom.p->plane1 * scale; nBox.zMax = ((gDom.p->lastpl + 1) * scale) - 1; } else { nBox.xMin = gDom.p->kol1 / scale; nBox.xMax = gDom.p->lastkl / scale; nBox.yMin = gDom.p->line1 / scale; nBox.yMax = gDom.p->lastln / scale; nBox.zMin = gDom.p->plane1 / scale; nBox.zMax = gDom.p->lastpl / scale; } nDom.p = WlzMakePlaneDomain(gDom.p->type, nBox.zMin, nBox.zMax, nBox.yMin, nBox.yMax, nBox.xMin, nBox.xMax, &errNum); if(errNum == WLZ_ERR_NONE) { if(gVal.core && (gVal.core->type != WLZ_EMPTY_OBJ)) { if(WlzGreyTableIsTiled(gVal.core->type)) { errNum = WLZ_ERR_VALUES_TYPE; } else { nVal.vox = WlzMakeVoxelValueTb(gVal.vox->type, nBox.zMin, nBox.zMax, WlzGetBackground(gObj, NULL), NULL, &errNum); } } } if(errNum == WLZ_ERR_NONE) { nPIdx = nBox.zMin; while((errNum == WLZ_ERR_NONE) && (nPIdx <= nBox.zMax)) { gPIdx = (expand)? nPIdx / scale: nPIdx * scale; if(nVal.vox) { gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(gDom.p->domains + gPIdx), *(gVal.vox->values + gPIdx), NULL, NULL, &errNum); } else { gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(gDom.p->domains + gPIdx), dumVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { nTObj = WlzIntRescaleObj2D(gTObj, scale, expand, &errNum); } (void )WlzFreeObj(gTObj); gTObj = NULL; if(errNum == WLZ_ERR_NONE) { *(nDom.p->domains + nPIdx) = WlzAssignDomain(nTObj->domain, NULL); if(nVal.vox) { *(nVal.vox->values + nPIdx) = WlzAssignValues(nTObj->values, NULL); } } (void )WlzFreeObj(nTObj); nTObj = NULL; ++nPIdx; } } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(gObj->type, nDom, nVal, NULL, NULL, &errNum); } else { (void )WlzFreePlaneDomain(nDom.p); (void )WlzFreeVoxelValueTb(nVal.vox); } if(dstErr) { *dstErr = errNum; } return(rObj); }
/*! * \ingroup WlzValuesUtils * \brief Convert a grey-level woolz object to RGBA via a colourmap look-up table. Values are clamped to [0,255] and the LUT is assumed to be unsigned byte 3x256 * * \return Woolz object * \param obj Input object to be converted * \param colormap Colourmap array * \param dstErr Error return * \par Source: * WlzRGBAConvert.c */ WlzObject *WlzIndexToRGBA( WlzObject *obj, unsigned char colormap[3][256], WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzGreyType oldpixtype; WlzGreyP go, gn; WlzIntervalWSpace oldiwsp, newiwsp; WlzGreyWSpace oldgwsp, newgwsp; WlzObjectType newvtbltype; WlzPixelV bg; WlzValues values; int k, greyVal, redVal, greenVal, blueVal; unsigned int rgbaVal; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object - must be domain object with a values table */ if( obj ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.core ){ if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else { oldpixtype = WlzGreyTableTypeToGreyType(obj->values.core->type, NULL); if( oldpixtype == WLZ_GREY_RGBA ){ return WlzMakeMain(obj->type, obj->domain, obj->values, NULL, NULL, dstErr); } } } else { errNum = WLZ_ERR_DOMAIN_NULL; } break; case WLZ_3D_DOMAINOBJ: return WlzIndexToRGBA3D(obj, colormap, dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } else { errNum = WLZ_ERR_OBJECT_NULL; } /* * Set type of new value table so as to preserve * rectangular/single interval/multiple interval * type. */ if( errNum == WLZ_ERR_NONE ){ newvtbltype = WlzGreyTableTypeToTableType(obj->values.core->type, &errNum); } if( errNum == WLZ_ERR_NONE ){ newvtbltype = WlzGreyTableType(newvtbltype, WLZ_GREY_RGBA, &errNum); } /* get the background - note background now carries its own type */ if( errNum == WLZ_ERR_NONE ){ bg = WlzGetBackground(obj, &errNum); switch( bg.type ){ case WLZ_GREY_INT: greyVal = WLZ_CLAMP(bg.v.inv, 0, 255); break; case WLZ_GREY_SHORT: greyVal = WLZ_CLAMP(bg.v.shv, 0, 255); break; case WLZ_GREY_UBYTE: greyVal = bg.v.ubv; break; case WLZ_GREY_FLOAT: greyVal = WLZ_CLAMP(bg.v.flv, 0, 255); break; case WLZ_GREY_DOUBLE: greyVal = (int )WLZ_CLAMP(bg.v.dbv, 0, 255); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } bg.type = WLZ_GREY_RGBA; WLZ_RGBA_RGBA_SET(bg.v.rgbv, colormap[0][greyVal], colormap[1][greyVal], colormap[2][greyVal], 255); } /* * Make the new object with new value table type and value table * allocated (but blank). Share original idom. */ if( errNum == WLZ_ERR_NONE ){ values.v = WlzNewValueTb(obj, newvtbltype, bg, &errNum); } if( errNum == WLZ_ERR_NONE ){ rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain, values, obj->plist, obj->assoc, &errNum); } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(obj, &oldiwsp, &oldgwsp); } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(rtnObj, &newiwsp, &newgwsp); } while( ((errNum = WlzNextGreyInterval(&oldiwsp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&newiwsp)) == WLZ_ERR_NONE) ){ go = oldgwsp.u_grintptr; gn = newgwsp.u_grintptr; for(k=0; k <= oldiwsp.colrmn; k++){ switch( oldgwsp.pixeltype ){ case WLZ_GREY_INT: greyVal = WLZ_CLAMP(*(go.inp), 0, 255); go.inp++; break; case WLZ_GREY_SHORT: greyVal = WLZ_CLAMP(*(go.shp), 0, 255); go.shp++; break; case WLZ_GREY_UBYTE: greyVal = *(go.ubp); go.ubp++; break; case WLZ_GREY_FLOAT: greyVal = WLZ_CLAMP(*(go.flp), 0, 255); go.flp++; break; case WLZ_GREY_DOUBLE: greyVal = (int )WLZ_CLAMP(*(go.dbp), 0, 255); go.dbp++; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } redVal = colormap[0][greyVal]; greenVal = colormap[1][greyVal]; blueVal = colormap[2][greyVal]; WLZ_RGBA_RGBA_SET(rgbaVal, redVal, greenVal, blueVal, 0xff); *(gn.rgbp) = rgbaVal; gn.rgbp++; } } /* while */ if(errNum == WLZ_ERR_EOO) /* Reset error from end of intervals */ { errNum = WLZ_ERR_NONE; } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \ingroup WlzValuesUtils * \brief Convert a RGBA image to a compound object. The RGBA * channels are at array indices 0,1,2,3 respectively * and the sub-object grey types will be WLZ_GREY_UBYTE. * * \return Compound array of rgba values * \param obj Input domain object with value type * WLZ_GREY_RGBA * \param colSpc The colour space. * \param dstErr Destination error ponyer, may be NULL. */ WlzCompoundArray *WlzRGBAToCompound( WlzObject *obj, WlzRGBAColorSpace colSpc, WlzErrorNum *dstErr) { WlzCompoundArray *cobj=NULL; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object type, and value type */ if( obj ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } return WlzRGBAToCompound3D(obj, colSpc, dstErr); case WLZ_TRANS_OBJ: /* not difficult, do it later */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_COMPOUND_ARR_1: case WLZ_COMPOUND_ARR_2: /* bit recursive this ! */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_EMPTY_OBJ: return (WlzCompoundArray *) WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; } } else { errNum = WLZ_ERR_OBJECT_NULL; } /* check colour space */ if( errNum == WLZ_ERR_NONE ){ switch( colSpc ){ case WLZ_RGBA_SPACE_RGB: case WLZ_RGBA_SPACE_HSB: case WLZ_RGBA_SPACE_CMY: break; default: errNum = WLZ_ERR_PARAM_DATA; break; } } /* create compound object return */ if( errNum == WLZ_ERR_NONE ){ WlzValues values; WlzObject *objs[4]; WlzObjectType type; WlzPixelV oldBck, newBck; type = WlzGreyTableType( WlzGreyTableTypeToTableType(obj->values.core->type, &errNum), WLZ_GREY_UBYTE, &errNum); oldBck = WlzGetBackground(obj, &errNum); /* red */ newBck.type = WLZ_GREY_UBYTE; newBck.v.ubv = (WlzUByte )WLZ_RGBA_RED_GET(oldBck.v.rgbv); values.v = WlzNewValueTb(obj, type, newBck, &errNum); objs[0] = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); /* green */ newBck.v.ubv = (WlzUByte )WLZ_RGBA_GREEN_GET(oldBck.v.rgbv); values.v = WlzNewValueTb(obj, type, newBck, &errNum); objs[1] = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); /* blue */ newBck.v.ubv = (WlzUByte )WLZ_RGBA_BLUE_GET(oldBck.v.rgbv); values.v = WlzNewValueTb(obj, type, newBck, &errNum); objs[2] = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); /* alpha */ newBck.v.ubv = (WlzUByte )WLZ_RGBA_ALPHA_GET(oldBck.v.rgbv); values.v = WlzNewValueTb(obj, type, newBck, &errNum); objs[3] = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); /* create compound object, object pointers are assigned for mode=3 so no need to free objects */ cobj = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 3, 4, &(objs[0]), obj->type, &errNum); } /* iterate through objects setting values */ if( errNum == WLZ_ERR_NONE ){ WlzIntervalWSpace iwsp0, iwsp[4]; WlzGreyWSpace gwsp0, gwsp[4]; int i, j, k; int a, col[3]; errNum = WlzInitGreyScan(obj, &iwsp0, &gwsp0); for(i=0; i < 4; i++){ errNum = WlzInitGreyScan(cobj->o[i], &(iwsp[i]), &(gwsp[i])); } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp0)) == WLZ_ERR_NONE)){ for(i=0; i < 4; i++){ errNum = WlzNextGreyInterval(&(iwsp[i])); } switch( colSpc ){ case WLZ_RGBA_SPACE_RGB: for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++, gwsp0.u_grintptr.rgbp++){ *(gwsp[0].u_grintptr.ubp++) = (WlzUByte )WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp)); *(gwsp[1].u_grintptr.ubp++) = (WlzUByte )WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp)); *(gwsp[2].u_grintptr.ubp++) = (WlzUByte )WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp)); *(gwsp[3].u_grintptr.ubp++) = (WlzUByte )WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp)); } break; case WLZ_RGBA_SPACE_HSB: /* each normalised to [0,255] */ for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++, gwsp0.u_grintptr.rgbp++){ col[0] = WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp)); col[1] = WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp)); col[2] = WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp)); a = WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp)); WlzRGBAConvertRGBToHSV_UBYTENormalised(col); *(gwsp[0].u_grintptr.ubp++) = (WlzUByte )(col[0]); *(gwsp[1].u_grintptr.ubp++) = (WlzUByte )(col[1]); *(gwsp[2].u_grintptr.ubp++) = (WlzUByte )(col[2]); *(gwsp[3].u_grintptr.ubp++) = (WlzUByte )a; } break; case WLZ_RGBA_SPACE_CMY: for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++, gwsp0.u_grintptr.rgbp++){ col[0] = WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp)); col[1] = WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp)); col[2] = WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp)); a = WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp)); *(gwsp[0].u_grintptr.ubp++) = (WlzUByte )((col[1] + col[2]) / 2); *(gwsp[1].u_grintptr.ubp++) = (WlzUByte )((col[2] + col[0]) / 2); *(gwsp[2].u_grintptr.ubp++) = (WlzUByte )((col[0] + col[1]) / 2); *(gwsp[3].u_grintptr.ubp++) = (WlzUByte )a; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } if( dstErr ){ *dstErr = errNum; } return cobj; }
/*! * \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); }
/*! * \ingroup WlzValuesUtils * \brief Calculate the modulus of the rgb values and return in an image of grey type WLZ_GREY_SHORT * * \return Grey-level object of modulus values * \param obj Input rgba object * \param dstErr error return * \par Source: * WlzRGBAConvert.c */ WlzObject *WlzRGBAToModulus( WlzObject *obj, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object type, and value type */ if( obj ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } return WlzRGBAToModulus3D(obj, dstErr); case WLZ_TRANS_OBJ: /* not difficult, do it later */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_COMPOUND_ARR_1: case WLZ_COMPOUND_ARR_2: /* bit recursive this ! */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; } } else { errNum = WLZ_ERR_OBJECT_NULL; } /* create object return */ if( errNum == WLZ_ERR_NONE ){ WlzValues values; WlzObjectType type; WlzPixelV oldBck, newBck; type = WlzGreyTableType( WlzGreyTableTypeToTableType(obj->values.core->type, &errNum), WLZ_GREY_SHORT, &errNum); oldBck = WlzGetBackground(obj, &errNum); newBck.type = WLZ_GREY_SHORT; newBck.v.shv = (short )WLZ_RGBA_MODULUS(oldBck.v.rgbv); /* make values table and return object */ values.v = WlzNewValueTb(obj, type, newBck, &errNum); rtnObj = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); } /* iterate through objects setting values */ if( errNum == WLZ_ERR_NONE ){ WlzIntervalWSpace iwsp0, iwsp1; WlzGreyWSpace gwsp0, gwsp1; int j, k; errNum = WlzInitGreyScan(obj, &iwsp0, &gwsp0); errNum = WlzInitGreyScan(rtnObj, &iwsp1, &gwsp1); while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp0)) == WLZ_ERR_NONE)){ errNum = WlzNextGreyInterval(&iwsp1); for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++, gwsp0.u_grintptr.rgbp++){ *(gwsp1.u_grintptr.shp++) = (short ) WLZ_RGBA_MODULUS(*(gwsp0.u_grintptr.rgbp)); } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
WlzObject *WlzRGBAToChannel( WlzObject *obj, WlzRGBAColorChannel chan, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzValues values; WlzObjectType type; WlzPixelV pixVal, oldBck, newBck; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object and channel */ if( obj ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if ( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){ errNum = WLZ_ERR_VALUES_TYPE; } return WlzRGBAToChannel3D(obj, chan, dstErr); case WLZ_TRANS_OBJ: /* not difficult, do it later */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_COMPOUND_ARR_1: case WLZ_COMPOUND_ARR_2: /* bit recursive this ! */ errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; } } else { errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ switch( chan ){ case WLZ_RGBA_CHANNEL_RED: case WLZ_RGBA_CHANNEL_GREEN: case WLZ_RGBA_CHANNEL_BLUE: case WLZ_RGBA_CHANNEL_HUE: case WLZ_RGBA_CHANNEL_SATURATION: case WLZ_RGBA_CHANNEL_BRIGHTNESS: case WLZ_RGBA_CHANNEL_CYAN: case WLZ_RGBA_CHANNEL_MAGENTA: case WLZ_RGBA_CHANNEL_YELLOW: break; default: errNum = WLZ_ERR_PARAM_DATA; break; } } /* now extract data */ if( errNum == WLZ_ERR_NONE ){ type = WlzGreyTableType( WlzGreyTableTypeToTableType(obj->values.core->type, &errNum), WLZ_GREY_UBYTE, &errNum); oldBck = WlzGetBackground(obj, &errNum); newBck.type = WLZ_GREY_UBYTE; newBck.v.ubv = (WlzUByte )WlzRGBAPixelValue(oldBck, chan, &errNum); } /* make values table and return object */ if( errNum == WLZ_ERR_NONE ){ values.v = WlzNewValueTb(obj, type, newBck, &errNum); rtnObj = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); } /* iterate through objects setting values */ if( errNum == WLZ_ERR_NONE ){ WlzIntervalWSpace iwsp0, iwsp1; WlzGreyWSpace gwsp0, gwsp1; int j, k; errNum = WlzInitGreyScan(obj, &iwsp0, &gwsp0); errNum = WlzInitGreyScan(rtnObj, &iwsp1, &gwsp1); pixVal.type = WLZ_GREY_RGBA; while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp0)) == WLZ_ERR_NONE)){ errNum = WlzNextGreyInterval(&iwsp1); for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++, gwsp0.u_grintptr.rgbp++){ pixVal.v.rgbv = (*(gwsp0.u_grintptr.rgbp)); *(gwsp1.u_grintptr.ubp++) = (WlzUByte ) WlzRGBAPixelValue(pixVal, chan, &errNum); } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \ingroup WlzBinaryOps * \brief Calculate the intersection of a set of objects. If uvt=0 calculate domain only, uvt=1 calculate the mmean grey-value at each point. Input objects must be all non-NULL and domain objects of the same type i.e. either 2D or 3D otherwise an error is returned. * * \return Intersection object with grey-table as required, if the intersection is empty returns WLZ_EMPTY_OBJ, NULL on error. * \param n number of input objects * \param objs input object array * \param uvt grey-table copy flag (1 - copy, 0 - no copy) * \param dstErr error return. * \par Source: * WlzIntersectN.c */ WlzObject *WlzIntersectN( int n, WlzObject **objs, int uvt, WlzErrorNum *dstErr) { WlzObject *obj = NULL; WlzIntervalDomain *idom; WlzInterval *itvl, *jtvl; WlzIntervalWSpace *iwsp; WlzIntervalWSpace *biwsp,*tiwsp,niwsp; WlzGreyWSpace *gwsp,ngwsp; WlzDomain domain; WlzValues values; WlzObjectType type; WlzPixelV backg; WlzGreyP greyptr; WlzGreyV gv; int i, j, k, l, inttot, change, lwas, nints; int line1, lastln; int kol1, lastkl; WlzErrorNum errNum = WLZ_ERR_NONE; /* * check pointers */ /* intersecction of no objects is an empty domain */ domain.i = NULL; values.v = NULL; if( n < 1 ) { return WlzMakeEmpty(dstErr); } /* array pointer == NULL or any object pointer == NULL is an error */ if(objs == NULL){ errNum = WLZ_ERR_OBJECT_NULL; } else { for(i=0; i<n; i++){ if(objs[i] == NULL){ errNum = WLZ_ERR_OBJECT_NULL; } } } if(errNum != WLZ_ERR_NONE) { obj = NULL; if(dstErr) { *dstErr = errNum; } return(obj); } /* check type of first object */ switch( objs[0]->type ){ case WLZ_2D_DOMAINOBJ: break; case WLZ_3D_DOMAINOBJ: return WlzIntersect3d(objs, n, uvt, &errNum); case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; if(dstErr) { *dstErr = errNum; } return NULL; } /* check number */ if (n == 1){ obj = WlzMakeMain(objs[0]->type, objs[0]->domain, objs[0]->values, NULL, NULL, &errNum); if(dstErr) { *dstErr = errNum; } return(obj); } /* check all objects are non-empty and have the same type Note an empty object is not an error */ for (i=0; i<n; i++){ if( objs[i]->type != objs[0]->type ){ if( objs[i]->type == WLZ_EMPTY_OBJ ){ return WlzMakeEmpty(dstErr); } else { errNum = WLZ_ERR_OBJECT_TYPE; if(dstErr) { *dstErr = errNum; } return NULL; } } /* check for size */ if( WlzIsEmpty(objs[i], &errNum) ){ return WlzMakeEmpty(dstErr); } else { if( errNum != WLZ_ERR_NONE ){ if(dstErr) { *dstErr = errNum; } return NULL; } } } /* * Find the line and column bounds of the intersection. */ line1 = objs[0]->domain.i->line1; lastln = objs[0]->domain.i->lastln; kol1 = objs[0]->domain.i->kol1; lastkl = objs[0]->domain.i->lastkl; for (i=1; i<n; i++) { idom = objs[i]->domain.i; if (line1 < idom->line1) { line1 = idom->line1; } if (lastln > idom->lastln) { lastln = idom->lastln; } if (kol1 < idom->kol1) { kol1 = idom->kol1; } if (lastkl > idom->lastkl) { lastkl = idom->lastkl; } } if( lastkl < kol1 || lastln < line1 ){ return WlzMakeEmpty(dstErr); } /* * Count the individual intervals so that sufficient space * for the intersection may be allocated. */ inttot=0; for (i=0; (i < n) && (errNum == WLZ_ERR_NONE); i++) { inttot += WlzIntervalCount(objs[i]->domain.i, &errNum); } if(errNum != WLZ_ERR_NONE) { if(dstErr) { *dstErr = errNum; } return NULL; } /* * Set up domain, value table structures, and object. */ if( (idom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL, line1, lastln, 0, lastkl-kol1, &errNum)) == NULL ){ if(dstErr) { *dstErr = errNum; } return NULL; } if( (itvl = (WlzInterval *) AlcMalloc (inttot * sizeof(WlzInterval))) == NULL ){ WlzFreeIntervalDomain(idom); errNum = WLZ_ERR_MEM_ALLOC; if(dstErr) { *dstErr = errNum; } return NULL; } idom->freeptr = AlcFreeStackPush(idom->freeptr, (void *)itvl, NULL); lwas = line1; jtvl = itvl; nints = 0; domain.i = idom; values.v = NULL; if( (obj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL, &errNum)) == NULL ){ WlzFreeIntervalDomain(idom); if(dstErr) { *dstErr = errNum; } return NULL; } /* * allocate space for workspaces */ if( (iwsp = (WlzIntervalWSpace *) AlcMalloc(n * sizeof(WlzIntervalWSpace))) == NULL ){ WlzFreeObj( obj ); errNum = WLZ_ERR_MEM_ALLOC; if(dstErr) { *dstErr = errNum; } return NULL; } biwsp = iwsp; tiwsp = biwsp + n; /* * Construct the intersection object's table of intervals. * Initialise scanning on each object/workspace combination. * Scan synchronously, setting up the intersection of * overlapping intervals. Needs a clear head !! */ for (i=0; (i < n) && (errNum == WLZ_ERR_NONE); i++) { errNum = WlzInitRasterScan(objs[i],iwsp,WLZ_RASTERDIR_ILIC); if(errNum == WLZ_ERR_NONE) { errNum = WlzNextInterval(iwsp++); } } if(errNum != WLZ_ERR_NONE) { WlzFreeObj( obj ); if(dstErr) { *dstErr = errNum; } return NULL; } l = lwas; for (;;) { /* * find next line of intersection */ do { change = 0; for (iwsp=biwsp; iwsp<tiwsp; iwsp++) { if (iwsp->linpos > l) { l = iwsp->linpos; } } for (iwsp=biwsp; iwsp<tiwsp; iwsp++) { while (iwsp->linpos < l) { if ((errNum = WlzNextInterval(iwsp)) != WLZ_ERR_NONE) { if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } goto firstfinished; } if (iwsp->linpos > l) { change = 1; } } } } while (change != 0); /* * find next interval of intersection */ kol1 = biwsp->lftpos; lastkl = biwsp->rgtpos; while(errNum == WLZ_ERR_NONE) { do { change = 0; for (iwsp=biwsp; iwsp<tiwsp; iwsp++) if (iwsp->lftpos > lastkl) { kol1 = iwsp->lftpos; lastkl = iwsp->rgtpos; } else if (iwsp->lftpos > kol1) kol1 = iwsp->lftpos; for (iwsp=biwsp; iwsp<tiwsp; iwsp++) { while (iwsp->rgtpos < kol1) { if ((errNum = WlzNextInterval(iwsp)) != WLZ_ERR_NONE) { if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } goto firstfinished; } if (iwsp->linpos != l) { l = iwsp->linpos; goto jumpline; } if (iwsp->lftpos > kol1) change = 1; } } } while ((change != 0) && (errNum == WLZ_ERR_NONE)); if(errNum == WLZ_ERR_NONE) { for (iwsp=biwsp; iwsp < tiwsp; iwsp++) { if (iwsp->rgtpos <= lastkl) { lastkl = iwsp->rgtpos; } } if (lastkl >= kol1) { itvl->ileft = kol1 - idom->kol1; itvl->iright = lastkl - idom->kol1; if (l == lwas) { nints++; } else { errNum = WlzMakeInterval(lwas,idom,nints,jtvl); for (j = lwas+1; (j < l) && (errNum == WLZ_ERR_NONE); j++) { errNum = WlzMakeInterval(j,idom,0,NULL); } if(errNum == WLZ_ERR_NONE) { lwas = l; nints = 1; jtvl = itvl; } } itvl++; } kol1 = lastkl+1; } } jumpline: ; } firstfinished: if(errNum != WLZ_ERR_NONE) { WlzFreeObj(obj); if(dstErr) { *dstErr = errNum; } return NULL; } errNum = WlzMakeInterval(lwas,idom,nints,jtvl); for (j = lwas+1; (j <= lastln) && (errNum == WLZ_ERR_NONE); j++) { errNum = WlzMakeInterval(j,idom,0,NULL); } if(errNum != WLZ_ERR_NONE) { WlzFreeObj(obj); AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return NULL; } /* * standardise the interval list (remove leading and trailing * empty lines, set kol1 so that at least one interval commences * at zero, set lastkl correctly) */ (void )WlzStandardIntervalDomain(idom); /* check for error or empty */ nints = WlzIntervalCount(idom, &errNum); if( nints < 0 ){ /* error */ WlzFreeObj(obj); AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return NULL; } else if( nints == 0 ){ /* empty object */ WlzFreeObj(obj); AlcFree((void *) biwsp); return WlzMakeEmpty(dstErr); } if (uvt != 0) { WlzGreyType grey_type; if( (gwsp = (WlzGreyWSpace *) AlcMalloc (n * sizeof (WlzGreyWSpace))) == NULL ){ WlzFreeObj(obj); AlcFree((void *) biwsp); errNum = WLZ_ERR_MEM_ALLOC; if(dstErr) { *dstErr = errNum; } return NULL; } /* construct an empty "ragged-rectangle" (type 1 or 2) greytable choosing the grey-value type from the first object in the list */ backg = WlzGetBackground(objs[0], &errNum); if(errNum == WLZ_ERR_NONE) { grey_type = WlzGreyTableTypeToGreyType(objs[0]->values.core->type, &errNum); } if(errNum == WLZ_ERR_NONE) { type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, grey_type, &errNum); } if((errNum != WLZ_ERR_NONE) || (values.v = WlzNewValueTb(obj, type, backg, &errNum)) == NULL ){ WlzFreeObj( obj ); AlcFree((void *) gwsp); AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return NULL; } obj->values = WlzAssignValues(values, &errNum); if(errNum != WLZ_ERR_NONE) { WlzFreeObj( obj ); AlcFree((void *) gwsp); AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return NULL; } /* * fill the grey table with mean of grey values. */ /* initialise the work-spaces and check pixel type */ errNum = WlzInitGreyScan(obj, &niwsp, &ngwsp); iwsp = biwsp; for (i=0; (i < n) && (errNum == WLZ_ERR_NONE); i++) { errNum = WlzInitGreyScan(objs[i], iwsp, &gwsp[i]); if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(iwsp++); } if( gwsp[i].pixeltype != grey_type ){ errNum = WLZ_ERR_GREY_TYPE; } } if(errNum != WLZ_ERR_NONE) { WlzFreeObj( obj ); AlcFree((void *) gwsp); AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return NULL; } while (WlzNextGreyInterval(&niwsp) == WLZ_ERR_NONE) { l = niwsp.linpos; greyptr = ngwsp.u_grintptr; switch( ngwsp.pixeltype ){ case WLZ_GREY_INT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.inv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.inv += *(gwsp[i].u_grintptr.inp + k - iwsp->lftpos); } *greyptr.inp = gv.inv / n; greyptr.inp++; } break; case WLZ_GREY_SHORT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.shv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.shv += *(gwsp[i].u_grintptr.shp + k - iwsp->lftpos); } *greyptr.shp = (short )(gv.shv / n); greyptr.shp++; } break; case WLZ_GREY_UBYTE: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.ubv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.ubv += *(gwsp[i].u_grintptr.ubp + k - iwsp->lftpos); } *greyptr.ubp = (WlzUByte )(gv.ubv / n); greyptr.ubp++; } break; case WLZ_GREY_FLOAT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.flv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.flv += *(gwsp[i].u_grintptr.flp + k - iwsp->lftpos); } *greyptr.flp = gv.flv / n; greyptr.flp++; } break; case WLZ_GREY_DOUBLE: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.dbv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.dbv += *(gwsp[i].u_grintptr.dbp + k - iwsp->lftpos); } *greyptr.dbp = gv.dbv / n; greyptr.dbp++; } break; case WLZ_GREY_RGBA: /* RGBA to be done again RAB */ for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { gv.rgbv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while(iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ (void )WlzNextGreyInterval(iwsp); } gv.rgbv += *(gwsp[i].u_grintptr.rgbp + k - iwsp->lftpos); } *greyptr.rgbp = gv.rgbv / n; greyptr.rgbp++; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } AlcFree((void *) gwsp); } AlcFree((void *) biwsp); if(dstErr) { *dstErr = errNum; } return obj; }
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); }
/*! * \ingroup WlzValuesFilters * \brief Perform 2D seperable transform on a 2D grey-level image. * It is the users responsibility to ensure that the grey-value * types are appropriate. * Now extended to include compound objects. * * \return Pointer to transformed object * \param obj Input object pointer * \param x_fun Convolution function to be applied in the x-direction (along the rows). * \param x_params Parameter pointer to be passed to the x-function. * \param y_fun Convolution function to be applied in the y-direction (down the columns). * \param y_params Parameter pointer to be passed to the y-function. * \param dstErr error return. * \par Source: * WlzSepTrans.c */ WlzObject *WlzSepTrans( WlzObject *obj, WlzIntervalConvFunc x_fun, void *x_params, WlzIntervalConvFunc y_fun, void *y_params, WlzErrorNum *dstErr) { WlzIntervalWSpace iwspace; WlzGreyWSpace gwspace; WlzSepTransWSpace stwspc; WlzValues values; WlzObject *obj1, *obj2; int i, width, height; WlzCompoundArray *cobj1, *cobj2; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object pointers and type */ obj2 = NULL; stwspc.outbuf.p.dbp = NULL; if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: /* check domain and valuetable */ if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; break; } if(WlzGreyTableIsTiled(obj->values.core->type)){ errNum = WLZ_ERR_VALUES_TYPE; break; } break; default: case WLZ_3D_DOMAINOBJ: errNum = WLZ_ERR_OBJECT_TYPE; break; case WLZ_TRANS_OBJ: if((obj1 = WlzSepTrans(obj->values.obj, x_fun, x_params, y_fun, y_params, &errNum)) != NULL){ values.obj = obj1; return WlzMakeMain(obj->type, obj->domain, values, NULL, obj, dstErr); } break; case WLZ_COMPOUND_ARR_1: case WLZ_COMPOUND_ARR_2: cobj1 = (WlzCompoundArray *) obj; if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL, cobj1->otype, &errNum)) != NULL){ /* transform each object, ignore type errors */ for(i=0; i < cobj1->n; i++){ cobj2->o[i] = WlzAssignObject(WlzSepTrans(cobj1->o[i], x_fun, x_params, y_fun, y_params, &errNum), NULL); } return (WlzObject *) cobj2; } break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); } } /* make space for a calculation buffer - assume worst case of doubles */ if( errNum == WLZ_ERR_NONE ){ width = obj->domain.i->lastkl - obj->domain.i->kol1 + 1; height = obj->domain.i->lastln - obj->domain.i->line1 + 1; stwspc.inbuf.type = WlzGreyTableTypeToGreyType(obj->values.core->type, NULL); stwspc.bckgrnd = WlzGetBackground(obj, NULL); switch( stwspc.inbuf.type ){ case WLZ_GREY_INT: case WLZ_GREY_SHORT: case WLZ_GREY_UBYTE: stwspc.outbuf.type = WLZ_GREY_INT; break; default: stwspc.outbuf.type = stwspc.inbuf.type; break; } if( (stwspc.outbuf.p.dbp = (double *) AlcMalloc(sizeof(double)*(width>height?width:height))) == NULL){ errNum = WLZ_ERR_MEM_ALLOC; } } /* tranpose the object - interchange x & y coordinates */ if( errNum == WLZ_ERR_NONE ){ obj1 = WlzTransposeObj(obj, &errNum); } /* perform the y convolution */ if((errNum == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(obj1, &iwspace, &gwspace)) == WLZ_ERR_NONE)) { while( (errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE ){ stwspc.inbuf.p.inp = gwspace.u_grintptr.inp; stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1; if((errNum = (*y_fun)(&stwspc, y_params)) == WLZ_ERR_NONE){ switch( stwspc.inbuf.type ){ case WLZ_GREY_INT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++) *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i]; break; case WLZ_GREY_SHORT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++) *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]); break; case WLZ_GREY_UBYTE: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++) *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]); break; case WLZ_GREY_FLOAT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++) *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i]; break; case WLZ_GREY_DOUBLE: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++) *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i]; break; case WLZ_GREY_RGBA: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++) *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i]; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } else { break; /* break from the while loop */ } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } /* rotate back and free temporary object */ if( errNum == WLZ_ERR_NONE ){ obj2 = WlzTransposeObj(obj1, &errNum); WlzFreeObj(obj1); } /* perform x convolution */ if((errNum == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(obj2, &iwspace, &gwspace)) == WLZ_ERR_NONE)) { while((errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE){ stwspc.inbuf.p.inp = gwspace.u_grintptr.inp; stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1; if( (errNum = (*x_fun)(&stwspc, x_params)) == WLZ_ERR_NONE ){ switch( gwspace.pixeltype ){ case WLZ_GREY_INT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++) *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i]; break; case WLZ_GREY_SHORT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++) *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]); break; case WLZ_GREY_UBYTE: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++) *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]); break; case WLZ_GREY_FLOAT: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++) *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i]; break; case WLZ_GREY_DOUBLE: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++) *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i]; break; case WLZ_GREY_RGBA: for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++) *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i]; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } else { break; /* break from the while loop */ } } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } /* free the buffer and return transformed object */ if( stwspc.outbuf.p.dbp ){ AlcFree((void *) stwspc.outbuf.p.dbp); } if( dstErr ){ *dstErr = errNum; } return obj2; }
/*! * \return New 2D domain object. * \ingroup WlzArithmetic * \brief Computes a new 2D object which shares the domain of the given * object, but which has grey values that are the result of * applying the given function to the grey values of the * given object. * \param sObj Given source domain object with values. * \param fn Scalar function to be applied. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzScalarFn2D(WlzObject *sObj, WlzFnType fn, WlzErrorNum *dstErr) { WlzGreyType sGType, dGType; WlzPixelV sBgd, dBgd; WlzObjectType dVType; WlzObject *dObj = NULL; WlzValues dVal; WlzIntervalWSpace sIWSp, dIWSp; WlzGreyWSpace sGWSp, dGWSp; WlzErrorNum errNum = WLZ_ERR_NONE; sGType = WlzGreyTypeFromObj(sObj, &errNum); if(errNum == WLZ_ERR_NONE) { dGType = WlzScalarFnPromoteGType(fn, sGType, &errNum); } if(errNum == WLZ_ERR_NONE) { dVType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, dGType, &errNum); } if(errNum == WLZ_ERR_NONE) { sBgd = WlzGetBackground(sObj, &errNum); } if(errNum == WLZ_ERR_NONE) { dBgd = WlzScalarFnPixel(sBgd, fn, &errNum); } if(errNum == WLZ_ERR_NONE) { dVal.v = WlzNewValueTb(sObj, dVType, dBgd, &errNum); } if(errNum == WLZ_ERR_NONE) { dObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, sObj->domain, dVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(sObj, &sIWSp, &sGWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(dObj, &dIWSp, &dGWSp); } if(errNum == WLZ_ERR_NONE) { while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&sIWSp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&dIWSp)) == WLZ_ERR_NONE)) { int len; WlzGreyP dGP, sGP; len = sIWSp.rgtpos - sIWSp.lftpos + 1; dGP = dGWSp.u_grintptr; sGP = sGWSp.u_grintptr; WlzValueCopyGreyToGrey(dGP, 0, dGType, sGP, 0, sGType, len); WlzScalarFnItv(dGP, dGType, len, fn); } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } if(dstErr) { *dstErr = errNum; } return(dObj); }
/*! * \return New Woolz object. * \ingroup WlzAllocation * \brief Creates a new or adds to an existing 3D spatial domain * object using a rectangular buffer of values to a single * plane of the given current object (which may be NULL or * empty if the object is to be created). * The returned object will share domains and values of * planes other than the given plane with the current object. * \param cObj Given current object. * \param og Origin of rectangular buffer. * \param sz Buffer size (note 2D). * \param gType Grey type which must be consistent * with the current object (if it is * valid) and the buffer of values. * \param bufSz Number of values in the buffer * (ie sz.vtX * sz.vtY). * \param bufP Given buffer of values. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzBuildObj3(WlzObject *cObj, WlzIVertex3 og, WlzIVertex2 sz, WlzGreyType gType, int bufSz, WlzGreyP bufP, WlzErrorNum *dstErr) { int nPlnReq = 1; WlzDomain cDom, nDom; WlzValues cVal, nVal; WlzObject *nObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; cDom.core = NULL; nDom.core = NULL; cVal.core = NULL; nVal.core = NULL; if(cObj) { WlzGreyType cGType = WLZ_GREY_ERROR;; switch(cObj->type) { case WLZ_EMPTY_OBJ: cObj = NULL; break; case WLZ_3D_DOMAINOBJ: if(cObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(cObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { cDom = cObj->domain; cVal = cObj->values; cGType = WlzGreyTypeFromObj(cObj, &errNum); } if((errNum == WLZ_ERR_NONE) && (cGType != gType)) { errNum = WLZ_ERR_GREY_TYPE; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Create a new object with new plane domain and voxel values. */ if(errNum == WLZ_ERR_NONE) { WlzIBox3 nBox; WlzPixelV bgdV; float vxSz[3]; nBox.xMin = og.vtX; nBox.yMin = og.vtY; nBox.zMin = og.vtZ; nBox.xMax = og.vtX + sz.vtX - 1; nBox.yMax = og.vtY + sz.vtY - 1; nBox.zMax = og.vtZ; if(cObj) { nPlnReq = (og.vtZ < cDom.p->plane1) || (og.vtZ > cDom.p->lastpl) || ((*(cDom.p->domains + og.vtZ - cDom.p->plane1)).core == NULL); nBox.xMin = ALG_MIN(nBox.xMin, cDom.p->kol1); nBox.yMin = ALG_MIN(nBox.yMin, cDom.p->line1); nBox.zMin = ALG_MIN(nBox.zMin, cDom.p->plane1); nBox.xMax = ALG_MAX(nBox.xMax, cDom.p->lastkl); nBox.yMax = ALG_MAX(nBox.yMax, cDom.p->lastln); nBox.zMax = ALG_MAX(nBox.zMax, cDom.p->lastpl); vxSz[0] = cDom.p->voxel_size[0]; vxSz[1] = cDom.p->voxel_size[1]; vxSz[2] = cDom.p->voxel_size[2]; bgdV = WlzGetBackground(cObj, &errNum); } else { vxSz[0] = vxSz[1] = vxSz[2] = 1.0f; bgdV.type = WLZ_GREY_INT; bgdV.v.inv = 0; } if(errNum == WLZ_ERR_NONE) { nDom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, nBox.zMin, nBox.zMax, nBox.yMin, nBox.yMax, nBox.xMin, nBox.xMax, &errNum); } if(errNum == WLZ_ERR_NONE) { nVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, nBox.zMin, nBox.zMax, bgdV, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { nDom.p->voxel_size[0] = vxSz[0]; nDom.p->voxel_size[1] = vxSz[1]; nDom.p->voxel_size[2] = vxSz[2]; nObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, nDom, nVal, NULL, NULL, &errNum); } } /* Set the domain and values on each plane for the new object. */ if(errNum == WLZ_ERR_NONE) { int idZ; for(idZ = nDom.p->plane1; idZ <= nDom.p->lastpl; ++idZ) { int idP; WlzDomain nDom2; WlzValues nVal2; nDom2.core = NULL; nVal2.core = NULL; idP = idZ - nDom.p->plane1; if(idZ == og.vtZ) { /* Plane with buffer. */ WlzIVertex2 og2, sz2; WlzObject *cObj2 = NULL, *nObj2 = NULL; og2.vtX = og.vtX; og2.vtY = og.vtY; sz2.vtX = sz.vtX; sz2.vtY = sz.vtY; if(nPlnReq == 0) { int idP; idP = idZ - cDom.p->plane1; cObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(cDom.p->domains + idP), *(cVal.vox->values + idP), NULL, NULL, &errNum); } nObj2 = WlzBuildObj2(cObj2, og2, sz2, gType, bufSz, bufP, &errNum); if(errNum == WLZ_ERR_NONE) { nDom2 = WlzAssignDomain(nObj2->domain, NULL); nVal2 = WlzAssignValues(nObj2->values, NULL); } (void )WlzFreeObj(cObj2); (void )WlzFreeObj(nObj2); } else if((idZ >= cDom.p->plane1) && (idZ <= cDom.p->lastpl)) { /* Not buffer plane, but previously existing plane. */ int idQ; idQ = idZ - cDom.p->plane1; nDom2 = WlzAssignDomain(*(cDom.p->domains + idQ), NULL); nVal2 = WlzAssignValues(*(cVal.vox->values + idQ), NULL); } if(errNum == WLZ_ERR_NONE) { *(nDom.p->domains + idP) = nDom2; *(nVal.vox->values + idP) = nVal2; } else { break; } } } if(dstErr) { *dstErr = errNum; } return(nObj); }
/*! * \return New 3D domain object. * \ingroup WlzArithmetic * \brief Computes a new 3D object which shares the domain of the given * object, but which has grey values that are the result of * applying the given function to the grey values of the * given object. * \param sObj Given source domain object with values. * \param fn Scalar function to be applied. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzScalarFn3D(WlzObject *sObj, WlzFnType fn, WlzErrorNum *dstErr) { int idx, off; WlzPixelV sBgd, dBgd; WlzValues dVal; WlzObject *sObj2D, *dObj2D, *dObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if(errNum == WLZ_ERR_NONE) { sBgd = WlzGetBackground(sObj, &errNum); } if(errNum == WLZ_ERR_NONE) { dBgd = WlzScalarFnPixel(sBgd, fn, &errNum); } if(errNum == WLZ_ERR_NONE) { dVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, sObj->domain.p->plane1, sObj->domain.p->lastpl, dBgd, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { for(idx = sObj->domain.p->plane1; idx <= sObj->domain.p->lastpl; ++idx) { off = idx - sObj->domain.p->plane1; dObj2D = NULL; sObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(sObj->domain.p->domains + off), *(sObj->values.vox->values + off), NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { dObj2D = WlzScalarFn2D(sObj2D, fn, &errNum); } WlzFreeObj(sObj2D); if(errNum == WLZ_ERR_NONE) { *(dVal.vox->values + off) = WlzAssignValues(dObj2D->values, NULL); } WlzFreeObj(dObj2D); } } if(errNum == WLZ_ERR_NONE) { dObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, sObj->domain, dVal, NULL, NULL, &errNum); } if(dstErr) { *dstErr = errNum; } return(dObj); }
/*! * \return Rescaled object. * \ingroup WlzTransform * \brief Rescales the given 2D domain object using an integer scale. * \param obj Given object. * \param scale Integer scale factor. * \param expand If zero use \f$\frac{1}{scale}\f$. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzIntRescaleObj2D( WlzObject *obj, int scale, int expand, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzDomain domain; WlzValues values; WlzInterval *intvls; int k1, kl, l1, ll, l, num_intvls; WlzErrorNum errNum=WLZ_ERR_NONE; /* check expand or contract */ if( expand ) { k1 = obj->domain.i->kol1 * scale; kl = obj->domain.i->lastkl * scale + scale - 1; l1 = obj->domain.i->line1 * scale; ll = obj->domain.i->lastln * scale + scale - 1; } else { k1 = obj->domain.i->kol1 / scale; kl = obj->domain.i->lastkl / scale; l1 = obj->domain.i->line1 / scale; ll = obj->domain.i->lastln / scale; } /* create a new object */ if((domain.i = WlzMakeIntervalDomain(obj->domain.i->type, l1, ll, k1, kl, &errNum)) != NULL){ values.core = NULL; rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL, NULL); } /* fill in the intervals */ if( errNum == WLZ_ERR_NONE){ if( domain.i->type == WLZ_INTERVALDOMAIN_INTVL ) { int intvline_offset, max_offset; WlzIntervalLine *intvline; num_intvls = WlzIntervalCount(obj->domain.i, NULL); num_intvls = expand ? num_intvls * scale : num_intvls; intvls = (WlzInterval *)AlcMalloc(sizeof(WlzInterval) * num_intvls); domain.i->freeptr = AlcFreeStackPush(domain.i->freeptr, (void *)intvls, NULL); max_offset = obj->domain.i->lastln - obj->domain.i->line1; for(l=l1; l <= ll; l++) { int i; intvline_offset = (expand?l/scale:l*scale) - obj->domain.i->line1; intvline_offset = WLZ_MAX(intvline_offset, 0); intvline_offset = WLZ_MIN(intvline_offset, max_offset); intvline = obj->domain.i->intvlines + intvline_offset; for(i=0; i < intvline->nintvs; i++) { intvls[i].ileft = (intvline->intvs + i)->ileft; intvls[i].iright = (intvline->intvs + i)->iright; if( expand ) { intvls[i].ileft *= scale; intvls[i].iright *= scale; intvls[i].iright += scale - 1; } else { intvls[i].ileft /= scale; intvls[i].iright /= scale; } } i = check_intvs(intvls, i); WlzMakeInterval(l, domain.i, i, intvls); intvls += i; } (void) WlzStandardIntervalDomain( domain.i ); } } /* create the valuetable */ if( (errNum == WLZ_ERR_NONE) && obj->values.core ) { WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzPixelV backgrnd; WlzGreyValueWSpace *gVWSp = NULL; WlzGreyType gtype; backgrnd = WlzGetBackground(obj, NULL); if((values.v = WlzNewValueTb(rtnObj, obj->values.v->type, backgrnd, &errNum)) != NULL){ rtnObj->values = WlzAssignValues(values, NULL); /* fill in the grey-values */ errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { gVWSp = WlzGreyValueMakeWSp(obj, &errNum); if(errNum == WLZ_ERR_NONE) { gtype = WlzGreyTableTypeToGreyType(obj->values.v->type, NULL); } while((errNum == WLZ_ERR_NONE) && (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE) { int k; int lp = expand ? iwsp.linpos/scale : iwsp.linpos*scale; for( k=0; k <= (iwsp.rgtpos - iwsp.lftpos); k++ ) { int kp = expand ? (k+iwsp.lftpos)/scale : (k+iwsp.lftpos)*scale; WlzGreyValueGet(gVWSp, 0, (double) lp, (double) kp); switch(gtype) { case WLZ_GREY_INT: gwsp.u_grintptr.inp[k] = (*(gVWSp->gVal)).inv; break; case WLZ_GREY_SHORT: gwsp.u_grintptr.shp[k] = (*(gVWSp->gVal)).shv; break; case WLZ_GREY_UBYTE: gwsp.u_grintptr.ubp[k] = (*(gVWSp->gVal)).ubv; break; case WLZ_GREY_FLOAT: gwsp.u_grintptr.flp[k] = (*(gVWSp->gVal)).flv; break; case WLZ_GREY_DOUBLE: gwsp.u_grintptr.dbp[k] = (*(gVWSp->gVal)).dbv; break; case WLZ_GREY_RGBA: gwsp.u_grintptr.rgbp[k] = (*(gVWSp->gVal)).rgbv; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } WlzGreyValueFreeWSp(gVWSp); (void )WlzEndGreyScan(&iwsp, &gwsp); } } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \ingroup WlzBinaryOps * \brief Calculate the set union of an array of domain objects. Domians only unless uvt non-zero in which case make an average grey table. Note background values are used in the averaging process. All objects must be domain objects of the same type (2D or 3D) unless WLZ_EMPTY_OBJ, NULL input objects are an error. This function may modify the order of the objects in the array it is passed if the array contains empty objects. * * \return Union of the array of object. * \param n number of input objects * \param objs input object array * \param uvt grey-table copy flag, copy if non-zero. * \param dstErr error return. * \par Source: * WlzUnionN.c */ WlzObject *WlzUnionN( int n, WlzObject **objs, int uvt, WlzErrorNum *dstErr) { WlzObject *obj=NULL; WlzDomain domain; WlzValues values; WlzIntervalDomain *idom; WlzInterval *itvl, *jtvl; WlzIntervalWSpace *iwsp; WlzIntervalWSpace *biwsp, *tiwsp, niwsp; WlzGreyWSpace *gwsp, ngwsp; WlzObjectType type; int i, j, k, l; int inttot, numactive, change, lwas, nints, noverlap; WlzPixelV backg; int line1, lastln; int kol1,lastkl; WlzGreyV gv; WlzGreyP greyptr; int **locbuff; int *locbuffs; int span; WlzErrorNum errNum=WLZ_ERR_NONE; /* preliminary stuff - count of non-NULL objects, note WLZ_EMPTY_OBJs are ignored but NULL objects are an error */ if( n < 1 ){ errNum = WLZ_ERR_PARAM_DATA; } else { for (i=0; i<n ; i++ ){ if ( objs[i] == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; break; } if( objs[i]->type == WLZ_EMPTY_OBJ ){ obj = objs[i]; for ( j=i; j<n-1 ; j++ ){ objs[j] = objs[j+1]; } objs[n-1] = obj; n--; i--; } } } /* n has been checked therefore no objects implies all empty */ if( (errNum == WLZ_ERR_NONE) && (n < 1) ){ return WlzMakeEmpty(dstErr); } /* now check they are all of the same type */ if( errNum == WLZ_ERR_NONE ){ for(i=1; i < n; i++){ if( objs[i]->type != objs[0]->type ){ errNum = WLZ_ERR_OBJECT_TYPE; break; } } } /* now test the type note empty objects have been discarded */ if( errNum == WLZ_ERR_NONE ){ switch( objs[0]->type ){ case WLZ_2D_DOMAINOBJ: break; case WLZ_3D_DOMAINOBJ: return WlzUnion3d(n, objs, uvt, dstErr); case WLZ_TRANS_OBJ: default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* now discard empty objects */ if( errNum == WLZ_ERR_NONE ){ for (i=0; i<n ; i++ ){ if( WlzIsEmpty(objs[i], NULL) ){ obj = objs[i]; for ( j=i; j<n-1 ; j++ ){ objs[j] = objs[j+1]; } objs[n-1] = obj; n--; i--; } } } obj = NULL; /* recheck number of objects */ if( (errNum == WLZ_ERR_NONE) && (n < 1) ){ return WlzMakeEmpty(dstErr); } if( (errNum == WLZ_ERR_NONE) && (n == 1) ){ return WlzMakeMain(objs[0]->type, objs[0]->domain, objs[0]->values, NULL, NULL, dstErr); } /* check if grey-value merge is possible */ if( errNum == WLZ_ERR_NONE ){ for (i=0; i<n ; i++ ){ if( objs[i]->values.core == NULL ){ uvt = 0; break; } } } /* * find the line and column bounds of the union. */ if( errNum == WLZ_ERR_NONE ){ line1 = objs[0]->domain.i->line1; lastln = objs[0]->domain.i->lastln; kol1 = objs[0]->domain.i->kol1; lastkl = objs[0]->domain.i->lastkl; for (i=1; i<n; i++) { idom = objs[i]->domain.i; if (line1 > idom->line1) line1 = idom->line1; if (lastln < idom->lastln) lastln = idom->lastln; if (kol1 > idom->kol1) kol1 = idom->kol1; if (lastkl < idom->lastkl) lastkl = idom->lastkl; } span = lastkl - kol1 +1 ; if( (locbuff = (int **) AlcMalloc((n+1)*sizeof(int *))) == NULL ){ errNum = WLZ_ERR_MEM_ALLOC; } } /* space must be allocated for the largest variety of grey-value */ if( errNum == WLZ_ERR_NONE ){ if( (locbuffs = (int *) AlcMalloc(sizeof(double)*span*(n+1))) == NULL ){ AlcFree((void *) locbuff); errNum = WLZ_ERR_MEM_ALLOC; } else { for(i=0; i <= n; i++){ locbuff[i] = locbuffs + i*span; } } } /* * count the individual intervals so that sufficient space * for the union may be allocated. */ if( errNum == WLZ_ERR_NONE ){ inttot=0; for(i=0; i < n; i++){ inttot += WlzIntervalCount(objs[i]->domain.i, &errNum); } } /* * set up domain, value table structures, and object. */ if( errNum == WLZ_ERR_NONE ){ if( (idom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL, line1,lastln,kol1,lastkl, &errNum)) == NULL ){ AlcFree((void *) locbuffs); AlcFree((void *) locbuff); } else if( (itvl = (WlzInterval *) AlcMalloc(inttot * sizeof(WlzInterval))) == NULL){ AlcFree((void *) locbuffs); AlcFree((void *) locbuff); WlzFreeIntervalDomain(idom); errNum = WLZ_ERR_MEM_ALLOC; } else { idom->freeptr = AlcFreeStackPush(idom->freeptr, (void *)itvl, NULL); lwas = line1; jtvl = itvl; nints = 0; domain.i = idom; values.v = NULL; if( (obj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL, &errNum)) == NULL ){ WlzFreeIntervalDomain( idom ); AlcFree((void *) locbuffs); AlcFree((void *) locbuff); return(NULL); } } } /* * allocate space for workspaces */ if( errNum == WLZ_ERR_NONE ){ if( (iwsp = (WlzIntervalWSpace *) AlcMalloc (n * sizeof (WlzIntervalWSpace))) == NULL ){ WlzFreeObj( obj ); AlcFree((void *) locbuffs); AlcFree((void *) locbuff); errNum = WLZ_ERR_MEM_ALLOC; obj = NULL; } else { biwsp = iwsp; tiwsp = iwsp + n; } } /* * Construct the union object's table of intervals. * Initialise scanning on each object/workspace combination. * Scan synchronously, setting up the union of adjacent and * overlapping intervals. Needs a clear head !! */ if( errNum == WLZ_ERR_NONE ){ for (i=0; i<n; i++) { WlzInitRasterScan(objs[i], iwsp, WLZ_RASTERDIR_ILIC); WlzNextInterval(iwsp++); } numactive = n; /* * find next line and left hand end of next interval of union */ while (numactive > 0) { /* * find first remaining active object */ iwsp = biwsp; while( iwsp->linrmn < 0 ){ iwsp++; } /* * find minimum line number of remaining active intervals */ l = iwsp->linpos; kol1 = iwsp->lftpos; lastkl = iwsp->rgtpos; for (iwsp++; iwsp<tiwsp; iwsp++) if (iwsp->linrmn >= 0 && iwsp->linpos < l) { l = iwsp->linpos; kol1 = iwsp->lftpos; lastkl = iwsp->rgtpos; } /* * find left-most interval in this line */ for (iwsp=biwsp; iwsp<tiwsp; iwsp++) if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos < kol1) { kol1 = iwsp->lftpos; lastkl = iwsp->rgtpos; } /* * construct maximal interval with current left end-point */ do { change = 0; for (iwsp=biwsp; iwsp<tiwsp; iwsp++) { while( iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= lastkl+1 ){ if (iwsp->rgtpos > lastkl) { lastkl = iwsp->rgtpos; change = 1; } if (WlzNextInterval(iwsp) != WLZ_ERR_NONE) { numactive--; } } } } while (change == 1); itvl->ileft = kol1 - idom->kol1; itvl->iright = lastkl - idom->kol1; if (l == lwas) nints++; else { (void) WlzMakeInterval(lwas,idom,nints,jtvl); for (j = lwas+1; j<l; j++) { (void) WlzMakeInterval(j,idom,0,NULL); } lwas = l; nints = 1; jtvl = itvl; } itvl++; } (void) WlzMakeInterval(lwas,idom,nints,jtvl); for (j = lwas+1; j<=lastln; j++) { (void) WlzMakeInterval(j,idom,0,NULL); } } /* now deal with the grey-values if required */ if( (errNum == WLZ_ERR_NONE) && (uvt != 0) ){ WlzGreyType grey_type; if( (gwsp = (WlzGreyWSpace *) AlcMalloc (n * sizeof (WlzGreyWSpace))) == NULL){ WlzFreeObj( obj ); AlcFree((void *) locbuffs); AlcFree((void *) locbuff); AlcFree((void *) biwsp); errNum = WLZ_ERR_MEM_ALLOC; obj = NULL; } /* construct an empty "ragged-rectangle" greytable with appropriate grey-type */ if( errNum == WLZ_ERR_NONE ){ backg = WlzGetBackground(objs[0], NULL); grey_type = WlzGreyTableTypeToGreyType(objs[0]->values.core->type, NULL); type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, grey_type, NULL); if( (values.v = WlzNewValueTb(obj, type, backg, &errNum)) == NULL ){ WlzFreeObj( obj ); AlcFree((void *) locbuffs); AlcFree((void *) locbuff); AlcFree((void *) biwsp); obj = NULL; } else { obj->values = WlzAssignValues(values, NULL); } } /* fill the grey table. Where more than one input objects overlap, take mean of grey values. */ if( errNum == WLZ_ERR_NONE ){ WlzInitGreyScan(obj, &niwsp, &ngwsp); iwsp = biwsp; for (i=0; i<n; i++) { WlzInitGreyScan(objs[i], iwsp, &gwsp[i]); WlzNextGreyInterval(iwsp++); if( gwsp[i].pixeltype != grey_type ){ AlcFree((void *) gwsp); AlcFree((void *) locbuffs); AlcFree((void *) locbuff); AlcFree((void *) biwsp); WlzFreeObj( obj ); obj = NULL; errNum = WLZ_ERR_GREY_TYPE; } } } if( errNum == WLZ_ERR_NONE ){ while (WlzNextGreyInterval(&niwsp) == WLZ_ERR_NONE) { l = niwsp.linpos; greyptr = ngwsp.u_grintptr; switch( ngwsp.pixeltype ){ case WLZ_GREY_INT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.inv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.inv += *(gwsp[i].u_grintptr.inp + k - iwsp->lftpos); } } *greyptr.inp = gv.inv / noverlap; greyptr.inp++; } break; case WLZ_GREY_SHORT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.shv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.shv += *(gwsp[i].u_grintptr.shp + k - iwsp->lftpos); } } *greyptr.shp = (short )(gv.shv / noverlap); greyptr.shp++; } break; case WLZ_GREY_UBYTE: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.inv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.inv += *(gwsp[i].u_grintptr.ubp + k - iwsp->lftpos); } } *greyptr.ubp = (WlzUByte )(gv.inv / noverlap); greyptr.ubp++; } break; case WLZ_GREY_FLOAT: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.flv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.flv += *(gwsp[i].u_grintptr.flp + k - iwsp->lftpos); } } *greyptr.flp = gv.flv / noverlap; greyptr.flp++; } break; case WLZ_GREY_DOUBLE: for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.dbv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.dbv += *(gwsp[i].u_grintptr.dbp + k - iwsp->lftpos); } } *greyptr.dbp = gv.dbv / noverlap; greyptr.dbp++; } break; case WLZ_GREY_RGBA: /* RGBA to be done - do properly RAB */ for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) { noverlap = 0; gv.rgbv = 0; for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) { while (iwsp->linrmn >= 0 && (iwsp->linpos < l || (iwsp->linpos == l && iwsp->rgtpos < k))){ WlzNextGreyInterval(iwsp); } if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos <= k) { noverlap++; gv.rgbv += *(gwsp[i].u_grintptr.rgbp + k - iwsp->lftpos); } } *greyptr.rgbp = gv.rgbv / noverlap; greyptr.rgbp++; } break; default: break; } } } AlcFree((void *) gwsp); } if( errNum == WLZ_ERR_NONE ){ AlcFree( (void *) biwsp); AlcFree( (void *)locbuff ); AlcFree( (void *)locbuffs ); } if( dstErr ){ *dstErr = errNum; } return( obj ); }
/*! * \return Transformed object. * \ingroup WlzTransform * \brief Transform an object using the given view-transform. * Typically this is for mapping section data back into * the 3D space of the reference image/reconstruction. * \param srcObj Given source object. * \param viewStr Given view transform. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *Wlz3DViewTransformObj( WlzObject *srcObj, WlzThreeDViewStruct *viewStr, WlzErrorNum *dstErr) { WlzErrorNum errNum=WLZ_ERR_NONE; AlcErrno alcErr = ALC_ER_NONE; WlzObject *dstObj=NULL; int area; int i, k, p, xp, yp, line; int plane1, lastpl, line1, lastln, kol1, lastkl; WlzIVertex3 *vertices; int numVtxs, vtxIdx; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzDomain domain, tmpDomain; WlzValues values; int numInts, itvlFlg; WlzInterval *itvl; /* check the object */ if( srcObj == NULL ) { errNum = WLZ_ERR_OBJECT_NULL; } else { switch( srcObj->type ) { case WLZ_2D_DOMAINOBJ: if( srcObj->domain.core == NULL ) { errNum = WLZ_ERR_DOMAIN_NULL; } area = WlzArea(srcObj, &errNum); if( area == 0 ) { dstObj = WlzMakeEmpty(&errNum); } break; case WLZ_2D_POLYGON: /* to be done at some time to 3D polyline */ case WLZ_BOUNDLIST: /* convert to 3D polylines */ case WLZ_TRANS_OBJ: errNum = WLZ_ERR_OBJECT_TYPE; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* create the voxel list */ if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) { numVtxs = sizeof(WlzIVertex3) * (area+4); vertices = AlcMalloc(sizeof(WlzIVertex3) * (area+4)); numVtxs = 0; if( vertices ) { errNum = WlzInitRasterScan(srcObj, &iwsp, WLZ_RASTERDIR_ILIC); } else { errNum = WLZ_ERR_MEM_ALLOC; } if( errNum == WLZ_ERR_NONE ) { while( (errNum = WlzNextInterval(&iwsp)) == WLZ_ERR_NONE ) { float x, y, z; if((iwsp.linpos < (int) viewStr->minvals.vtY) || (iwsp.linpos > (int) viewStr->maxvals.vtY)) { continue; } yp = iwsp.linpos - (int) viewStr->minvals.vtY; for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++) { if((k < (int) viewStr->minvals.vtX) || (k > (int) viewStr->maxvals.vtX)) { continue; } xp = k - (int) viewStr->minvals.vtX; x = (float )(viewStr->xp_to_x[xp] + viewStr->yp_to_x[yp]); y = (float )(viewStr->xp_to_y[xp] + viewStr->yp_to_y[yp]); z = (float )(viewStr->xp_to_z[xp] + viewStr->yp_to_z[yp]); vertices[numVtxs].vtX = WLZ_NINT(x); vertices[numVtxs].vtY = WLZ_NINT(y); vertices[numVtxs].vtZ = WLZ_NINT(z); numVtxs++; } } if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */ { errNum = WLZ_ERR_NONE; } } } /* sort wrt planes, lines, kols */ if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) { qsort((void *) vertices, (size_t) numVtxs, sizeof(WlzIVertex3), compareVtxVal); /* create planedomain */ plane1 = vertices[0].vtZ; lastpl = vertices[numVtxs - 1].vtZ; line1 = vertices[0].vtY; lastln = line1; kol1 = vertices[0].vtX; lastkl = kol1; for(i=1; i < numVtxs; i++) { if( kol1 > vertices[i].vtX ) { kol1 = vertices[i].vtX; } if( lastkl < vertices[i].vtX ) { lastkl = vertices[i].vtX; } if( line1 > vertices[i].vtY ) { line1 = vertices[i].vtY; } if( lastln < vertices[i].vtY ) { lastln = vertices[i].vtY; } } if( (domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, plane1, lastpl, line1, lastln, kol1, lastkl, &errNum)) == NULL ) { AlcFree((void *) vertices); } } /* for each plane count intervals and make domain */ if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) { vtxIdx = 0; for(p=plane1; p <= lastpl; p++) { /* increment vertex index to current plane */ while( vertices[vtxIdx].vtZ < p ) { vtxIdx++; } /* check for empty domain */ if( vertices[vtxIdx].vtZ > p ) { domain.p->domains[p - plane1].i = NULL; continue; } /* estimate intervals - foreach pixel add one, foreach adjacent pixel on the same line subtract one */ numInts = 1; kol1 = vertices[vtxIdx].vtX; lastkl = kol1; for(i=vtxIdx+1; i < numVtxs; i++) { if( vertices[i].vtZ > p ) { break; } numInts++; if((vertices[i].vtY == vertices[i-1].vtY) && ((vertices[i].vtX == (vertices[i-1].vtX)) || (vertices[i].vtX == (vertices[i-1].vtX + 1)) )) { numInts--; } if(kol1 > vertices[i].vtX) { kol1 = vertices[i].vtX; } if(lastkl < vertices[i].vtX) { lastkl = vertices[i].vtX; } } line1 = vertices[vtxIdx].vtY; lastln = vertices[i-1].vtY; /* make the domain and add the intervals pointer */ tmpDomain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL, line1, lastln, kol1, lastkl, &errNum); itvl = (WlzInterval *) AlcMalloc(sizeof(WlzInterval)*numInts); tmpDomain.i->freeptr = AlcFreeStackPush(tmpDomain.i->freeptr, (void *) itvl, &alcErr); if(alcErr != ALC_ER_NONE) { errNum = WLZ_ERR_MEM_ALLOC; } /* one more loop to add the intervals */ itvl->ileft = vertices[vtxIdx].vtX - kol1; line = vertices[vtxIdx].vtY; itvlFlg = 1; /* interval started */ numInts = 1; for(i=vtxIdx+1; i < numVtxs; i++) { /* new plane -> interval finished if started */ if( vertices[i].vtZ > p ) { if( itvlFlg ) { itvl[numInts-1].iright = vertices[i-1].vtX - kol1; WlzMakeInterval(line, tmpDomain.i, numInts, itvl); itvl += numInts; itvlFlg = 0; /* interval finished */ numInts = 0; } break; } /* check if new interval */ if( !itvlFlg ) { itvl->ileft = vertices[i].vtX - kol1; line = vertices[i].vtY; itvlFlg = 1; numInts = 1; continue; /* no further tests */ } /* check for gap - increment interval count */ if((vertices[i].vtY == line) && ((vertices[i].vtX - vertices[i-1].vtX) > 1)) { itvl[numInts-1].iright = vertices[i-1].vtX - kol1; numInts++; itvl[numInts-1].ileft = vertices[i].vtX - kol1; itvlFlg = 1; } /* check for new-line */ if( line < vertices[i].vtY ) { itvl[numInts-1].iright = vertices[i-1].vtX - kol1; WlzMakeInterval(line, tmpDomain.i, numInts, itvl); itvl += numInts; itvl->ileft = vertices[i].vtX - kol1; line = vertices[i].vtY; itvlFlg = 1; numInts = 1; } } /* complete the last interval */ if( itvlFlg ) { itvl[numInts-1].iright = vertices[i-1].vtX - kol1; WlzMakeInterval(line, tmpDomain.i, numInts, itvl); itvl += numInts; } /* add the domain to the planedomain */ domain.p->domains[p - plane1] = WlzAssignDomain(tmpDomain, &errNum); (void) WlzIntervalCount(tmpDomain.i, 0); } } /* create the new object */ if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) { values.core = NULL; dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } /* check for grey-level data */ if((errNum == WLZ_ERR_NONE) && dstObj && (dstObj->type != WLZ_EMPTY_OBJ) && srcObj->values.core ) { WlzPixelV bckgrnd; WlzObject *tmpObj; WlzValues tmpValues; WlzDVertex3 vtx; WlzGreyValueWSpace *gVWSp = NULL; WlzObjectType valueTbType; /* explicit intialisation to satisfy strict ANSI on SGI */ bckgrnd = WlzGetBackground(srcObj, &errNum); valueTbType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, bckgrnd.type, NULL); /* make a voxel table */ values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, plane1, lastpl, bckgrnd, NULL, &errNum); dstObj->values = WlzAssignValues(values, &errNum); /* set up grey-value random access to original and loop through planes setting values */ gVWSp = WlzGreyValueMakeWSp(srcObj, NULL); for(p=plane1; p <= lastpl; p++) { /* check for empty domain */ if( domain.p->domains[p-plane1].core == NULL ) { continue; } /* make a value table */ tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain.p->domains[p-plane1], values.vox->values[p-plane1], NULL, NULL, &errNum); tmpValues.v = WlzNewValueTb(tmpObj, valueTbType, bckgrnd, &errNum); values.vox->values[p-plane1] = WlzAssignValues(tmpValues, &errNum); tmpObj->values = WlzAssignValues(tmpValues, &errNum); /* transfer values */ errNum = WlzInitGreyScan(tmpObj, &iwsp, &gwsp); while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)) { for(i=0; i<iwsp.colrmn; i++) { vtx.vtX = iwsp.colpos + i; vtx.vtY = iwsp.linpos; vtx.vtZ = p; Wlz3DSectionTransformVtx(&vtx, viewStr); WlzGreyValueGet(gVWSp, 0.0, WLZ_NINT(vtx.vtY), WLZ_NINT(vtx.vtX)); switch( gwsp.pixeltype ) { case WLZ_GREY_LONG: *(gwsp.u_grintptr.lnp+i) = gVWSp->gVal[0].lnv; break; case WLZ_GREY_INT: *(gwsp.u_grintptr.inp+i) = gVWSp->gVal[0].inv; break; case WLZ_GREY_SHORT: *(gwsp.u_grintptr.shp+i) = gVWSp->gVal[0].shv; break; case WLZ_GREY_UBYTE: *(gwsp.u_grintptr.ubp+i) = gVWSp->gVal[0].ubv; break; case WLZ_GREY_FLOAT: *(gwsp.u_grintptr.flp+i) = gVWSp->gVal[0].flv; break; case WLZ_GREY_DOUBLE: *(gwsp.u_grintptr.dbp+i) = gVWSp->gVal[0].dbv; break; case WLZ_GREY_RGBA: *(gwsp.u_grintptr.rgbp+i) = gVWSp->gVal[0].rgbv; break; case WLZ_GREY_BIT: /* not sure what to do with these */ default: break; } } } if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */ { errNum = WLZ_ERR_NONE; } WlzFreeObj(tmpObj); } WlzGreyValueFreeWSp(gVWSp); } /* clean temp allocation */ if( vertices ) { AlcFree((void *) vertices); } if( dstErr ) { *dstErr = errNum; } return dstObj; }
/*! * \ingroup WlzValuesUtils * \brief * * \return New object with the same domain <tt>tmpl</tt> but values in the intersection with <tt>obj</tt> set to those of the object. Returns NULL on error. * \param obj Input object to which the template is applied * \param tmpl Template object * \param tmplVal Template value for regions in the template not in the original object * \param dstErr Error return. * \par Source: * WlzGreyTemplate.c */ WlzObject *WlzGreyTemplate( WlzObject *obj, WlzObject *tmpl, WlzPixelV tmplVal, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObject *obj1, *obj2; WlzValues values; WlzPixelV bckgrnd; WlzObjectType type; WlzGreyType gtype=WLZ_GREY_UBYTE; WlzIntervalWSpace iwsp1, iwsp2; WlzGreyWSpace gwsp1, gwsp2; int size; 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; } else if( WlzGreyTableIsTiled(obj->values.core->type) ){ errNum = WLZ_ERR_VALUES_TYPE; } else { bckgrnd = WlzGetBackground(obj, &errNum); } if(errNum == WLZ_ERR_NONE) { gtype = WlzGreyTableTypeToGreyType(obj->values.core->type, NULL); } break; case WLZ_3D_DOMAINOBJ: return WlzGreyTemplate3d(obj, tmpl, tmplVal, dstErr); case WLZ_TRANS_OBJ: if((values.obj = WlzGreyTemplate(obj->values.obj, tmpl, tmplVal, &errNum)) != NULL){ return WlzMakeMain(WLZ_TRANS_OBJ, obj->domain, values, NULL, NULL, dstErr); } break; case WLZ_EMPTY_OBJ: bckgrnd.type = WLZ_GREY_UBYTE; bckgrnd.v.ubv = 0; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* check the template */ if( errNum == WLZ_ERR_NONE ){ if( tmpl == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { values.core = NULL; switch( tmpl->type ){ case WLZ_2D_DOMAINOBJ: rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmpl->domain, values, NULL, NULL, &errNum); break; case WLZ_TRANS_OBJ: rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmpl->values.obj->domain, values, NULL, NULL, &errNum); break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); case WLZ_2D_POLYGON: rtnObj = WlzPolyToObj(tmpl->domain.poly, WLZ_SIMPLE_FILL, &errNum); break; case WLZ_BOUNDLIST: rtnObj = WlzBoundToObj(tmpl->domain.b, WLZ_SIMPLE_FILL, &errNum); break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } } /* attach a value table to the template and set to the template value, note the background is set to the input object or zero if empty */ if( errNum == WLZ_ERR_NONE ){ type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gtype, NULL); if((values.v = WlzNewValueTb(rtnObj, type, bckgrnd, &errNum)) != NULL){ rtnObj->values = WlzAssignValues(values, NULL); errNum = WlzGreySetValue(rtnObj, tmplVal); } } /* copy input obj values within the intersection */ if( errNum == WLZ_ERR_NONE ){ if((obj->type != WLZ_EMPTY_OBJ) ){ if( (obj1 = WlzIntersect2(obj, rtnObj, &errNum)) ){ obj1->values = WlzAssignValues(rtnObj->values, NULL); obj2 = WlzMakeMain(obj1->type, obj1->domain, obj->values, NULL, NULL, NULL); errNum = WlzInitGreyScan(obj1, &iwsp1, &gwsp1); errNum = WlzInitGreyScan(obj2, &iwsp2, &gwsp2); switch( gwsp1.pixeltype ){ case WLZ_GREY_INT: size = sizeof(int); break; case WLZ_GREY_SHORT: size = sizeof(short); break; case WLZ_GREY_UBYTE: size = sizeof(WlzUByte); break; case WLZ_GREY_FLOAT: size = sizeof(float); break; case WLZ_GREY_DOUBLE: size = sizeof(double); break; case WLZ_GREY_RGBA: size = sizeof(WlzUInt); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp1)) == WLZ_ERR_NONE)){ (void) WlzNextGreyInterval(&iwsp2); memcpy((void *) gwsp1.u_grintptr.inp, (const void *) gwsp2.u_grintptr.inp, size * iwsp1.colrmn); } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } WlzFreeObj(obj2); WlzFreeObj(obj1); } else { WlzFreeObj(rtnObj); rtnObj = NULL; } } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
void file_menu_init( Widget topl) { Widget rc, form, toggle; Visual *visual; Arg arg[1]; char fileStr[128]; FILE *fp; WlzEffFormat image_type=WLZEFF_FORMAT_WLZ; /* set the top-level title */ set_topl_title(NULL); /* get the visual explicitly */ visual = HGU_XmWidgetToVisual(topl); XtSetArg(arg[0], XmNvisual, visual); /* create the read-model file selection dialog */ read_model_dialog = XmCreateFileSelectionDialog(topl, "read_model_dialog", arg, 1); XtAddCallback(read_model_dialog, XmNokCallback, read_reference_object_cb, (XtPointer) WLZEFF_FORMAT_WLZ); XtAddCallback(read_model_dialog, XmNokCallback, PopdownCallback, NULL); XtAddCallback( read_model_dialog, XmNcancelCallback, PopdownCallback, NULL); XtAddCallback(read_model_dialog, XmNmapCallback, FSBPopupCallback, NULL); XtManageChild( read_model_dialog ); /* create the read-obj file selection dialog */ read_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "read_obj_dialog", read_reference_object_cb, NULL); if((rc = XtNameToWidget(read_obj_dialog, "*.formatFormRC"))){ /* add a form to include file type and fill-blanks toggle */ form = XtVaCreateManagedWidget("read_file_form", xmFormWidgetClass, rc, XmNborderWidth, 0, NULL); /* add a fill-blanks toggles */ toggle = XtVaCreateManagedWidget("fill_blanks", xmToggleButtonGadgetClass, form, XmNindicatorOn, True, XmNindicatorType, XmN_OF_MANY, XmNset, False, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, NULL); toggle = XtVaCreateManagedWidget("min_domain", xmToggleButtonGadgetClass, form, XmNindicatorOn, True, XmNindicatorType, XmN_OF_MANY, XmNset, True, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, toggle, NULL); } HGU_XmExtFFObjectFSBSetType(read_obj_dialog, WLZEFF_FORMAT_WLZ); XtManageChild( read_obj_dialog ); /* add to the save restore list */ HGU_XmSaveRestoreAddWidget( read_obj_dialog, HGU_XmFSD_SaveFunc, (XtPointer) XtName(topl), NULL, NULL ); /* create the write-obj file selection dialog */ write_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "write_obj_dialog", write_reference_object_cb, NULL); HGU_XmExtFFObjectFSBSetType(write_obj_dialog, WLZEFF_FORMAT_WLZ); /* initialise the reference file list pulldown */ if( !globals.sectViewFlg ){ Widget cascade; if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ globals.resourceFile = (String) AlcMalloc(sizeof(char) * (strlen(getenv("HOME")) + 16)); sprintf(globals.resourceFile, "%s/%s", getenv("HOME"), ".maRecentFiles"); globals.fileList = HGU_XmFileListCreateList(globals.resourceFile, NULL); HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } /* add to the save restore list */ HGU_XmSaveRestoreAddWidget( write_obj_dialog, HGU_XmFSD_SaveFunc, (XtPointer) XtName(topl), NULL, NULL ); /* create the object properties dialog */ obj_props_dialog_init( topl ); globals.file = NULL; globals.obj = NULL; globals.orig_obj = NULL; globals.fb_obj = NULL; globals.origObjExtType = image_type; /* setup the theiler directory and menu item - check for stage */ XtGetApplicationResources(topl, &globals, set_att_res, XtNumber(set_att_res), NULL, 0); /* check the logfile */ if( globals.logfile ){ if( (globals.logfileFp = fopen(globals.logfile, "w")) == NULL ){ fprintf(stderr, "MAPaint: something wrong with the logfile %s\n" "Please check name and permissions\n" "Logging not enabled\n\007", globals.logfile); } else { char timeBuf[16]; struct hostent *hstnt; fprintf(stderr, "MAPaint: logging enabled to %s\n", globals.logfile); MAPaintLogData("Filename", globals.logfile, 0, NULL); MAPaintLogData("User", getenv("USER"), 0, NULL); #if defined (LINUX2) || defined (DARWIN) strcpy(timeBuf, "00/00/00"); #else tmpTime = time(NULL); cftime(timeBuf, "%d/%m/%Y", &tmpTime); #endif /* LINUX2 */ MAPaintLogData("Date", timeBuf, 0, NULL); #if defined (LINUX2) || defined (DARWIN) strcpy(timeBuf, "00.00"); #else cftime(timeBuf, "%H.%M", &tmpTime); #endif /* LINUX2 */ MAPaintLogData("Time", timeBuf, 0, NULL); hstnt = gethostbyname(getenv("HOST")); MAPaintLogData("Host", getenv("HOST"), 0, NULL); MAPaintLogData("Hostname", hstnt->h_name, 0, NULL); } } else { globals.logfileFp = NULL; } /* check base directory - if the string has come from the resources then we need to duplicate it to allow it to be freed possibly some memory leakage here */ /* note: only non-NULL if set by the user, if NULL then attempt to find the cdrom or copied data */ if( globals.base_theiler_dir ){ globals.base_theiler_dir = AlcStrDup( globals.base_theiler_dir ); } /* else { FILE *pp;*/ /* search for the Theiler mode directory as per the CDROM should search local disc first */ /*#if defined (LINUX2) if((pp = popen("find /mnt -maxdepth 4 -name Models", "r"))){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #elif defined (DARWIN) if( (pp = popen("find /Volumes -maxdepth 4 -name Models", "r")) ){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #elif defined (SUNOS4) || defined (SUNOS5) if( pp = popen("find /cdrom -maxdepth 4 -name Models", "r") ){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #else globals.base_theiler_dir = NULL; #endif }*/ if( globals.theiler_stage ){ char *tStr; if((tStr = theilerString(globals.theiler_stage))){ globals.theiler_stage = AlcStrDup(tStr); } else { globals.theiler_stage = NULL; } } theiler_menu_init( topl ); /* check for an initial reference file else check Theiler stage */ if( initial_reference_file != NULL ){ WlzObject *obj; /* open the reference object file and install */ if( (fp = fopen(initial_reference_file, "r")) ){ HGU_XmSetHourGlassCursor(topl); if((obj = WlzReadObj( fp, NULL ))){ WlzDomain domain; WlzValues values; WlzObject *newObj; switch( obj->type ){ case WLZ_2D_DOMAINOBJ: domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, NULL); domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, NULL); values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, NULL); WlzFreeObj(obj); obj = newObj; globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D woolz\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } HGU_XmFileListAddFile(globals.fileList, initial_reference_file, image_type); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); MAPaintLogData("ReferenceFile", initial_reference_file, 0, NULL); install_paint_reference_object( obj ); /* set the globals reference file */ globals.file = initial_reference_file; /* set the title of the top-level window */ set_topl_title(globals.file); } else { /* if it fails to read, check the file name or the file content for special options */ if( strstr(initial_reference_file, "MAPaint") ){ /* standard MAPaint startup */ globals.app_name = "MAPaint"; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( strstr(initial_reference_file, "SectionView") ){ /* restricted section view startup */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( theilerString(initial_reference_file) ){ /* load in theiler stage anatomy etc. */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; set_theiler_stage_cb(topl, theilerString(initial_reference_file), NULL); } else { char strBuf[33]; /* check the content */ rewind(fp); fscanf(fp, "%32s", strBuf); if( strstr(strBuf, "MAPaint") ){ /* standard MAPaint startup */ globals.app_name = "MAPaint"; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( strstr(strBuf, "SectionView") ){ /* restricted section view startup */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( theilerString(strBuf) ){ /* load in theiler stage anatomy etc. */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; set_theiler_stage_cb(topl, theilerString(strBuf), NULL); } } /* set the globals reference file */ globals.file = NULL; } (void) fclose( fp ); HGU_XmUnsetHourGlassCursor(topl); } } else if( globals.theiler_stage ){ globals.app_name = "MAPaint"; set_theiler_stage_cb(topl, theilerString(globals.theiler_stage), NULL); } /* reset the colormap */ if( globals.sectViewFlg == 1 ){ init_paint_cmapstruct(globals.topl); } /* check for an initial domain file */ if( initial_domain_file != NULL ){ WlzObject *obj; /* open the domain object file and put it in as a 3D feedback option */ if( (fp = fopen(initial_domain_file, "rb")) ){ HGU_XmSetHourGlassCursor(topl); if((obj = WlzReadObj( fp, NULL ))){ if( globals.fb_obj ){ WlzFreeObj(globals.fb_obj); } globals.fb_obj = WlzAssignObject(obj, NULL); setup_ref_display_list_cb(read_obj_dialog, NULL, NULL); } (void) fclose( fp ); HGU_XmUnsetHourGlassCursor(topl); } } return; }
/*! * \return Object with transformed grey-values. * \ingroup WlzArithmetic * \brief Apply a binary operation (add subtract etc) to * each pixel value in the given object. The operand value * is in <tt>pval</tt>. * \param o1 Input object * \param pval Pixel value for binary operation. * \param op Opertor * \param dstErr Error return. * \par Source: * WlzScalarArithmeticOp.c */ WlzObject *WlzScalarBinaryOp2( WlzObject *o1, WlzPixelV pval, WlzBinaryOperatorType op, WlzErrorNum *dstErr) { WlzObject *obj=NULL, *tmp3; WlzErrorNum errNum=WLZ_ERR_NONE; WlzValues values; WlzPixelV old_bckgrnd, new_bckgrnd; WlzGreyType new_grey_type; int p; /* check object pointers */ if( (o1 == NULL) ){ errNum = WLZ_ERR_OBJECT_NULL; } /* check object types - WLZ_EMPTY_OBJ is legal */ if( errNum == WLZ_ERR_NONE ){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_TRANS_OBJ: break; case WLZ_EMPTY_OBJ: obj = WlzMakeEmpty(&errNum); break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* check domains and valuetables */ if( (errNum == WLZ_ERR_NONE) && (obj == NULL) ){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } break; case WLZ_3D_DOMAINOBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN) ){ errNum = WLZ_ERR_PLANEDOMAIN_TYPE; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } if( (o1->values.vox->type != WLZ_VOXELVALUETABLE_GREY) ){ errNum = WLZ_ERR_VOXELVALUES_TYPE; break; } break; case WLZ_TRANS_OBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } if((values.obj = WlzScalarBinaryOp2(o1->values.obj, pval, op, &errNum)) != NULL){ obj = WlzMakeMain(WLZ_TRANS_OBJ, o1->domain, values, NULL, NULL, &errNum); break; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* set up temporary object */ if((errNum == WLZ_ERR_NONE) && (obj == NULL)){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: values.core = NULL; if( (tmp3 = WlzMakeMain(WLZ_2D_DOMAINOBJ, o1->domain, values, NULL, NULL, &errNum)) == NULL ){ break; } old_bckgrnd = WlzGetBackground(o1, NULL); switch( WlzGreyTableTypeToGreyType(o1->values.core->type, NULL) ){ case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: new_grey_type = WlzGreyTableTypeToGreyType(o1->values.core->type, NULL); new_bckgrnd = old_bckgrnd; break; case WLZ_GREY_UBYTE: new_grey_type = WLZ_GREY_SHORT; new_bckgrnd.type = WLZ_GREY_SHORT; new_bckgrnd.v.shv = old_bckgrnd.v.ubv; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE){ values.v = WlzNewValueTb(tmp3, WlzGreyTableType(WLZ_GREY_TAB_RAGR, new_grey_type, NULL), new_bckgrnd, &errNum); tmp3->values = WlzAssignValues( values, NULL ); } break; case WLZ_3D_DOMAINOBJ: values.core = NULL; if((tmp3 = WlzMakeMain(WLZ_3D_DOMAINOBJ, o1->domain, values, NULL, NULL, &errNum)) == NULL){ break; } /* now a new destination voxeltable */ old_bckgrnd = WlzGetBackground(o1, NULL); switch( old_bckgrnd.type ){ case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: new_grey_type = old_bckgrnd.type; new_bckgrnd = old_bckgrnd; break; case WLZ_GREY_UBYTE: new_grey_type = WLZ_GREY_SHORT; new_bckgrnd.type = WLZ_GREY_SHORT; new_bckgrnd.v.shv = old_bckgrnd.v.ubv; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } if(errNum == WLZ_ERR_NONE){ values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, tmp3->domain.p->plane1, tmp3->domain.p->lastpl, new_bckgrnd, NULL, &errNum); if( values.vox == NULL ){break;} for(p=tmp3->domain.p->plane1; p <= tmp3->domain.p->lastpl; p++){ WlzValues values2d; /* currently test for NULL domain to imply WLZ_EMPTY_DOMAIN */ if( tmp3->domain.p->domains[p-tmp3->domain.p->plane1].core == NULL ){ values2d.core = NULL; } else { WlzObject *tmp2d; values2d.core = NULL; if((tmp2d = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmp3->domain.p->domains[p-tmp3->domain.p->plane1], values2d, NULL, NULL, &errNum)) != NULL){ values2d.v = WlzNewValueTb( tmp2d, WlzGreyTableType(WLZ_GREY_TAB_RAGR, new_grey_type, NULL), new_bckgrnd, &errNum); WlzFreeObj( tmp2d ); } } values.vox->values[p-tmp3->domain.p->plane1] = WlzAssignValues(values2d, NULL); } tmp3->values = WlzAssignValues(values, NULL); } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* apply operation and free space */ if((errNum == WLZ_ERR_NONE) && (obj == NULL)){ if((errNum = WlzScalarBinaryOp(o1, pval, tmp3, op)) != WLZ_ERR_NONE){ WlzFreeObj( tmp3 ); } else { obj = tmp3; } } if( dstErr ){ *dstErr = errNum; } return obj; }
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 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 New object or NULL on error. * \ingroup WlzValuesUtils * \brief Transfers grey values from the source object to the * destination object within the intersection of the source * and destination. Grey values within the destination * object outside of the source object are unchanged. * It is an error if either object has a different dimension * or grey value type, except for when either is an empty * object. * \param dObj Destination object which may be * empty, but otherwise should be of the * same dimension as the source object * with valid values.. * \param sObj Source object which if not empty must * have both a valid domain and valid * values. * \param inplace Overwrite the destination object's * values if non zero. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzGreyTransfer( WlzObject *dObj, WlzObject *sObj, int inplace, WlzErrorNum *dstErr) { WlzObject *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if((dObj == NULL) || (sObj == NULL)) { errNum = WLZ_ERR_OBJECT_NULL; } else if(WlzIsEmpty(dObj, NULL)) { rObj = WlzMakeEmpty(&errNum); } else if(WlzIsEmpty(sObj, NULL)) { rObj = WlzMakeMain(dObj->type, dObj->domain, dObj->values, dObj->plist, NULL, &errNum); } else if(dObj->type != sObj->type) { errNum = WLZ_ERR_OBJECT_TYPE; } else if((dObj->domain.core == NULL) || (sObj->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(sObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { switch(sObj->type) { case WLZ_2D_DOMAINOBJ: case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */ { WlzObject *rIObj = NULL; rIObj = WlzIntersect2(dObj, sObj, &errNum); if((errNum == WLZ_ERR_NONE) && (WlzIsEmpty(rIObj, NULL) == 0)) { rObj = (inplace)? WlzMakeMain(dObj->type, dObj->domain, dObj->values, dObj->plist, NULL, &errNum): WlzCopyObject(dObj, &errNum); if(errNum == WLZ_ERR_NONE) { /* If the destination object does not have values then * create them to match the domain of the destination * object. */ if((sObj->values.core != NULL) && (rObj->values.core == NULL)) { WlzPixelV bgdV; WlzGreyType gType; WlzObjectType gTT; WlzValues newVal; newVal.core = NULL; bgdV = WlzGetBackground(sObj, &errNum); if(errNum == WLZ_ERR_NONE) { gType = WlzGreyTypeFromObj(sObj, &errNum); } if(errNum == WLZ_ERR_NONE) { gTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gType, NULL); if(rObj->type == WLZ_2D_DOMAINOBJ) { newVal.v = WlzNewValueTb(rObj, gTT, bgdV, &errNum); } else /* rObj->type == WLZ_3D_DOMAINOBJ */ { newVal.vox = WlzNewValuesVox(rObj, gTT, bgdV, &errNum); } } if(errNum == WLZ_ERR_NONE) { rObj->values = WlzAssignValues(newVal, NULL); } if(errNum == WLZ_ERR_NONE) { errNum = WlzGreySetValue(rObj, bgdV); } } } if(errNum == WLZ_ERR_NONE) { if(sObj->type == WLZ_2D_DOMAINOBJ) { WlzObject *sIObj; rIObj->values = WlzAssignValues(rObj->values, NULL); sIObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, rIObj->domain, sObj->values, NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { errNum = WlzGreyTransfer2D(rIObj, sIObj); } (void )WlzFreeObj(sIObj); } else /* sObj->type == WLZ_3D_DOMAINOBJ */ { int p, rTiled, sTiled, nPlanes; rTiled = WlzGreyTableIsTiled(rObj->values.core->type); sTiled = WlzGreyTableIsTiled(sObj->values.core->type); nPlanes = rIObj->domain.p->lastpl - rIObj->domain.p->plane1 + 1; #ifdef _OPENMP #pragma omp parallel for #endif for(p = 0; p < nPlanes; ++p) { if(errNum == WLZ_ERR_NONE) { int pln; WlzDomain dom; WlzValues val; WlzObject *rIObj2D = NULL, *sIObj2D = NULL; WlzErrorNum errNum2D = WLZ_ERR_NONE; pln = p + rIObj->domain.p->plane1; dom = rIObj->domain.p->domains[p]; val = (rTiled)? rObj->values: rObj->values.vox->values[pln - rObj->values.vox->plane1]; rIObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, dom, val, NULL, NULL, &errNum2D); if(errNum2D == WLZ_ERR_NONE) { val = (sTiled)? sObj->values: sObj->values.vox->values[pln - sObj->values.vox->plane1]; sIObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, dom, val, NULL, NULL, &errNum2D); } if(errNum2D == WLZ_ERR_NONE) { errNum2D = WlzGreyTransfer2D(rIObj2D, sIObj2D); } (void )WlzFreeObj(rIObj2D); (void )WlzFreeObj(sIObj2D); #ifdef _OPENMP #pragma omp critical { #endif if((errNum == WLZ_ERR_NONE) && (errNum2D != WLZ_ERR_NONE)) { errNum = errNum2D; } #ifdef _OPENMP } #endif } } } } } (void )WlzFreeObj(rIObj); } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum != WLZ_ERR_NONE) { WlzFreeObj(rObj); rObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rObj); }
/*! * \return New woolz object or NULL on error. * \ingroup WlzArithmetic * \brief Scales the values of the given 3D Woolz object so that * \f$v_{new} = m v_{given} + a.\f$ The input object is known * to be a valid 3D 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 *WlzScalarMulAdd3D(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 = WlzGreyTableType(WLZ_GREY_TAB_RAGR, rGType, &errNum); } if(errNum == WLZ_ERR_NONE) { rValues.vox = WlzNewValuesVox(iObj, rVType, bgdV, &errNum); } if(errNum == WLZ_ERR_NONE) { int idP, plMin, plMax; WlzPlaneDomain *iPDom; WlzVoxelValues *iVox, *rVox; iPDom = iObj->domain.p; iVox = iObj->values.vox; rVox = rValues.vox; plMin = iPDom->plane1; plMax = iPDom->lastpl; #ifdef _OPENMP #pragma omp parallel for #endif for(idP = plMin; idP <= plMax; ++idP) { WlzErrorNum errNum2D = WLZ_ERR_NONE; if(errNum == WLZ_ERR_NONE) { int idO; WlzDomain *iDom2D; WlzValues *iVal2D, *rVal2D; idO = idP - iPDom->plane1; iDom2D = iPDom->domains + idO; iVal2D = iVox->values + idO; rVal2D = rVox->values + idO; if(((*iDom2D).core != NULL) && ((*iVal2D).core != NULL) && ((*rVal2D).core != NULL)) { WlzObject *iObj2D = NULL, *rObj2D = NULL; if((iObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, *iDom2D, *iVal2D, NULL, NULL, &errNum2D)) != NULL) { rObj2D = WlzScalarMulAdd2D(iObj2D, m, a, rGType, &errNum2D); } if(errNum2D == WLZ_ERR_NONE) { *rVal2D = WlzAssignValues(rObj2D->values, NULL); } (void )WlzFreeObj(iObj2D); (void )WlzFreeObj(rObj2D); } } if(errNum2D != WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2D; } #ifdef _OPENMP } #endif } } } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, iObj->domain, rValues, iObj->plist, iObj->assoc, &errNum); } if(errNum != WLZ_ERR_NONE) { if(rObj == NULL) { (void )WlzFreeVoxelValueTb(rValues.vox); } else { (void )WlzFreeObj(rObj); rObj = NULL; } } if(dstErr != NULL) { *dstErr = errNum; } return(rObj); }
/*! * \return New 3D object. * \ingroup WlzAllocation * \brief Constructs a 3D domain object from 2D domain objects read * from the given files. Each file is read in turn and added * to the 3D object. An empty plane can be specified by * setting the file string to NULL. Either all or none of * the 2D objects must have values. When the 2D objects * have values then the background value of the first 2D * object is set to be the background value of the 3D object. * \param nFileStr Number of file strings. * \param fileStr File strings. * \param plane1 The plane coordinate of the first * 2D object. * \param xSz Column voxel size. * \param ySz Line voxel size. * \param zSz Plane voxel size. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzConstruct3DObjFromFile(int nFileStr, char **fileStr, int plane1, float xSz, float ySz, float zSz, WlzErrorNum *dstErr) { int idx, lastpl; WlzDomain dom3D; WlzValues val3D; WlzObject *obj2D = NULL, *obj3D = NULL; WlzPixelV bgd; FILE *fP = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; dom3D.core = NULL; val3D.core = NULL; lastpl = plane1 + nFileStr - 1; if((nFileStr <= 0) || (fileStr == NULL) || (*fileStr == NULL)) { errNum = WLZ_ERR_PARAM_NULL; } else { if((fP = fopen(*fileStr, "r")) == NULL) { errNum = WLZ_ERR_READ_EOF; } else { obj2D = WlzReadObj(fP, &errNum); (void )fclose(fP); fP = NULL; } } if(errNum == WLZ_ERR_NONE) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Make a plane domain, set column and line bounds later. */ if(errNum == WLZ_ERR_NONE) { dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, plane1, lastpl, 0, 1, 0, 1, &errNum); } if(errNum == WLZ_ERR_NONE) { dom3D.p->voxel_size[0] = xSz; dom3D.p->voxel_size[1] = ySz; dom3D.p->voxel_size[2] = zSz; } /* Make a voxel value table. */ if(errNum == WLZ_ERR_NONE) { if(obj2D->values.core) { bgd = WlzGetBackground(obj2D, &errNum); if(errNum == WLZ_ERR_NONE) { val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, plane1, lastpl, bgd, NULL, &errNum); } } } idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < nFileStr)) { if(obj2D) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE) { *(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL); if(val3D.core) { if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL); } } } WlzFreeObj(obj2D); obj2D = NULL; } if(errNum == WLZ_ERR_NONE) { ++idx; if((idx < nFileStr) && *(fileStr + idx)) { if((fP = fopen(*(fileStr + idx), "r")) == NULL) { errNum = WLZ_ERR_READ_EOF; } else { obj2D = WlzReadObj(fP, &errNum); (void )fclose(fP); fP = NULL; } } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox); } if(errNum == WLZ_ERR_NONE) { obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum); } if(errNum != WLZ_ERR_NONE) { if(dom3D.core) { (void )WlzFreeDomain(dom3D); } if(val3D.core) { (void )WlzFreeValues(val3D); } } if(dstErr) { *dstErr = errNum; } return(obj3D); }
/*! * \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 3D domain objects. * \param srcObj0 First object. * \param srcObj1 Second object. * \param srcObj2 Third object. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzGreyMagnitude3D(WlzObject *srcObj0, WlzObject *srcObj1, WlzObject *srcObj2, WlzErrorNum *dstErr) { int idN, idP, nPlanes; WlzDomain dstDom; WlzValues dstVal; WlzObject *dstObj2D, *istObj = NULL, *dstObj = NULL; WlzObject *srcObjA[3], *iObj3DA[3], *iObj2DA[3]; WlzPixelV bgdV; WlzErrorNum errNum = WLZ_ERR_NONE; dstDom.core = NULL; dstVal.core = NULL; iObj3DA[0] = iObj3DA[1] = iObj3DA[2] = NULL; if((srcObj0->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) || (srcObj1->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) || (srcObj2->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN)) { errNum = WLZ_ERR_DOMAIN_TYPE; } else if ((srcObj0->values.core->type != WLZ_VOXELVALUETABLE_GREY) || (srcObj1->values.core->type != WLZ_VOXELVALUETABLE_GREY) || (srcObj2->values.core->type != WLZ_VOXELVALUETABLE_GREY)) { errNum = WLZ_ERR_VALUES_TYPE; } else { srcObjA[0] = srcObj0; srcObjA[1] = srcObj1; srcObjA[2] = srcObj2; istObj = WlzIntersectN(3, srcObjA, 0, &errNum); } if(errNum == WLZ_ERR_NONE) { if(istObj->type == WLZ_EMPTY_OBJ) { dstObj = istObj; } else { dstDom = WlzAssignDomain(istObj->domain, NULL); WlzFreeObj(istObj); idN = 0; while((errNum == WLZ_ERR_NONE) && (idN < 3)) { iObj3DA[idN] = WlzMakeMain(WLZ_3D_DOMAINOBJ, dstDom, srcObjA[idN]->values, NULL, NULL, &errNum); ++idN; } if(errNum == WLZ_ERR_NONE) { idP = 0; nPlanes = dstDom.p->lastpl - dstDom.p->plane1 + 1; while((errNum == WLZ_ERR_NONE) && (idP < nPlanes)) { if((dstDom.p->domains + idN)->core == NULL) { (dstVal.vox->values + idP)->core = NULL; } else { dstObj2D = NULL; iObj2DA[0] = iObj2DA[1] = iObj2DA[2] = NULL; idN = 0; /* Make 2D objects. */ while((errNum == WLZ_ERR_NONE) && (idN < 3)) { iObj2DA[idN] = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(iObj3DA[idN]->domain.p->domains + idP), *(iObj3DA[idN]->values.vox->values + idP), NULL, NULL, &errNum); ++idN; } /* Compute magnitude. */ if(errNum == WLZ_ERR_NONE) { dstObj2D = WlzGreyMagnitude2D3(iObj2DA[0], iObj2DA[1], iObj2DA[2], &errNum); } /* If first plane get grey type and background, then create new * 3D object with new voxel values. */ if((idP == 0) && (errNum == WLZ_ERR_NONE)) { bgdV = WlzGetBackground(iObj2DA[0], &errNum); if(errNum == WLZ_ERR_NONE) { dstVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, dstDom.p->plane1, dstDom.p->lastpl, bgdV, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dstDom, dstVal, NULL, NULL, &errNum); } } /* Add 2D values to the 3D objects values. */ if(errNum == WLZ_ERR_NONE) { *(dstVal.vox->values + idP) = WlzAssignValues(dstObj2D->values, NULL); } /* Free temporary 2D object. */ if(dstObj2D) { WlzFreeObj(dstObj2D); } idN = 0; while(idN < 3) { if(iObj2DA[idN]) { WlzFreeObj(iObj2DA[idN]); } ++idN; } } ++idP; } } /* Free 3D intersection gradient objects. */ idN = 0; while(idN < 3) { if(iObj3DA[idN]) { WlzFreeObj(iObj3DA[idN]); } ++idN; } /* Decrement link count to the destination 3D domain. */ (void )WlzFreeDomain(dstDom); } } if((errNum != WLZ_ERR_NONE) && (dstObj != NULL)) { WlzFreeObj(dstObj); dstObj = NULL; } if(dstErr) { *dstErr = errNum; } return(dstObj); }