/*! * Extracts a slice at section number [sno] from the volume in the * @@Istack structure@ [v], where [axis] is either x or X for a Y/Z slice or * y or Y for an X/Z slice. Returns NULL for error. */ Islice *mrc_slice_getvol(Istack *v, int sno, char axis) { Islice *sout; Ival val; int i, j, k; switch (axis){ case 'y': case 'Y': sout = sliceCreate(v->vol[0]->xsize, v->zsize, v->vol[0]->mode); if (!sout) return(NULL); for (k = 0; k < sout->ysize; k++) for(i = 0; i < sout->xsize; i++){ sliceGetVal(v->vol[k], i, sno, val); slicePutVal(sout, i, k, val); } break; case 'x': case 'X': sout = sliceCreate(v->vol[0]->ysize, v->zsize, v->vol[0]->mode); if (!sout) return(NULL); for (k = 0; k < sout->ysize; k++) for (j = 0; j < sout->xsize; j++){ sliceGetVal(v->vol[k], sno, j, val); slicePutVal(sout, j, k, val); } break; default: return(NULL); } return(sout); }
/*! * Creates a new slice of size [nx], [ny] and resizes the input slice [slin] * into this slice, with the center of the old slice placed in the center of * the new one. Fills areas with no data from the old slice with * the slice mean for every channel of multi-channel data. Returns new slice * or NULL for error. */ Islice *mrc_slice_resize(Islice *slin, int nx, int ny) { Islice *sout; int i, j, x, y; int sx, sy; Ival pval, val; pval[0] = slin->mean; pval[1] = slin->mean; pval[2] = slin->mean; sout = sliceCreate(nx, ny, slin->mode); if (!sout) return(sout); sx = (slin->xsize - nx) / 2; sy = (slin->ysize - ny) / 2; for(j = 0, y = sy; j < ny; j++, y++) for(i = 0, x = sx; i < nx; i++, x++){ if ( (x < 0) || (y < 0) || (x >= slin->xsize) || (y >= slin->ysize ) ) slicePutVal(sout, i, j, pval); else{ sliceGetVal(slin, x, y, val); slicePutVal(sout, i, j, val); } } return(sout); }
/*! * Puts values from the slice [s] into the volume in * the @@Istack structure@ [v] at coordinate [sno] along the axis given by * [axis], which must be one of x, X, y, Y, z, or Z. For a Z slice, * the existing slice is freed and the supplied slice becomes part of the * stack, so it should not be freed separately from the stack. Returns 0. */ int mrc_slice_putvol(Istack *v, Islice *s, int sno, char axis) { Ival val; int i, j, k; switch (axis){ case 'z': case 'Z': sliceFree(v->vol[sno]); v->vol[sno] = s; break; case 'y': case 'Y': for (k = 0; k < s->ysize; k++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, k, val); slicePutVal(v->vol[k], i, sno, val); } break; case 'x': case 'X': for (k = 0; k < s->ysize; k++) for (j = 0; j < s->xsize; j++){ sliceGetVal(s, j, k, val); slicePutVal(v->vol[k], sno, j, val); } break; default: return(0); } return(0); }
/*! * Mirrors the slice [s] about the given axis, where [axis] must be one of * x, X, y, or Y. Returns 1 for error. */ int sliceMirror(Islice *s, char axis) { int i, j; Ival val1; Ival val2; int lim; if (axis == 'x' || axis == 'X'){ lim = s->ysize / 2; for(j = 0; j < lim; j++){ for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val1); sliceGetVal(s, i, s->ysize - j - 1, val2); slicePutVal(s, i, j, val2); slicePutVal(s, i, s->ysize - j - 1, val1); } } return(0); } if (axis == 'y' || axis == 'Y'){ lim = s->xsize / 2; for(i = 0; i < lim; i++) for(j = 0; j < s->ysize; j++){ sliceGetVal(s, i, j, val1); sliceGetVal(s, s->xsize - 1 - i, j, val2); slicePutVal(s, i, j, val2); slicePutVal(s, s->xsize - 1 - i, j, val1); } return(0); } return(-1); }
/* reorders data so that fft center is at (datasize/2 <-> 0 ) UNUSED 2/2/07 except by unused mrc_vol_wrap */ int mrc_slice_wrap(Islice *s) { int i,j; int mx, my; Ival val, tval; mx = s->xsize / 2; my = s->ysize / 2; for (j = 0; j < my; j++){ for (i = 0; i < mx; i++){ fflush(stdout); sliceGetVal(s, i, j, val); sliceGetVal(s, i + mx, j + my, tval); slicePutVal(s, i, j, tval); slicePutVal(s, i + mx, j + my, val); } for( i = mx; i < s->xsize; i++){ sliceGetVal(s, i, j, val); sliceGetVal(s, i - mx, j + my, tval); slicePutVal(s, i, j, tval); slicePutVal(s, i - mx, j + my, val); } } return(0); }
/*! * Scales data in the slice by the factor [alpha] around the value [fixed]; * i.e., a value of [fixed] is unchanged by the scaling. Returns 0. */ int mrc_slice_lie(Islice *sin, double fixed, double alpha) { int i, j, c; Ival val; float scale, offset, minval, maxval; minval = maxval = 0.; scale = (float)alpha; offset = (1.0f - scale) * (float)fixed; switch(sin->mode) { case MRC_MODE_BYTE: case MRC_MODE_RGB: maxval = 255.; break; case MRC_MODE_SHORT: case MRC_MODE_COMPLEX_SHORT: minval = -32768.; maxval = 32767.; break; case MRC_MODE_USHORT: maxval = 65535.; break; } if (sin->csize == 1) { for (j = 0; j < sin->ysize; j++) for (i = 0; i < sin->xsize; i++) { sliceGetVal(sin, i, j, val); val[0] = (offset + (scale * val[0])); if (maxval) { if (val[0] > maxval) val[0] = maxval; if (val[0] < minval) val[0] = minval; } slicePutVal(sin, i, j, val); } } else { for (j = 0; j < sin->ysize; j++) for (i = 0; i < sin->xsize; i++) { sliceGetVal(sin, i, j, val); for (c = 0; c < sin->csize; c++) { val[c] = (offset + (scale * val[c])); if (maxval) { if (val[c] > maxval) val[c] = maxval; if (val[c] < minval) val[c] = minval; } } slicePutVal(sin, i, j, val); } } return(0); }
/*! * Rotates the input slice [slin] by the [angle] (in degrees) about the center * point [cx], [cy] and places the result into the output slice [sout]. * Uses quadratic interpolation. For areas where there is no image data, all * channels will be filled with the slice mean. Returns 0. */ int mrc_slice_rotates(Islice *slin, Islice *sout, double angle, double cx, double cy) { int i, j; Ival val; double x, y; double sino, coso; double x2, y2; angle *= 0.017453293; coso = cos(-angle); sino = sin(-angle); x2 = (double)sout->xsize * 0.5; y2 = (double)sout->ysize * 0.5; for(j = 0; j < sout->ysize; j++) for (i = 0; i < sout->xsize; i++){ x = (((double)i - x2) * coso) - (((double)j - y2) * sino) + cx; y = (((double)i - x2) * sino) + (((double)j - y2) * coso) + cy; sliceQuadInterpolate(slin, x, y, val); slicePutVal(sout, i, j, val); } return(0); }
/*! * Returns a slice with the gradient of the input slice [sin], or NULL for * error. The gradient is the absolute value of the difference * between the current and next pixel, averaged over the X and Y direction. */ Islice *sliceGradient(Islice *sin) { Islice *s; int i, j; Ival val, nval, gval; s = sliceCreate(sin->xsize, sin->ysize, sin->mode); if (!s) return(NULL); /* Store gradient in X */ for(j = 0; j < sin->ysize; j++){ for(i = 0; i < sin->xsize - 1; i++){ sliceGetVal(sin, i, j, val); sliceGetVal(sin, i+1, j, nval); val[0] = nval[0] - val[0]; if (val[0] < 0) val[0] *= -1; slicePutVal(s, i, j, val); } } /* Get gradient in Y and average with the one in X, copy last line */ for(i = 0; i < sin->xsize; i++){ for(j = 0; j < sin->ysize - 1; j++){ sliceGetVal(sin, i, j, val); sliceGetVal(sin, i, j + 1, nval); sliceGetVal(s, i, j, gval); val[0] = nval[0] - val[0]; if (val[0] < 0) val[0] *= -1; gval[0] = (val[0] + gval[0]) / 2; slicePutVal(s, i, j, gval); } sliceGetVal(s, i, j - 1, val); slicePutVal(s, i, j, val); } /* Copy last column over too */ for(j = 0; j < sin->ysize; j++){ sliceGetVal(s, sin->xsize - 2, j, val); slicePutVal(s, sin->xsize - 1, j, val); } sliceMMM(s); return(s); }
/*! * Sets the entire slice [s] to the value given by the @@Ival type@ [val] */ void sliceClear(Islice *s, Ival val) { unsigned int i, j; s->min = s->max = s->mean = sliceGetValMagnitude(val, s->mode); for (j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++) slicePutVal(s, i, j, val); }
/*! * Adds the constant in the value array [c] to [slice]. Returns 0. */ int sliceAddConst(Islice *slice, Ival c) { Ival val; unsigned int i, j; unsigned int xsize = slice->xsize; unsigned int ysize = slice->ysize; if (slice->csize == 1 ){ for (j = 0; j < ysize; j++){ for (i = 0; i < xsize; i++){ sliceGetVal(slice, i, j, val); val[0] += c[0]; slicePutVal(slice, i, j, val); } } return(0); } if (slice->csize == 2 ){ for (j = 0; j < ysize; j++){ for (i = 0; i < xsize; i++){ sliceGetVal(slice, i, j, val); val[0] += c[0]; val[1] += c[1]; slicePutVal(slice, i, j, val); } } return(0); } if (slice->csize == 3 ){ for (j = 0; j < ysize; j++){ for (i = 0; i < xsize; i++){ sliceGetVal(slice, i, j, val); val[0] += c[0]; val[1] += c[1]; val[2] += c[2]; slicePutVal(slice, i, j, val); } } return(0); } return(0); }
/*! * Multiples all values in [slice] by the constants in the value array [c]. * Returns 0. */ int sliceMultConst(Islice *slice, Ival c) { int i, j; Ival val; switch(slice->csize){ case 1: for (j = 0; j < slice->ysize; j++){ for (i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); val[0] *= c[0]; slicePutVal(slice, i, j, val); } } break; case 2: for (j = 0; j < slice->ysize; j++){ for (i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); val[0] *= c[0]; val[1] *= c[1]; slicePutVal(slice, i, j, val); } } case 3: for (j = 0; j < slice->ysize; j++){ for (i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); val[0] *= c[0]; val[1] *= c[1]; val[2] *= c[2]; slicePutVal(slice, i, j, val); } } break; } return(0); }
/* Unused 11/10/05 */ int mrc_slice_lie_img(Islice *sin, Islice *mask, double alpha) { int i, j; Ival val1, val2; float a, ma; a = alpha; ma = 1 - alpha; for(j = 0; j < sin->ysize; j++) for(i = 0; i < sin->xsize; i++){ sliceGetVal(sin, i, j, val1); sliceGetVal(mask, i, j, val2); val1[0] = (ma * val1[0]) + (a * val2[0]); switch(sin->mode){ case MRC_MODE_BYTE: if (val1[0] > 255) val1[0] = 255; if (val1[0] < 0) val1[0] = 0; break; case MRC_MODE_SHORT: if (val1[0] > 32767) val1[0] = 32767; if (val1[0] < -32768) val1[0] = -32768; break; case MRC_MODE_USHORT: if (val1[0] > 65535) val1[0] = 65535; if (val1[0] < 0) val1[0] = 0; break; } if (sin->csize == 3){ val1[1] = (ma * val1[1]) + (a * val2[1]); val1[2] = (ma * val1[2]) + (a * val2[2]); } slicePutVal(sin, i, j, val1); } return(0); }
/* Make a blank slice to write to the output volume, using the pad in opt */ static Islice *clipBlankSlice(MrcHeader *hout, ClipOptions *opt) { Ival val; int i, j; Islice *ps = sliceCreate(hout->nx, hout->ny, hout->mode); if (!ps){ fprintf(stderr, "clipBlankSlice: error getting slice\n"); return NULL; } val[0] = opt->pad; val[1] = opt->pad; val[2] = opt->pad; for(j = 0; j < hout->ny; j++) for(i = 0; i < hout->nx; i++) slicePutVal(ps, i, j, val); return ps; }
/*! * Filters the FFT data in slice [sin] with a bandpass filter specified by * [low] and [high], in cycles/pixel (range 0 to 0.5). The attenuation at * frequency {rad} is the product of 1/(1+(rad/low)**3) if [low] > 0 and * 1/1+(high/rad)**3) if high > 0. Returns -1 for mode not complex float. */ int mrc_bandpass_filter(struct MRCslice *sin, double low, double high) { int i, j; double dist, mval, dx, dy, xscale, xadd, power = 3; Ival val; if (sin->mode != MRC_MODE_COMPLEX_FLOAT){ b3dError(stderr, " mrc_band_filter: Only complex float mode.\n"); return(-1); } /* Set up X coordinate scaling for odd or even (mirrored) FFTs */ if (sin->xsize % 2) { xscale = 0.5 / (sin->xsize - 1.); xadd = 0.; } else { xscale = 1. / sin->xsize; xadd = -0.5; } for (j = 0; j < sin->ysize; j++) for(i = 0; i < sin->xsize; i++){ dx = xscale * i + xadd; dy = (float)j / sin->ysize - 0.5; dist = sqrt(dx *dx + dy * dy); if (low > 0.) { if (dist < 0.00001) mval = 0; else mval = 1 / (1 + pow(low / dist, power)); } else mval = 1.0; if (high > 0.0) mval *= 1 / (1 + pow(dist / high, power)); sliceGetVal(sin, i, j, val); val[0] *= mval; val[1] *= mval; slicePutVal(sin, i, j, val); } return(0); }
/*! * Extracts a subarea of slice [sl] into a new slice and returns the slice * or NULL for error. The coordinates of the subarea are from [llx] to * [urx] - 1 in X and [lly] to [ury] -1 in Y, inclusive. For areas where * there is no image data, the slice mean is used to fill only the first * channel. */ Islice *sliceBox(Islice *sl, int llx, int lly, int urx, int ury) { Islice *sout; int i, j, x, y; int nx, ny; Ival val; nx = urx-llx; ny = ury-lly; sout = sliceCreate(nx, ny, sl->mode); if (!sout) return(NULL); for(j = lly, y = 0; y < ny; y++, j++) for(i = llx, x = 0; x < nx; x++, i++){ sliceGetVal(sl, i, j, val); slicePutVal(sout, x, y, val); } return(sout); }
/*! * Creates a slice of size [xsize], [ysize] and translates the input slice * [sin] by [dx], [dy] using bilinear interpolation, putting the result in * the new slice. For areas where there is no image data, all channels will * be filled with the slice mean. Returns the new slice or NULL for error. */ Islice *mrc_slice_translate(Islice *sin, double dx, double dy, int xsize, int ysize) { int i, j; Islice *sout; Ival val; double x, y; sout = sliceCreate(xsize, ysize, sin->mode); if (sout == NULL) return(NULL); for(j = 0; j < ysize; j++){ y = (double)j + dy; for (i = 0; i < xsize; i++){ x = (double)i + dx; sliceQuadInterpolate(sin, x, y, val); slicePutVal(sout, i, j, val); } } return(sout); }
/*! * Converts the data in [slice] from modes 0-3 or 6 to complex float. For * modes 0-2 and 6, the value is placed in the real component and the imaginary * component is set to 0. This should be slightly more efficient than * @sliceNewMode is. Returns -1 for error. */ int sliceComplexFloat(Islice *slice) { Islice *tsl; Ival val; int i, j; if (slice->mode > 3 && slice->mode != MRC_MODE_USHORT) return(-1); val[1] = 0; tsl = sliceCreate(slice->xsize, slice->ysize, MRC_MODE_COMPLEX_FLOAT); if (!tsl) return(-1); for(j = 0; j < slice->ysize; j++) for(i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); slicePutVal(tsl, i, j, val); } free(slice->data.b); slice->data.f = tsl->data.f; slice->mode = MRC_MODE_COMPLEX_FLOAT; free(tsl); return(0); }
/*! * Filters a slice [sin] by convolving with the square matrix [mat] of * dimension [dim] and returns a float slice, or NULL for error. Pixels outside * the image bounds are obtained by replicated pixels on the edge, so there is * no need to set the {mean} value of the slice. */ Islice *slice_mat_filter(Islice *sin, float *mat, int dim) { Islice *sout; float *imat; Ival val; int i,j; imat = (float *)malloc(dim * dim * sizeof(float)); if (!imat) return(NULL); sout = sliceCreate(sin->xsize, sin->ysize, MRC_MODE_FLOAT); if (!sout) return NULL; for(j = 0; j < sin->ysize; j++){ for(i = 0; i < sin->xsize; i++){ mrc_slice_mat_getimat(sin, i, j, dim, imat); val[0] = mrc_slice_mat_mult(mat, imat, dim); slicePutVal(sout, i, j, val); } } free(imat); return(sout); }
/*! * Expands the input slice [sin] by the factors [xz] in X and [yz] in Y about * the center point [cx], [cy] and places the result in the slice [sout]. * Uses quadratic interpolation. For areas where * there is no image data, the slice mean is used to fill only the first * channel. Returns the new slice or NULL for error. */ int mrc_slice_zooms(Islice *sin, Islice *sout, double xz, double yz, double cx, double cy) { int i, j; Ival val; double x, y; double sbx, sby; if ((!xz) || (!yz)) return(1); sbx = (xz * cx) - ((double)sout->xsize * 0.5); sby = (yz * cy) - ((double)sout->ysize * 0.5); for(j = 0; j < sout->ysize; j++){ y = ((double)j / yz) + sby; for (i = 0; i < sout->xsize; i++){ x = ((double)i / xz) + sbx; sliceQuadInterpolate(sin, x, y, val); slicePutVal(sout, i, j, val); } } return(0); }
/*! * Converts the data in slice [s] from its current mode to [mode], allocating * a new data array as needed. Complex values are converted to others by * taking the magnitude. Values are converted to complex modes by setting the * real component to the value, and the imaginary component to 0. RGB values * are converted by taking a weighted sum of components. When converting to a * mode with integer or byte values, the data are truncated to fit within the * range of the new mode. Returns the new mode or -1 for error. */ int sliceNewMode(Islice *s, int mode) { Islice *ns; Ival val; int i, j; int default_copy = 0; int limit_val = 0; float minval, maxval; if (!s) return(-1); if (s->mode == mode) return(mode); ns = sliceCreate(s->xsize, s->ysize, mode); /* Set up limiting values */ if (mode == MRC_MODE_BYTE || mode == MRC_MODE_RGB) { limit_val = 1; minval = 0.; maxval = 255; } else if (mode == MRC_MODE_SHORT) { limit_val = 1; minval = -32768.; maxval = 32767.; } else if (mode == MRC_MODE_USHORT) { limit_val = 1; minval = 0.; maxval = 65535.; } if (!ns) return(-1); switch(s->mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: default_copy = 1; break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: val[1] = 0; default_copy = 1; break; case MRC_MODE_RGB: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); val[2] = val[1] = val[0]; slicePutVal(ns, i, j, val); } break; default: default_copy = 1; break; } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (float)sqrt(val[0] * val[0] + val[1] * val[1]); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: default_copy = 1; break; case MRC_MODE_RGB: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (float)sqrt(val[0] * val[0] + val[1] * val[1]); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); val[2] = val[1] = val[0]; slicePutVal(ns, i, j, val); } break; } break; case MRC_MODE_RGB: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (val[0] * 0.3f) + (val[1] * 0.59f) + (val[2] * 0.11f); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (val[0] * 0.3f) + (val[1] * 0.59f) + (val[2] * 0.11f); val[1] = 0; slicePutVal(ns, i, j, val); } break; default: default_copy = 1; break; } break; default: default_copy = 1; break; } if (default_copy){ for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } } free(s->data.b); /* 2/3/07: switch from copying ns to s to just setting data and mode */ s->data.b = ns->data.b; s->mode = mode; free(ns); return(mode); }
/* Read the required data volume */ Istack *grap_volume_read(MrcHeader *hin, ClipOptions *opt) { Istack *v; Islice *s; Ival val; int i, j, k, x, y, z; if (opt->dim == 2){ if (opt->iz == IP_DEFAULT) opt->iz = 0; if (opt->iz2 == IP_DEFAULT) opt->iz2 = hin->nz - 1; if (opt->iz2 == 0) opt->iz2 = opt->iz; if (opt->iz2 < opt->iz) opt->iz2 = opt->iz; opt->cz = ( opt->iz2 + opt->iz) / 2.; opt->iz = opt->iz2 - opt->iz + 1; } if (opt->ix == IP_DEFAULT) opt->ix = hin->nx; if (opt->iy == IP_DEFAULT) opt->iy = hin->ny; if (opt->iz == IP_DEFAULT) opt->iz = hin->nz; if (opt->cx == IP_DEFAULT) opt->cx = hin->nx / 2.; if (opt->cy == IP_DEFAULT) opt->cy = hin->ny / 2.; if (opt->cz == IP_DEFAULT) opt->cz = hin->nz / 2.; /* Do not set opt->pad yet, just pad with current mean */ val[0] = opt->pad; if (opt->pad == IP_DEFAULT) val[0] = hin->amean; val[1] = val[0]; val[2] = val[0]; /* Create volume and initialize to pad value. */ v = (Istack *)malloc(sizeof(Istack)); v->vol = (Islice **)malloc( opt->iz * sizeof(Islice *)); v->zsize = opt->iz; for (k = 0; k < opt->iz; k++) { v->vol[k] = sliceCreate(opt->ix, opt->iy, hin->mode); if (!v->vol[k]) return(NULL); for( j = 0; j < opt->iy; j++) for(i = 0; i < opt->ix; i++) slicePutVal(v->vol[k], i, j, val); v->vol[k]->mean = hin->amean; v->vol[k]->max = hin->amax; v->vol[k]->min = hin->amin; } s = sliceCreate(hin->nx, hin->ny, hin->mode); if (!s) return(NULL); /* Read slices in, copying just the part that is needed */ k = (int)floor(opt->cz - ((float)opt->iz * 0.5f)); /* printf("k = %d\n", k); */ for (z = 0; (k < hin->nz) && (z < opt->iz); k++, z++) { if (k >= 0) { if (mrc_read_slice((void *)s->data.b, hin->fp, hin, k, 'z')) return (NULL); j = (int)floor(opt->cy - opt->iy / 2.); for (y = 0; (j < hin->ny) && (y < opt->iy); j++, y++) { if (j >= 0) { i = (int)floor(opt->cx - opt->ix / 2.); x = 0; if (i < 0) { x = -i; i = 0; } for (; (i < hin->nx) && (x < opt->ix); i++, x++) { sliceGetVal(s, i, j, val); slicePutVal(v->vol[z], x, y, val); } } } } } sliceFree(s); return(v); }
/*! * Converts the data in [slice] to float mode. For complex data, the magnitude * is taken; for RGB data, a weighed sum of the components is taken. This * should be slightly more efficient than @sliceNewMode is. Returns -1 for * error. */ int sliceFloat(Islice *slice) { Islice *tsl; Ival val; int i, j; switch(slice->mode){ case SLICE_MODE_BYTE: case SLICE_MODE_SHORT: tsl = sliceCreate(slice->xsize, slice->ysize, SLICE_MODE_FLOAT); if (!tsl) return(-1); for(j = 0; j < slice->ysize; j++) for(i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); slicePutVal(tsl, i, j, val); } free(slice->data.b); slice->data.f = tsl->data.f; slice->mode = SLICE_MODE_FLOAT; free(tsl); break; case SLICE_MODE_FLOAT: break; case SLICE_MODE_COMPLEX_SHORT: case SLICE_MODE_COMPLEX_FLOAT: tsl = sliceCreate(slice->xsize, slice->ysize, SLICE_MODE_FLOAT); if (!tsl) return(-1); for(j = 0; j < slice->ysize; j++) for(i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); val[0] = (val[0] * val[0]) + (val[1] * val[1]); val[0] = sqrt(val[0]); slicePutVal(tsl, i, j, val); } free(slice->data.b); slice->data.f = tsl->data.f; slice->mode = SLICE_MODE_FLOAT; free(tsl); break; case SLICE_MODE_RGB: tsl = sliceCreate(slice->xsize, slice->ysize, SLICE_MODE_FLOAT); if (!tsl) return(-1); for(j = 0; j < slice->ysize; j++) for(i = 0; i < slice->xsize; i++){ sliceGetVal(slice, i, j, val); val[0] = val[0] * 0.3f + val[1] * 0.59f + val[2] * 0.11f; slicePutVal(tsl, i, j, val); } free(slice->data.b); slice->data.f = tsl->data.f; slice->mode = SLICE_MODE_FLOAT; free(tsl); break; default: return(-1); } return(0); }