WlzObject *WlzRGBABoxThreshold( WlzObject *obj, WlzPixelV lowVal, WlzPixelV highVal, WlzErrorNum *dstErr) { WlzErrorNum errNum=WLZ_ERR_NONE; WlzObject *rtnObj=NULL; int h, l; WlzUInt combineMode; /* check and reset low annd high values */ l = WLZ_RGBA_RED_GET(lowVal.v.rgbv); h = WLZ_RGBA_RED_GET(highVal.v.rgbv); if( l > h ){ WLZ_RGBA_RED_SET(highVal.v.rgbv, l); WLZ_RGBA_RED_SET(lowVal.v.rgbv, h); } l = WLZ_RGBA_GREEN_GET(lowVal.v.rgbv); h = WLZ_RGBA_GREEN_GET(highVal.v.rgbv); if( l > h ){ WLZ_RGBA_GREEN_SET(highVal.v.rgbv, l); WLZ_RGBA_GREEN_SET(lowVal.v.rgbv, h); } l = WLZ_RGBA_BLUE_GET(lowVal.v.rgbv); h = WLZ_RGBA_BLUE_GET(highVal.v.rgbv); if( l > h ){ WLZ_RGBA_BLUE_SET(highVal.v.rgbv, l); WLZ_RGBA_BLUE_SET(lowVal.v.rgbv, h); } /* set all AND for combine value and call multi-threshold */ WLZ_RGBA_RGBA_SET(combineMode, WLZ_BO_AND, WLZ_BO_AND, WLZ_BO_AND, 255); rtnObj = WlzRGBAMultiThreshold(obj, lowVal, highVal, combineMode, &errNum); /* check error and return */ if( dstErr ){ *dstErr = errNum; } return rtnObj; }
int main(int argc, char **argv) { int tI, idN, option, con = WLZ_0_CONNECTED, nLo = 0, nHi = 0, maxSep = 1024, nObj = 0, ok = 1, usage = 0; char tC; double tD, mrkMass = 1.0, rad = 0.0; int tR[4]; WlzPixelV gV, bV; WlzBlobMark mrk = WLZ_BLOBMARK_CIRCLE; WlzObject *inObj = NULL, *outObj = NULL, *mrkObj = NULL; WlzObject **lObj = NULL; FILE *fP = NULL; char *inObjFileStr, *outObjFileStr; WlzErrorNum errNum = WLZ_ERR_NONE; const char *errMsg; static char optList[] = "c:g:G:hm:n:N:o:r:x:", fileStrDef[] = "-"; opterr = 0; memset(&gV, 0, sizeof(WlzPixelV)); bV.type = WLZ_GREY_UBYTE; bV.v.ubv = 0; gV.type = WLZ_GREY_ERROR; inObjFileStr = fileStrDef; outObjFileStr = fileStrDef; while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'c': if(sscanf(optarg, "%d", &tI) != 1) { usage = 1; } else { switch(tI) { case 4: con = WLZ_4_CONNECTED; break; case 6: con = WLZ_6_CONNECTED; break; case 8: con = WLZ_8_CONNECTED; break; case 18: con = WLZ_18_CONNECTED; break; case 26: con = WLZ_26_CONNECTED; break; default: usage = 1; break; } } break; case 'g': switch(gV.type) { case WLZ_GREY_UBYTE: if((sscanf(optarg, "%d", &tI) != 1) || (tI < 0) || (tI > 255)) { usage = 1; } else { gV.v.ubv = tI; } break; case WLZ_GREY_SHORT: if((sscanf(optarg, "%d", &tI) != 1) || (tI < SHRT_MIN) || (tI > SHRT_MAX)) { usage = 1; } else { gV.v.shv = tI; } break; case WLZ_GREY_INT: if(sscanf(optarg, "%d", &tI) != 1) { usage = 1; } else { gV.v.inv = tI; } break; case WLZ_GREY_FLOAT: if((sscanf(optarg, "%lg", &tD) != 1) || (tD < -(FLT_MAX)) || (tD > FLT_MAX)) { usage = 1; } else { gV.v.flv = tD; } break; case WLZ_GREY_DOUBLE: if(sscanf(optarg, "%lg", &tD) != 1) { usage = 1; } else { gV.v.dbv = tD; } break; case WLZ_GREY_RGBA: tR[3] = 255; tR[0] = tR[1] = tR[2] = 0; if((sscanf(optarg, "%d,%d,%d,%d", &(tR[0]), &(tR[1]), &(tR[2]), &(tR[3])) == 0) || (tR[0] < 0) || (tR[0] > 255) || (tR[1] < 0) || (tR[1] > 255) || (tR[2] < 0) || (tR[2] > 255) || (tR[3] < 0) || (tR[3] > 255)) { usage = 1; } else { WLZ_RGBA_RGBA_SET(gV.v.rgbv, tR[0], tR[1], tR[2], tR[3]); } break; default: usage = 1; break; } break; case 'G': if(sscanf(optarg, "%c", &tC) != 1) { usage = 1; } switch(tC) { case 'v': gV.type = WLZ_GREY_ERROR; break; case 'u': gV.type = WLZ_GREY_UBYTE; break; case 's': gV.type = WLZ_GREY_SHORT; break; case 'i': gV.type = WLZ_GREY_INT; break; case 'f': gV.type = WLZ_GREY_FLOAT; break; case 'd': gV.type = WLZ_GREY_DOUBLE; break; case 'r': gV.type = WLZ_GREY_RGBA; break; default: usage = 1; break; } break; case 'm': if((sscanf(optarg, "%d", &tI) != 1) || ((tI != WLZ_BLOBMARK_CIRCLE) && (tI != WLZ_BLOBMARK_SQUARE))) { usage = 1; } else { mrk = (WlzBlobMark )tI; } break; case 'n': if((sscanf(optarg, "%d", &nLo) != 1) || (nLo < 0)) { usage = 1; } break; case 'N': if((sscanf(optarg, "%d", &nHi) != 1) || (nHi < 0)) { usage = 1; } break; case 'o': outObjFileStr = optarg; break; case 'r': if((sscanf(optarg, "%lg", &rad) != 1) || (rad < 0.0)) { usage = 1; } break; case 'x': if((sscanf(optarg, "%d", &maxSep) != 1) || (maxSep < 1)) { usage = 1; } case 'h': /* FALLTHROUGH */ default: usage = 1; break; } } if((usage == 0) && (nLo > nHi) && (nHi != 0)) { usage = 1; } if((usage == 0) && (optind < argc)) { if((optind + 1) != argc) { usage = 1; } else { inObjFileStr = *(argv + optind); } } ok = (usage == 0); /* Read input domain object. */ if(ok) { if((inObjFileStr == NULL) || (*inObjFileStr == '\0') || ((fP = (strcmp(inObjFileStr, "-")? fopen(inObjFileStr, "r"): stdin)) == NULL) || ((inObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) || (errNum != WLZ_ERR_NONE)) { ok = 0; } if(fP) { if(strcmp(inObjFileStr, "-")) { (void )fclose(fP); } fP = NULL; } } /* Check object type and connectivity. */ if(ok) { switch(inObj->type) { case WLZ_2D_DOMAINOBJ: switch(con) { case WLZ_0_CONNECTED: con = WLZ_8_CONNECTED; break; case WLZ_4_CONNECTED: /* FALLTHROUGH */ case WLZ_8_CONNECTED: break; default: ok = 0; errNum = WLZ_ERR_PARAM_DATA; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Connectivity for 2D must be 4 or 8 (%s).\n", *argv, errMsg); break; } break; case WLZ_3D_DOMAINOBJ: switch(con) { case WLZ_0_CONNECTED: con = WLZ_26_CONNECTED; break; case WLZ_6_CONNECTED: /* FALLTHROUGH */ case WLZ_18_CONNECTED: /* FALLTHROUGH */ case WLZ_26_CONNECTED: break; default: ok = 0; errNum = WLZ_ERR_PARAM_DATA; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Connectivity for 3D must be 6, 18 or 26 (%s).\n", *argv, errMsg); break; } break; default: ok = 0; errNum = WLZ_ERR_OBJECT_TYPE; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Input object must either a 2 or 3D domain object (%s).\n", *argv, errMsg); break; } } /* Make basic marker with centre at the origin. */ if(ok) { double mrkRad; if(rad > 0.5) { mrkRad = rad; } else { mrkRad = 127; } if(mrk == WLZ_BLOBMARK_SQUARE) { mrkObj = WlzMakeCuboidObject(inObj->type, mrkRad, mrkRad, mrkRad, 0, 0, 0, &errNum); } else /* mrk = WLZ_BLOBMARK_CIRCLE */ { mrkObj = WlzMakeSphereObject(inObj->type, mrkRad, 0, 0, 0, &errNum); } if(mrkObj == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to create basic marker object (%s).\n", *argv, errMsg); } else { mrkMass = WlzVolume(mrkObj, NULL); } } /* Label the given domain. */ if(ok) { errNum = WlzLabel(inObj, &nObj, &lObj, maxSep, 1, con); if((errNum != WLZ_ERR_NONE) || (nObj == 0)) { ok = 0; if(errNum == WLZ_ERR_NONE) { errNum = WLZ_ERR_DOMAIN_DATA; } (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to split the given object into separate regions (%s)\n", *argv, errMsg); } } /* Work through the separate object list removing small/large objects * according to the low and high thresholds. */ if(ok) { int idM; for(idN = 0, idM = 0; idN < nObj; ++idN) { int vol; vol = WlzVolume(lObj[idN], &errNum); if(errNum == WLZ_ERR_NONE) { if(((nLo > 0) && (vol < nLo)) || ((nHi > 0) && (vol > nHi))) { (void )WlzFreeObj(lObj[idN]); } else { lObj[idM] = lObj[idN]; ++idM; } } } nObj = idM; if(nObj == 0) { ok = 0; errNum = WLZ_ERR_DOMAIN_DATA; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to find and separate regions (%s)\n", *argv, errMsg); } } /* Build a marker object by adding a mark at the centre of mass of each * separate fragment. */ if(ok) { WlzObject *obj0 = NULL; idN = 0; obj0 = WlzMakeEmpty(&errNum); while((errNum == WLZ_ERR_NONE) && (idN < nObj)) { double mass; WlzDVertex3 com; WlzObject *obj1 = NULL, *obj2 = NULL; WlzAffineTransform *tr = NULL; com = WlzCentreOfMass3D(lObj[idN], 1, &mass, &errNum); if(errNum == WLZ_ERR_NONE) { double s; if(rad < 0.5) { double t; t = mass / mrkMass; if(inObj->type == WLZ_2D_DOMAINOBJ) { s = sqrt(t); } else /* inObj->type == WLZ_3D_DOMAINOBJ */ { s = cbrt(t); } } else { s = 1.0; } tr = (inObj->type == WLZ_2D_DOMAINOBJ)? WlzAffineTransformFromPrimVal( WLZ_TRANSFORM_2D_AFFINE, com.vtX, com.vtY, 0.0, s, 0.0, 0.0, 0.0, 0.0, 0.0, 0, &errNum): WlzAffineTransformFromPrimVal( WLZ_TRANSFORM_3D_AFFINE, com.vtX, com.vtY, com.vtZ, s, 0.0, 0.0, 0.0, 0.0, 0.0, 0, &errNum); } if(errNum == WLZ_ERR_NONE) { obj1 = WlzAffineTransformObj(mrkObj, tr, WLZ_INTERPOLATION_NEAREST, &errNum); } if(errNum == WLZ_ERR_NONE) { obj2 = WlzUnion2(obj0, obj1, &errNum); } if(errNum == WLZ_ERR_NONE) { (void )WlzFreeObj(obj0); obj0 = obj2; obj2 = NULL; } (void )WlzFreeObj(obj1); (void )WlzFreeObj(obj2); (void )WlzFreeAffineTransform(tr); ++idN; } if(errNum == WLZ_ERR_NONE) { WlzValues val; WlzObjectType vTT; val.core = NULL; if(gV.type != WLZ_GREY_ERROR) { vTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gV.type, NULL); if(inObj->type == WLZ_2D_DOMAINOBJ) { val.v = WlzNewValueTb(obj0, vTT, bV, &errNum); } else /* inObj->type == WLZ_3D_DOMAINOBJ */ { val.vox = WlzNewValuesVox(obj0, vTT, bV, &errNum); } } if(errNum == WLZ_ERR_NONE) { outObj = WlzMakeMain(inObj->type, obj0->domain, val, NULL, NULL, &errNum); } if((errNum == WLZ_ERR_NONE) && (gV.type != WLZ_GREY_ERROR)) { errNum = WlzGreySetValue(outObj, gV); } } } if(ok) { errNum = WLZ_ERR_WRITE_EOF; if(((fP = (strcmp(outObjFileStr, "-")? fopen(outObjFileStr, "w"): stdout)) == NULL) || ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to write output object (%s).\n", *argv, errMsg); } if(fP && strcmp(outObjFileStr, "-")) { (void )fclose(fP); } } (void )WlzFreeObj(inObj); if(lObj != NULL) { for(idN = 0; idN < nObj; ++idN) { (void )WlzFreeObj(lObj[idN]); } AlcFree(lObj); } (void )WlzFreeObj(outObj); if(usage) { (void )fprintf(stderr, "Usage: %s%sExample: %s%s", *argv, " [-c#] [-g#] [-G#] [-h] [-m#] [-n#] [-N#]\n" " [-o<output object>] [-r#]] [-x#] [<input object>]\n" "Options:\n" " -c Connectivity: 4, 6, 8, 18 or 26 connected (default 8 for 2D\n" " domains and 26 for 3D domains).\n" " -g Grey value for marker. This is a single number for all except\n" " RGBA (colour) grey values. RGBA components must be separated by\n" " by a comma.\n" " -G Grey value type for marker specified by letter:\n" " v no grey values (default).\n" " u unsigned byte grey values.\n" " s short grey values.\n" " i int grey values.\n" " f int grey values.\n" " d int grey values.\n" " r red, green, blue, alpha grey values.\n" " -h Help, prints usage message.\n" " -m Marker type specified by a number:\n" " 1 circle/sphere (default)\n" " 2 square/cube\n" " -n Threshold minimum area/volume of blob for a marker (default\n" " >= 1).\n" " -N Threshold maximum area/volume of blob for a marker. If zero\n" " there is no upper limit. (default 0).\n" " -o Output object file.\n" " -r Marker radius. Attempts to keep the same area/volume if zero.\n" " (default 0).\n" " -x Maximum number of separate regions in the object (default 1024).\n" "Reads a spatial domain object and replaces each spatialy separate\n" "region with a marker placed at the centre of mass of the region.\n" "All files are read from the standard input and written to the standard\n" "output unless filenames are given.\n" "If grey values are required then the grey value type must be set before\n" "the actual grey value.\n", *argv, " -o out.wlz -n 4 -r 10 -G r -g 200,100,0,255 in.wlz\n" "A spatial domain object is read from the file in.wlz and each\n" "spatialy separate region of the domain is replaced by a circle or\n" "sphere of radius 10 (pixels). All small regions with less than four\n" "(pixels voxels) is ignored. The output object (with grey values set\n" "to orange) is written to the file out.wlz.\n"); } return(!ok); }
/*! * \ingroup WlzValuesFilters * \brief Set new grey-range by simple linear interpolation. It assumes that the min and max values enclose the true range of grey-values in the object. Failure to check this could result in a segmentation fault. The transform function is: \f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta \f] Here \f$\delta\f$ is the dither value. * * \return Woolz error number * \param obj Input grey-level object whose values are to be reset. * \param min Initial minimum value * \param max Initial maximum value * \param Min Final minimum value * \param Max Final maximum value * \param Dither values if destination range is greater than source range * and this flag is non-zero. * \par Source: * WlzGreySetRange.c */ WlzErrorNum WlzGreySetRange( WlzObject *obj, WlzPixelV min, WlzPixelV max, WlzPixelV Min, WlzPixelV Max, int dither) { double gMin = 0.0, gMax = 0.0, sigma = 0.0, factor, val; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzObject *tempobj; WlzValues *values; WlzDomain *domains; int i, j, nplanes; WlzErrorNum errNum = WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->values.core == NULL ){ return WLZ_ERR_VALUES_NULL; } if( WlzGreyTableIsTiled(obj->values.core->type) ){ return WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ return WLZ_ERR_PLANEDOMAIN_TYPE; } if( obj->values.vox == NULL ){ return WLZ_ERR_VALUES_NULL; } if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ return WLZ_ERR_VOXELVALUES_TYPE; } /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; i < nplanes; i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, &errNum); if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){ errNum = WLZ_ERR_UNSPECIFIED; break; } errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither); WlzFreeObj( tempobj ); if( errNum != WLZ_ERR_NONE ){ break; } } return errNum; case WLZ_TRANS_OBJ: return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ /* get conversion function - should use LUT use 4 LUTS for rgb type since bounded */ if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){ WlzUByte rgbaLut[4][256]; WlzUInt rgbamin[4], rgbaMin[4]; double rgbaFactor[4], val1; WlzUInt red, green, blue, alpha; rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv); rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv); if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){ rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - WLZ_RGBA_RED_GET(Min.v.rgbv))/ (WLZ_RGBA_RED_GET(max.v.rgbv) - WLZ_RGBA_RED_GET(min.v.rgbv))); } else { rgbaFactor[0] = 0.0; } rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv); rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv); if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){ rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - WLZ_RGBA_GREEN_GET(Min.v.rgbv))/ (WLZ_RGBA_GREEN_GET(max.v.rgbv) - WLZ_RGBA_GREEN_GET(min.v.rgbv))); } else { rgbaFactor[1] = 0.0; } rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv); rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv); if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){ rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - WLZ_RGBA_BLUE_GET(Min.v.rgbv))/ (WLZ_RGBA_BLUE_GET(max.v.rgbv) - WLZ_RGBA_BLUE_GET(min.v.rgbv))); } else { rgbaFactor[2] = 0.0; } rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv); rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv); if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){ rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/ (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - WLZ_RGBA_ALPHA_GET(min.v.rgbv))); } else { rgbaFactor[3] = 0.0; } /* now set up the LUTS */ for(i=0; i < 4; i++){ for(j=0; j < 256; j++){ val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i]; rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255); } } /* set values - can assume rgba grey-type */ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){ red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)]; green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)]; blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)]; alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)]; WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } else { WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE); if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){ return WLZ_ERR_FLOAT_DATA; } errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv); if(dither) { if(fabs(factor) < 1.0 + DBL_EPSILON) { dither = 0; } else { sigma = fabs(2.0 / factor); AlgRandSeed(101); switch(gwsp.pixeltype) { case WLZ_GREY_INT: gMin = ALG_MAX(Min.v.dbv, INT_MIN); gMax = ALG_MIN(Max.v.dbv, INT_MAX); break; case WLZ_GREY_SHORT: gMin = ALG_MAX(Min.v.dbv, SHRT_MIN); gMax = ALG_MIN(Max.v.dbv, SHRT_MAX); break; case WLZ_GREY_UBYTE: gMin = ALG_MAX(Min.v.dbv, 0); gMax = ALG_MIN(Max.v.dbv, 255); break; case WLZ_GREY_FLOAT: gMin = ALG_MAX(Min.v.dbv, FLT_MIN); gMax = ALG_MIN(Max.v.dbv, FLT_MAX); break; case WLZ_GREY_DOUBLE: gMin = Min.v.dbv; gMax = Max.v.dbv; break; default: break; } } } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++){ if(dither){ val = factor * (*gptr.inp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv; } *gptr.inp = WLZ_NINT(val); } break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++){ if(dither){ val = factor * (*gptr.shp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv; } *gptr.shp = (short )WLZ_NINT(val); } break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){ if(dither){ val = factor * (*gptr.ubp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv; } *gptr.ubp = (WlzUByte )WLZ_NINT(val); } break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++){ if(dither){ val = factor * (*gptr.flp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv; } *gptr.flp = (float )val; } break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){ if(dither){ val = factor * (*gptr.dbp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv; } *gptr.dbp = val; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } } return errNum; }
/*! * \return Woolz object read from jpeg image. * \ingroup WlzExtFF * \brief Reads a jpeg image frm the given file stream and returns a * Woolz object. * \param fP Given file stream. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzEffReadObjJpeg( FILE *fP, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ int width, height; /* int depth; */ int wlzDepth; WlzGreyType newpixtype; WlzPixelV bckgrnd; int i, rOff; WlzGreyP wlzData; WlzErrorNum errNum=WLZ_ERR_NONE; /* check input */ if( fP == NULL ){ errNum = WLZ_ERR_PARAM_NULL; } /* We set up the normal JPEG error routines, then override error_exit. */ if( errNum == WLZ_ERR_NONE ){ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); if( rtnObj ){ WlzFreeObj(rtnObj); rtnObj = NULL; } errNum = WLZ_ERR_READ_INCOMPLETE; } } if( errNum == WLZ_ERR_NONE ){ /* initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, fP); /* read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* default set parameters for decompression */ (void) jpeg_start_decompress(&cinfo); /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* create the appropriate woolz object, read scanlines and copy data */ switch( cinfo.jpeg_color_space ){ default: case JCS_UNKNOWN: errNum = WLZ_ERR_READ_INCOMPLETE; break; case JCS_GRAYSCALE: bckgrnd.type = WLZ_GREY_UBYTE; #if BITS_IN_JSAMPLE == 8 if( cinfo.data_precision != 8 ){ errNum = WLZ_ERR_FILE_FORMAT; } else { wlzDepth = sizeof(char); newpixtype = WLZ_GREY_UBYTE; /* depth = cinfo.num_components * 8; */ bckgrnd.v.ubv = 0; } #endif /* BITS_IN_SAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 if( cinfo.data_precision != 12 ){ errNum = WLZ_ERR_FILE_FORMAT; } else { wlzDepth = sizeof(short); newpixtype = WLZ_GREY_SHORT; /* depth = cinfo.num_components * 12; */ bckgrnd.v.shv = 0; } #endif /* BITS_IN_SAMPLE == 12 */ break; case JCS_YCbCr: case JCS_CMYK: case JCS_YCCK: case JCS_RGB: bckgrnd.type = WLZ_GREY_RGBA; cinfo.out_color_space = JCS_RGB; #if BITS_IN_JSAMPLE == 8 if( cinfo.data_precision != 8 ){ errNum = WLZ_ERR_FILE_FORMAT; } else { wlzDepth = sizeof(int); newpixtype = WLZ_GREY_RGBA; /* depth = cinfo.num_components * 8; */ bckgrnd.v.inv = 0; } #endif /* BITS_IN_SAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 errNum = WLZ_ERR_UNIMPLEMENTED; #endif /* BITS_IN_SAMPLE == 8 */ break; } if( errNum == WLZ_ERR_NONE ){ /* make the woolz object */ width = cinfo.image_width; height = cinfo.image_height; if((wlzData.ubp = (WlzUByte *)AlcCalloc(width*height, wlzDepth)) != NULL){ if((rtnObj = WlzMakeRect(0, height-1, 0, width-1, newpixtype, wlzData.inp, bckgrnd, NULL, NULL, &errNum)) != NULL){ AlcErrno errAlcNum; rtnObj->values.r->freeptr = AlcFreeStackPush(rtnObj->values.r->freeptr, (void *) wlzData.ubp, &errAlcNum); if( errAlcNum != ALC_ER_NONE ){ errNum = WLZ_ERR_MEM_ALLOC; } } else{ AlcFree((void *) wlzData.ubp); } } else { errNum = WLZ_ERR_MEM_ALLOC; } } } /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. * scan object copying in scanline values */ if( errNum == WLZ_ERR_NONE ){ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines(&cinfo, buffer, 1); /* copy to the woolz object buffer */ switch( newpixtype ){ case WLZ_GREY_UBYTE: memcpy((void *) wlzData.ubp, (const void *) buffer[0], sizeof(char) * width); wlzData.ubp += width; break; case WLZ_GREY_SHORT: memcpy((void *) wlzData.shp, (const void *) buffer[0], sizeof(short) * width); wlzData.shp += width; break; case WLZ_GREY_RGBA: /* this we need to decode */ rOff = 0; for(i=0; i < width; i++, wlzData.rgbp++, rOff += 3){ WLZ_RGBA_RGBA_SET(*wlzData.rgbp, buffer[0][rOff], buffer[0][rOff+1], buffer[0][rOff+2], 255); } break; default: break; } } /* Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* Release JPEG decompression object */ jpeg_destroy_decompress(&cinfo); } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
void warpSetSignalDomain( WlzIVertex2 *selVtx) { WlzErrorNum errNum=WLZ_ERR_NONE; WlzPixelV threshV, threshV1; WlzObject *obj, *obj1; WlzUInt combineMode; /* image processing sequence */ if( warpGlobals.sgnlThreshObj == NULL ){ warpSetSignalThreshObj(); } if( warpGlobals.sgnlThreshObj ){ obj1 = WlzAssignObject(warpGlobals.sgnlThreshObj, &errNum); } else { return; } /* threshold the resultant image */ if( errNum == WLZ_ERR_NONE ){ switch( warpGlobals.thresholdType ){ case WLZ_RGBA_THRESH_NONE: break; case WLZ_RGBA_THRESH_SINGLE: threshV.type = WLZ_GREY_INT; threshV.v.inv = warpGlobals.threshRangeLow; if( obj1 ){ /* clear signal object */ if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); } if((obj = WlzThreshold(obj1, threshV, WLZ_THRESH_HIGH, &errNum)) && (WlzVolume(obj, &errNum) > 0)){ obj = WlzAssignObject(obj, &errNum); WlzFreeObj(obj1); threshV.v.inv = warpGlobals.threshRangeHigh + 1; if((obj1 = WlzThreshold(obj, threshV, WLZ_THRESH_LOW, &errNum)) && (WlzVolume(obj1, &errNum) > 0)){ warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum); } else { if( obj1 ){ WlzFreeObj(obj1); } warpGlobals.sgnlObj = NULL; } WlzFreeObj(obj); } else { if( obj ) { WlzFreeObj(obj); } WlzFreeObj(obj1); warpGlobals.sgnlObj = NULL; } } break; case WLZ_RGBA_THRESH_MULTI: /* clear signal object */ if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); } /* set the thresholds and combine mode */ threshV.type = WLZ_GREY_RGBA; WLZ_RGBA_RGBA_SET(threshV.v.rgbv, warpGlobals.threshRangeRGBLow[0], warpGlobals.threshRangeRGBLow[1], warpGlobals.threshRangeRGBLow[2], 255); threshV1.type = WLZ_GREY_RGBA; WLZ_RGBA_RGBA_SET(threshV1.v.rgbv, warpGlobals.threshRangeRGBHigh[0], warpGlobals.threshRangeRGBHigh[1], warpGlobals.threshRangeRGBHigh[2], 255); WLZ_RGBA_RGBA_SET(combineMode, WLZ_BO_AND, WLZ_BO_AND, WLZ_BO_AND, 255); /* use multi-threshold */ if((obj = WlzRGBAMultiThreshold(obj1, threshV, threshV1, combineMode, &errNum))){ if( WlzIsEmpty(obj, &errNum) ){ WlzFreeObj(obj); warpGlobals.sgnlObj = NULL; } else { warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum); } } else { warpGlobals.sgnlObj = NULL; } WlzFreeObj(obj1); break; case WLZ_RGBA_THRESH_BOX: /* clear signal object */ if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); } /* use box-threshold */ if((obj = WlzRGBABoxThreshold(obj1, warpGlobals.lowRGBPoint, warpGlobals.highRGBPoint, &errNum))){ if( WlzIsEmpty(obj, &errNum) ){ WlzFreeObj(obj); warpGlobals.sgnlObj = NULL; } else { warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum); } } else { warpGlobals.sgnlObj = NULL; } WlzFreeObj(obj1); break; case WLZ_RGBA_THRESH_SLICE: /* clear signal object */ if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); } /* use slice-threshold */ if((obj = WlzRGBASliceThreshold(obj1, warpGlobals.lowRGBPoint, warpGlobals.highRGBPoint, &errNum))){ if( WlzIsEmpty(obj, &errNum) ){ WlzFreeObj(obj); warpGlobals.sgnlObj = NULL; } else { warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum); } } else { warpGlobals.sgnlObj = NULL; } WlzFreeObj(obj1); break; case WLZ_RGBA_THRESH_SPHERE: /* clear signal object */ if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); } /* use Ellipsoid-threshold */ if((obj = WlzRGBAEllipsoidThreshold(obj1, warpGlobals.lowRGBPoint, warpGlobals.highRGBPoint, warpGlobals.colorEllipseEcc, &errNum))){ if( WlzIsEmpty(obj, &errNum) ){ WlzFreeObj(obj); warpGlobals.sgnlObj = NULL; } else { warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum); } } else { warpGlobals.sgnlObj = NULL; } WlzFreeObj(obj1); break; default: errNum = WLZ_ERR_PARAM_DATA; if( obj1 ){ WlzFreeObj(obj1); } if( warpGlobals.sgnlObj ){ WlzFreeObj(warpGlobals.sgnlObj); warpGlobals.sgnlObj = NULL; } break; } } /* check for local mode */ if( warpGlobals.sgnlObj && !warpGlobals.globalThreshFlg ){ if( selVtx != NULL ){ warpGlobals.globalThreshVtx = *selVtx; } /* extract a local domain if the vertex is sensible */ if( warpGlobals.globalThreshVtx.vtX != -10000 ){ WlzObject **objs=NULL; int i, numObjs; double x, y; obj1 = NULL; x = warpGlobals.globalThreshVtx.vtX; y = warpGlobals.globalThreshVtx.vtY; errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0, WLZ_4_CONNECTED); if( (errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){ WlzObject *tmpObj1, *tmpObj2; WlzDomain domain; WlzValues values; /* try again, smaller domain */ for(i=0; i < numObjs; i++){ WlzFreeObj( objs[i] ); } AlcFree((void *) objs); objs = NULL; numObjs = 0; domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT, y - 80, y + 80, x - 80, x + 80, &errNum); values.core = NULL; if((tmpObj1 = WlzMakeMain(warpGlobals.sgnlObj->type, domain, values, NULL, NULL, &errNum))){ if((tmpObj2 = WlzIntersect2(warpGlobals.sgnlObj, tmpObj1, &errNum))){ tmpObj2->values = WlzAssignValues(warpGlobals.sgnlObj->values, NULL); errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0, WLZ_4_CONNECTED); WlzFreeObj(tmpObj2); if((errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){ errNum = WLZ_ERR_NONE; } } WlzFreeObj(tmpObj1); } } if( errNum == WLZ_ERR_NONE ){ for(i=0; i < numObjs; i++){ if( WlzInsideDomain( objs[i], 0.0, y, x, NULL ) ){ obj1 = WlzMakeMain(objs[i]->type, objs[i]->domain, objs[i]->values, NULL, NULL, NULL); obj1 = WlzAssignObject(obj1, NULL); } WlzFreeObj( objs[i] ); } AlcFree((void *) objs); } if( obj1 ){ WlzFreeObj(warpGlobals.sgnlObj); warpGlobals.sgnlObj = obj1; } } else { WlzFreeObj(warpGlobals.sgnlObj); warpGlobals.sgnlObj = NULL; } } /* check for increment mode */ if( warpGlobals.incrThreshFlg && sgnlIncrObj() ){ if( warpGlobals.sgnlObj ){ if((obj1 = WlzUnion2(warpGlobals.sgnlObj, sgnlIncrObj(), &errNum))){ WlzFreeObj(warpGlobals.sgnlObj); warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum); } } else { warpGlobals.sgnlObj = WlzAssignObject(sgnlIncrObj(), &errNum); } } if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "warpSetSignalDomain", errNum); } return; }
static unsigned char *WlzEFFTiffToWlzRowData( unsigned char *inp, unsigned char *dstPtr, int width, short photometric, short samplesperpixel, short bitspersample, WlzGreyType newpixtype, unsigned char red[], unsigned char green[], unsigned char blue[], WlzErrorNum *dstErr) { WlzGreyP wlzData; int col; off_t offset = 0; WlzErrorNum errNum=WLZ_ERR_NONE; wlzData.v = NULL; if( inp == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } if( dstPtr ){ wlzData.ubp = dstPtr; } else { errNum = WLZ_ERR_VALUES_NULL; } if( (errNum == WLZ_ERR_NONE) ){ offset = 0; switch (photometric) { case PHOTOMETRIC_RGB: if (samplesperpixel == 4){ for (col = 0; col < width; col++, offset++) { WLZ_RGBA_RGBA_SET(wlzData.rgbp[offset], inp[0], inp[1], inp[2], inp[3]); inp += 4; /* skip to next values */ } } else { for (col = 0; col < width; col++, offset++) { WLZ_RGBA_RGBA_SET(wlzData.rgbp[offset], inp[0], inp[1], inp[2], 0xff); inp += 3; /* skip to next values */ } } break; case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: switch (bitspersample) { case 1: for (col = 0; col < ((width + 7) / 8); col++, offset++){ wlzData.ubp[offset] = *inp++; } break; case 2: for (col = 0; col < ((width + 3) / 4); col++) { wlzData.ubp[offset++] = (*inp >> 6) & 3; wlzData.ubp[offset++] = (*inp >> 4) & 3; wlzData.ubp[offset++] = (*inp >> 2) & 3; wlzData.ubp[offset++] = *inp++ & 3; } break; case 4: for (col = 0; col < width / 2; col++) { wlzData.ubp[offset++] = *inp >> 4; wlzData.ubp[offset++] = *inp++ & 0xf; } break; case 8: for (col = 0; col < width; col++, offset++){ wlzData.ubp[offset] = *inp++; } break; case 16: switch( newpixtype ){ case WLZ_GREY_SHORT: for (col = 0; col < width; col++, offset++){ #if defined (__sparc) || defined (__mips) || defined (__ppc) wlzData.shp[offset] = (inp[0]<<8) | (inp[1]); #endif /* __sparc || __mips */ #if defined (__x86) || defined (__alpha) wlzData.shp[offset] = (inp[0]) | (inp[1]<<8); #endif /* __x86 || __alpha */ inp += 2; } break; case WLZ_GREY_INT: for (col = 0; col < width; col++, offset++){ #if defined (__sparc) || defined (__mips) || defined (__ppc) wlzData.inp[offset] = (inp[0]<<8) | (inp[1]); #endif /* __sparc || __mips */ #if defined (__x86) || defined (__alpha) wlzData.inp[offset] = (inp[0]) | (inp[1]<<8); #endif /* __x86 || __alpha */ inp += 2; } break; case WLZ_GREY_FLOAT: /* FALLTHROUGH */ default: errNum = WLZ_ERR_FILE_FORMAT; break; } break; default: errNum = WLZ_ERR_FILE_FORMAT; break; } break; case PHOTOMETRIC_PALETTE: switch (bitspersample) { case 4: for (col = 0; col < width / 2; col++) { wlzData.ubp[offset++] = *inp >> 4; wlzData.ubp[offset++] = *inp++ & 0xf; } break; case 8: switch( newpixtype ){ case WLZ_GREY_UBYTE: for (col = 0; col < width; col++, offset++){ wlzData.ubp[offset] = *inp++; } break; case WLZ_GREY_RGBA: for (col = 0; col < width; col++, offset++){ WLZ_RGBA_RGBA_SET(wlzData.rgbp[offset], red[*inp], green[*inp], blue[*inp], 255); inp += 1; /* skip to next value */ } break; default: errNum = WLZ_ERR_FILE_FORMAT; } break; default: errNum = WLZ_ERR_FILE_FORMAT; break; } break; default: errNum = WLZ_ERR_FILE_FORMAT; break; } }
/*! * \ingroup WlzValuesFilters * \brief Perform a 1D convolution on a 1D array of data. Typically used to pass to WlzSepTrans(). The params variable is a 1D convolution mask. * * \return Woolz error * \param stwspc Separable transfom work space * \param params parameters passed from top-level calling function, unchanged by WlzSepTrans() * \par Source: * WlzGauss.c */ WlzErrorNum Wlz1DConv( WlzSepTransWSpace *stwspc, void *params) { Wlz1DConvMask *convParams = (Wlz1DConvMask *) params; int i, j, n, *mask, factor, length; int intSum; double dblSum; WlzGreyP inbuf, outbuf; WlzUInt red, green, blue; /* set some local parameters */ n = convParams->mask_size / 2; mask = convParams->mask_values + n; factor = convParams->norm_factor; inbuf = stwspc->inbuf.p; outbuf = stwspc->outbuf.p; length = stwspc->len; /* calculate the new value - use int for WlzUByte, short and int double otherwise, separate rgb values each use WlzUInt */ switch( stwspc->inbuf.type ){ case WLZ_GREY_INT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.inp[-((i>j)?j:i)] * mask[-j]; } inbuf.inp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[j] * mask[j]; intSum += inbuf.inp[-j] * mask[-j]; } inbuf.inp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.inp[-j] * mask[-j]; } inbuf.inp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_SHORT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.shp[-((i>j)?j:i)] * mask[-j]; } inbuf.shp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[j] * mask[j]; intSum += inbuf.shp[-j] * mask[-j]; } inbuf.shp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ =(float )( intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.shp[-j] * mask[-j]; } inbuf.shp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_UBYTE: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.ubp[-((i>j)?j:i)] * mask[-j]; } inbuf.ubp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[j] * mask[j]; intSum += inbuf.ubp[-j] * mask[-j]; } inbuf.ubp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.ubp[-j] * mask[-j]; } inbuf.ubp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_FLOAT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.flp[-((i>j)?j:i)] * mask[-j]; } inbuf.flp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[j] * mask[j]; dblSum += inbuf.flp[-j] * mask[-j]; } inbuf.flp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.flp[-j] * mask[-j]; } inbuf.flp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_DOUBLE: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.dbp[-((i>j)?j:i)] * mask[-j]; } inbuf.dbp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[j] * mask[j]; dblSum += inbuf.dbp[-j] * mask[-j]; } inbuf.dbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.dbp[-j] * mask[-j]; } inbuf.dbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_RGBA: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; } inbuf.rgbp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-j]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-j]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-j]) * mask[-j]; } inbuf.rgbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-j]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-j]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-j]) * mask[-j]; } inbuf.rgbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte)((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; default: return WLZ_ERR_GREY_TYPE; break; } return WLZ_ERR_NONE; }
/*! * \return Woolz error code. * \ingroup WlzBinaryOps * \brief Splits the given montage object into component objects * clipped from the montage object. The montage object * must be composed of component images embedded in a * background, with little variation in the background * values. * \param mObj Montage object, which must be either * a WLZ_2D_DOMAINOBJ or a * WLZ_3D_DOMAINOBJ with values. * \param gapV Value for the uniform background. * Must be either WLZ_GREY_INT or * WLZ_GREY_RGBA. * \param tol Tolerance (fraction) for the * variation in background values. * \param bWidth Additional boundary width added * to detected images before they are * clipped. * \param minArea Minimum area for a valid component * image, must be greater than zero. * \param maxComp Maximum number of components. * \param dstNComp Destination pointer for the number of * components extracted, must not be NULL. * \param dstComp Destination pointer for the extracted * components, must not be NULL. */ WlzErrorNum WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV, double tol, int bWidth, int minArea, int maxComp, int *dstNComp, WlzObject ***dstComp) { int id0, id1, area, nLComp = 0; WlzObject *gObj = NULL, *tObj = NULL; WlzObject **lComp; WlzGreyType objG; WlzBox box; WlzPixelV gapLV, gapHV; WlzConnectType lCon; int tI[8]; WlzErrorNum errNum = WLZ_ERR_NONE; tol = WLZ_CLAMP(tol, 0.0, 1.0); if(mObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(minArea < 1) { errNum = WLZ_ERR_PARAM_DATA; } else { switch(mObj->type) { case WLZ_2D_DOMAINOBJ: lCon = WLZ_4_CONNECTED; break; case WLZ_3D_DOMAINOBJ: lCon = WLZ_6_CONNECTED; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { objG = WlzGreyTypeFromObj(mObj, &errNum); } if(errNum == WLZ_ERR_NONE) { switch(gapV.type) { case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_RGBA: break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { if(objG == WLZ_GREY_RGBA) { if(gapV.type != WLZ_GREY_RGBA) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA); } } else { if(gapV.type != WLZ_GREY_INT) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT); } } gapLV.type = gapHV.type = gapV.type; if(gapV.type == WLZ_GREY_INT) { tI[0] = gapV.v.inv * tol; gapLV.v.inv = gapV.v.inv - tI[0]; gapHV.v.inv = gapV.v.inv + tI[0]; tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum); if((errNum == WLZ_ERR_NONE) && (tObj != NULL)) { gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum); } (void )WlzFreeObj(tObj); tObj = NULL; } else /* gapV.type == WLZ_GREY_RGBA */ { tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[2] = tI[0] - tI[1]; tI[5] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[3] = tI[0] - tI[1]; tI[6] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[4] = tI[0] - tI[1]; tI[7] = tI[0] + tI[1]; tI[2] = WLZ_CLAMP(tI[2], 0, 255); tI[3] = WLZ_CLAMP(tI[3], 0, 255); tI[4] = WLZ_CLAMP(tI[4], 0, 255); WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255); tI[5] = WLZ_CLAMP(tI[5], 0, 255); tI[6] = WLZ_CLAMP(tI[6], 0, 255); tI[7] = WLZ_CLAMP(tI[7], 0, 255); WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255); gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum); } } if(errNum == WLZ_ERR_NONE) { tObj = WlzDiffDomain(mObj, gObj, &errNum); } (void )WlzFreeObj(gObj); if(errNum == WLZ_ERR_NONE) { errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon); } (void )WlzFreeObj(tObj); if(errNum == WLZ_ERR_NONE) { /* Get rid of small objects using minArea as the threshold. */ id0 = 0; id1 = 0; while(id0 < nLComp) { switch((*(lComp + id0))->type) { case WLZ_2D_DOMAINOBJ: area = WlzArea(*(lComp + id0), NULL); break; case WLZ_3D_DOMAINOBJ: area = WlzVolume(*(lComp + id0), NULL); break; default: area = 0; break; } if(area >= minArea) { *(lComp + id1) = *(lComp + id0); ++id1; } else { (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = NULL; } ++id0; } nLComp = id1; } if(errNum == WLZ_ERR_NONE) { /* Clip rectangular objects from the montage object. */ id0 = 0; while((errNum == WLZ_ERR_NONE) && (id0 < nLComp)) { if(tObj->type == WLZ_2D_DOMAINOBJ) { box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum); box.i2.xMin -= bWidth; box.i2.yMin -= bWidth; box.i2.xMax += bWidth; box.i2.yMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum); } else /* tObj->type == WLZ_3D_DOMAINOBJ */ { box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum); box.i3.xMin -= bWidth; box.i3.yMin -= bWidth; box.i3.zMin -= bWidth; box.i3.xMax += bWidth; box.i3.yMax += bWidth; box.i3.zMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum); } ++id0; } } *dstNComp = nLComp; *dstComp = lComp; return(errNum); }
/*! * \return Woolz error code. * \ingroup WlzArithmetic * \brief Sets the values of the return object from the input object * using simple linear scaling, see WlzScalarMulAdd(). The * objects are known to be 2D, have the same domain. * \param rObj * \param iObj * \param m * \param a */ static WlzErrorNum WlzScalarMulAddSet2D(WlzObject *rObj, WlzObject *iObj, double m, double a) { int bufLen; WlzGreyWSpace iGWSp, rGWSp; WlzIntervalWSpace iIWSp = {0}, rIWSp = {0}; WlzErrorNum errNum = WLZ_ERR_NONE; bufLen = iObj->domain.i->lastkl - iObj->domain.i->kol1 + 1; if((bufLen != iObj->domain.i->lastkl - iObj->domain.i->kol1 + 1) || (bufLen < 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else if(bufLen > 0) { if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(iObj, &iIWSp, &iGWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(rObj, &rIWSp, &rGWSp); } if(errNum == WLZ_ERR_NONE) { double *buf = NULL; if((buf = AlcMalloc(sizeof(double) * bufLen)) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } else { while((errNum = WlzNextGreyInterval(&iIWSp)) == WLZ_ERR_NONE) { int t, idN, itvLen; double f; itvLen = iIWSp.colrmn; (void )WlzNextGreyInterval(&rIWSp); switch(iGWSp.pixeltype) { case WLZ_GREY_INT: WlzValueCopyIntToDouble(buf, iGWSp.u_grintptr.inp, itvLen); break; case WLZ_GREY_SHORT: WlzValueCopyShortToDouble(buf, iGWSp.u_grintptr.shp, itvLen); break; case WLZ_GREY_UBYTE: WlzValueCopyUByteToDouble(buf, iGWSp.u_grintptr.ubp, itvLen); break; case WLZ_GREY_FLOAT: WlzValueCopyFloatToDouble(buf, iGWSp.u_grintptr.flp, itvLen); break; case WLZ_GREY_DOUBLE: WlzValueCopyDoubleToDouble(buf, iGWSp.u_grintptr.dbp, itvLen); break; case WLZ_GREY_RGBA: WlzValueCopyRGBAToDouble(buf, iGWSp.u_grintptr.rgbp, itvLen); break; default: break; } switch(rGWSp.pixeltype) { case WLZ_GREY_UBYTE: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, 0, 255); rGWSp.u_grintptr.ubp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_SHORT: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, SHRT_MIN, SHRT_MAX); rGWSp.u_grintptr.shp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_INT: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, INT_MIN, INT_MAX); rGWSp.u_grintptr.inp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_RGBA: for(idN = 0; idN < itvLen; ++idN) { WlzUInt u; f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, 0, 255); t = WLZ_NINT(f); WLZ_RGBA_RGBA_SET(u, t, t, t, 255); rGWSp.u_grintptr.inp[idN] = u; } case WLZ_GREY_FLOAT: for(idN = 0; idN < itvLen; ++idN) { double t; t = (buf[idN] * m) + a; rGWSp.u_grintptr.flp[idN] = WLZ_CLAMP(t, -(FLT_MAX), FLT_MAX); } break; case WLZ_GREY_DOUBLE: for(idN = 0; idN < itvLen; ++idN) { rGWSp.u_grintptr.dbp[idN] = (buf[idN] * m) + a; } break; default: break; } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } AlcFree(buf); } (void )WlzEndGreyScan(&iIWSp, &iGWSp); (void )WlzEndGreyScan(&rIWSp, &rGWSp); } return(errNum); }
/*! * \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; }
/*! * \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); }
WlzErrorNum WlzGreyScalarDivValue( WlzObject *obj, WlzPixelV val) { WlzObject *tmpObj; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzPixelV tmpVal; WlzDomain *domains; WlzValues *values; int i, nplanes; int red = 0, green = 0, blue = 0, alpha = 0; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->values.v == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if( obj->values.vox == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else { /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; (errNum == WLZ_ERR_NONE) && (i < nplanes); i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } if((tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, NULL)) != NULL){ errNum = WlzGreyScalarDivValue(tmpObj, val); WlzFreeObj( tmpObj ); } } } return errNum; case WLZ_TRANS_OBJ: return WlzGreyScalarDivValue(obj->values.obj, val); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); WlzValueConvertPixel(&tmpVal, val, WLZ_GREY_DOUBLE); while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++) *gptr.inp /= tmpVal.v.dbv; break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++) *gptr.shp /= tmpVal.v.dbv; break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++) *gptr.ubp /= tmpVal.v.dbv; break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++) *gptr.flp /= tmpVal.v.dbv; break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++) *gptr.dbp /= tmpVal.v.dbv; break; case WLZ_GREY_RGBA: for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++) red = WLZ_RGBA_RED_GET(*gptr.rgbp) / tmpVal.v.dbv; green = WLZ_RGBA_GREEN_GET(*gptr.rgbp) / tmpVal.v.dbv; blue = WLZ_RGBA_BLUE_GET(*gptr.rgbp) / tmpVal.v.dbv; alpha = WLZ_RGBA_ALPHA_GET(*gptr.rgbp); red = WLZ_CLAMP(red, 0, 255); green = WLZ_CLAMP(red, 0, 255); blue = WLZ_CLAMP(red, 0, 255); WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } return errNum; }
int main(int argc, char *argv[]) { int option, copy = 0, ok = 1, usage = 0, voxSzSet = 0; WlzGreyType gType = WLZ_GREY_UBYTE; WlzFVertex3 voxSz; WlzPixelV bgdV; WlzErrorNum errNum = WLZ_ERR_NONE; FILE *fP = NULL; WlzObject *inObj = NULL, *outObj = NULL; char *inFileStr, *outFileStr; int iBuf[4]; const char *errMsg; const size_t tlSz = WLZ_TILEDVALUES_TILE_SIZE; static char optList[] = "chb:g:o:s:", inFileStrDef[] = "-", outFileStrDef[] = "-"; opterr = 0; inFileStr = inFileStrDef; outFileStr = outFileStrDef; bgdV.v.dbv = 0.0; bgdV.type = WLZ_GREY_DOUBLE; voxSz.vtX = voxSz.vtY = voxSz.vtZ = 1.0f; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'c': copy = 1; break; case 'b': bgdV.type = gType; switch(gType) { case WLZ_GREY_LONG: if(sscanf(optarg, "%lld", &(bgdV.v.lnv)) != 1) { usage = 1; } break; case WLZ_GREY_INT: if(sscanf(optarg, "%d", &(bgdV.v.inv)) != 1) { usage = 1; } break; case WLZ_GREY_SHORT: if((sscanf(optarg, "%d", iBuf) != 1) || (iBuf[0] < SHRT_MIN) || (iBuf[0] > SHRT_MAX)) { usage = 1; } else { bgdV.v.shv = iBuf[0]; } break; case WLZ_GREY_UBYTE: if((sscanf(optarg, "%d", iBuf) != 1) || (iBuf[0] < 0) || (iBuf[0] > 255)) { usage = 1; } else { bgdV.v.ubv = iBuf[0]; } break; case WLZ_GREY_FLOAT: if(sscanf(optarg, "%g", &(bgdV.v.flv)) != 1) { usage = 1; } break; case WLZ_GREY_DOUBLE: if(sscanf(optarg, "%lg", &(bgdV.v.dbv)) != 1) { usage = 1; } break; case WLZ_GREY_RGBA: iBuf[0] = iBuf[1] = iBuf[2] = iBuf[3] = 0; if((sscanf(optarg, "%d,%d,%d,%d", iBuf + 0, iBuf + 1, iBuf + 2, iBuf + 3) < 3) || (iBuf[0] < 0) || (iBuf[0] > 255) || (iBuf[1] < 0) || (iBuf[1] > 255) || (iBuf[2] < 0) || (iBuf[2] > 255) || (iBuf[3] < 0) || (iBuf[3] > 255)) { usage = 1; } else { WLZ_RGBA_RGBA_SET(bgdV.v.rgbv, iBuf[0], iBuf[1], iBuf[2], iBuf[3]); } break; default: usage = 1; break; } break; case 'g': switch(*optarg) { case 'l': gType = WLZ_GREY_LONG; break; 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; case 'r': gType = WLZ_GREY_RGBA; break; default: usage = 1; break; } break; case 'o': outFileStr = optarg; break; case 's': voxSzSet = 1; if(sscanf(optarg, "%g,%g,%g", &(voxSz.vtX), &(voxSz.vtY), &(voxSz.vtZ)) != 3) { usage = 1; } break; case 'h': /* FALLTHROUGH */ default: usage = 1; break; } } if((usage == 0) && (optind < argc)) { if((optind + 1) != argc) { usage = 1; } else { inFileStr = *(argv + optind); } } ok = !usage; if(ok) { fP = NULL; errNum = WLZ_ERR_READ_EOF; if(((fP = (strcmp(inFileStr, "-")? fopen(inFileStr, "r"): stdin)) == NULL) || ((inObj= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to read object from file %s (%s).\n", *argv, inFileStr, errMsg); } if(fP && strcmp(inFileStr, "-")) { (void )fclose(fP); } } if(ok) { if(inObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(inObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { switch(inObj->type) { case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_3D_DOMAINOBJ: break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: invalid object read from file %s (%s).\n", *argv, inFileStr, errMsg); } } if(ok) { WlzObject *domObj = NULL; WlzValues nullVal; nullVal.core = NULL; domObj = WlzMakeMain(inObj->type, inObj->domain, (copy == 0)? nullVal: inObj->values, NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { if((voxSzSet != 0) && (domObj->type == WLZ_3D_DOMAINOBJ)) { domObj->domain.p->voxel_size[0] = voxSz.vtX; domObj->domain.p->voxel_size[1] = voxSz.vtY; domObj->domain.p->voxel_size[2] = voxSz.vtZ; } outObj = WlzMakeTiledValuesFromObj(domObj, tlSz, copy, gType, 0, NULL, bgdV, &errNum); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to create object with tiled values (%s).\n", *argv, errMsg); } (void )WlzFreeObj(domObj); } if(ok && (outFileStr != NULL)) { if(((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL) || ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to write tiled object to file %s (%s).\n", *argv, outFileStr, errMsg); } if(fP!= NULL) { (void )fclose(fP); } } (void )WlzFreeObj(outObj); (void )WlzFreeObj(inObj); if(usage) { (void )fprintf(stderr, "Usage: %s%s%s%s", *argv, " [-o<output object>] [-h] [-b #] [-g #] [-s #,#,#]\n" " [<input object>]\n" "Creates an object with a tiled value table from an object with a\n" "valid spatial domain.\n" "Version: ", WlzVersion(), "\n" "Options:\n" " -b Background value. If the grey type is RGBA then the channel\n" " background values should be comma seperated and in the order\n" " RGBA.\n" " -c Copy the values from the given object to the tiled object.\n" " -g Grey type specified using one of the characters:\n" " l, i, s, u, f, d, r for long, intm shortm unsigned byte,\n" " float, double or RGBA.\n" " -h Prints this usage information.\n" " -s Voxel size (x,y,z).\n" " -o Output tiled object.\n"); } return(!ok); }
/*! * \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); }