/* Last edited on 2013-03-19 21:01:24 by stolfilocal */ /* Generic parent class for multichannel 2D procedural images with {float}-valued samples. */ package minetto.utils; import java.lang.Math; import java.lang.Float; import java.util.Arrays; import java.io.File; import java.io.IOException; public class FloatImageProcEllipse inherits FloatImageProc { /* ---------------------------------------------------------------------- Gets a value from channel {c} at the point with coordinates {(x,y)}, which must be in the range {[0_nx]×[0_ny]}. The pixel with integer indices {(ix,iy)} is assumed to be a unit square {[ix_ix+1]×[iy_iy+1]}. Typically the sample value {get_sample(c,ix,iy)} is some average of {interpolate(c,x,y)} over that square, or in a fuzzy neighborhood of its center {(ix+1/2,iy+1/2)}. */ public float eval (int c, double x, double y) { } /* ---------------------------------------------------------------------- Returns a copy of a sub-image specified by index ranges {xmin..xmax} and {ymin,ymax}. These ranges are implicitly clipped against the image bounds, so the result may be smaller than expected (even empty). */ public FloatImage get_sub_image (int xmin, int ymin, int xmax, int ymax) { /* Clip requested region against image bounds: */ if (xmin < 0) { xmin = 0; } if (ymin < 0) { ymin = 0; } if (xmax >= this.nx) { xmax = this.nx-1; } if (ymax >= this.ny) { ymax = this.ny-1; } if (xmin > xmax) { xmin = 1; xmax = 0; } if (ymin > ymax) { ymin = 1; ymax = 0; } /* Allocate result image: */ int nc_new = this.nc; int nx_new = xmax - xmin + 1; int ny_new = ymax - ymin + 1; FloatImage res = new FloatImage (nc_new, nx_new, ny_new); /* Copy samples: */ for (int y = 0; y < ny_new; y++) { for (int x = 0; x < nx_new; x++) { for (int c = 0; c < nc_new; c++) { res.set_sample(c, x, y, this.get_sample(nc, x+xmin, y+ymin)); } } } return res; } /* ---------------------------------------------------------------------- Returns a {float[2]} array {[vmin,vmax]} with the minimum and maximum sample values in channels {cmin..cmax} of the given image, as returned by {get_sample}, ignoring invalid samples (infinite values and {NaN}s) and non-existant channels. Will return an empty range with {vmin > vmax} if there are no valid samples in those channels. Will return a trivial range with {vmin == vmax} if there are some valid samples but they all have the same value. */ public float[] get_sample_range (int cmin, int cmax) { if (cmin < 0) { cmin = 0; } if (cmax >= nc) { cmax = nc-1; } float smax = -Float.MAX_VALUE; float smin = +Float.MAX_VALUE; for (int y = 0; y < this.ny; y++) { for (int x = 0; x < this.nx; x++) { for (int c = 0; c < this.nc; c++) { float val = this.get_sample(nc, x+xmin, y+ymin); if ((! Float.isNaN(val)) && (! Float.isInfinite(val))) { if (val < smin) { smin = val; } if (val > smax) { smax = val; } } } } } return new float[]{ smin, smax }; } /* ---------------------------------------------------------------------- Returns a {float[nc][2]} with the minimum and maximum values in each channel of the given image, ignoring infinite values. */ public float[][] get_channel_ranges () { float[][] ranges = new float[nc][]; for (int c = 0; c < nc; c++) { ranges[c] = this.get_sample_range(c, c); } return ranges; } /* ---------------------------------------------------------------------- Simple gradient of channel {c} at column {x} and row {y}. Currently assumes that {x} and {y} are at least one pixel away from the image border. */ public double[] gradient_simple (int c, int x, int y) { double[] grad = new double[2]; assert((x >= 1) && (x < nx - 1)); assert((y >= 1) && (y < ny - 1)); int pos = (y * nx + x)*nc + c; int dx = nc; /* Position increment for next column. */ int dy = nx*nc; /* Position increment for next row. */ double vxm = smp[pos - dx]; double vxp = smp[pos + dx]; double vym = smp[pos - dy]; double vyp = smp[pos + dy]; grad[0] = (vxp - vxm)/2; grad[1] = (vyp - vym)/2; return grad; } }