Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
FloatProcessor.java
1 package ij.process;
2 
3 import java.util.*;
4 import java.awt.*;
5 import java.awt.image.*;
6 import ij.gui.*;
7 
9 public class FloatProcessor extends ImageProcessor {
10 
11  private float min, max, snapshotMin, snapshotMax;
12  private float[] pixels;
13  private byte[] pixels8;
14  private float[] snapshotPixels = null;
15  private byte[] LUT = null;
16  private float fillColor = Float.MAX_VALUE;
17  //private float bgColor = Float.MIN_VALUE;
18  private boolean fixedScale = false;
19 
22  public FloatProcessor(int width, int height, float[] pixels, ColorModel cm) {
23  if (pixels!=null && width*height!=pixels.length)
24  throw new IllegalArgumentException(WRONG_LENGTH);
25  this.width = width;
26  this.height = height;
27  this.pixels = pixels;
28  this.cm = cm;
29  resetRoi();
30  if (pixels!=null)
31  findMinAndMax();
32  }
33 
36  public FloatProcessor(int width, int height) {
37  this(width, height, new float[width*height], null);
38  }
39 
41  public FloatProcessor(int width, int height, int[] pixels) {
42  this(width, height);
43  for (int i=0; i<pixels.length; i++)
44  this.pixels[i] = (float)(pixels[i]);
45  findMinAndMax();
46  }
47 
49  public FloatProcessor(int width, int height, double[] pixels) {
50  this(width, height);
51  for (int i=0; i<pixels.length; i++)
52  this.pixels[i] = (float)pixels[i];
53  findMinAndMax();
54  }
55 
65  public void findMinAndMax() {
66  if (fixedScale)
67  return;
68  min = Float.MAX_VALUE;
69  max = -Float.MAX_VALUE;
70  for (int i=0; i < width*height; i++) {
71  float value = pixels[i];
72  if (!Float.isInfinite(value)) {
73  if (value<min)
74  min = value;
75  if (value>max)
76  max = value;
77  }
78  }
79  pixelsModified = true;
80  hideProgress();
81  }
82 
89  public void setMinAndMax(double min, double max) {
90  if (min==0.0 && max==0.0)
91  {resetMinAndMax(); return;}
92  this.min = (float)min;
93  this.max = (float)max;
94  fixedScale = true;
96  }
97 
101  public void resetMinAndMax() {
102  fixedScale = false;
103  findMinAndMax();
104  resetThreshold();
105  }
106 
108  public double getMin() {
109  return min;
110  }
111 
113  public double getMax() {
114  return max;
115  }
116 
117  public Image createImage() {
118  boolean firstTime = pixels8==null;
119  if (firstTime || !lutAnimation) {
120  // scale from float to 8-bits
121  int size = width*height;
122  if (pixels8==null)
123  pixels8 = new byte[size];
124  float value;
125  int ivalue;
126  float scale = 255f/(max-min);
127  for (int i=0; i<size; i++) {
128  value = pixels[i]-min;
129  if (value<0f) value = 0f;
130  ivalue = (int)(value*scale);
131  if (ivalue>255) ivalue = 255;
132  pixels8[i] = (byte)ivalue;
133  }
134  }
135  if (cm==null)
136  makeDefaultColorModel();
137  if (source==null || (ij.IJ.isMacintosh()&&(!ij.IJ.isJava2()||lutAnimation))) {
138  source = new MemoryImageSource(width, height, cm, pixels8, 0, width);
139  source.setAnimated(true);
140  source.setFullBufferUpdates(true);
141  img = Toolkit.getDefaultToolkit().createImage(source);
142  } else if (newPixels) {
143  source.newPixels(pixels8, cm, 0, width);
144  newPixels = false;
145  } else
146  source.newPixels();
147  lutAnimation = false;
148  return img;
149  }
150 
152  public ImageProcessor createProcessor(int width, int height) {
153  ImageProcessor ip2 = new FloatProcessor(width, height, new float[width*height], getColorModel());
154  ip2.setMinAndMax(getMin(), getMax());
155  return ip2;
156  }
157 
158  public void snapshot() {
159  snapshotWidth=width;
160  snapshotHeight=height;
161  snapshotMin=min;
162  snapshotMax=max;
163  if (snapshotPixels==null || (snapshotPixels!=null && snapshotPixels.length!=pixels.length))
164  snapshotPixels = new float[width * height];
165  System.arraycopy(pixels, 0, snapshotPixels, 0, width*height);
166  pixelsModified = false;
167  newSnapshot = true;
168  }
169 
170  public void reset() {
171  if (snapshotPixels==null)
172  return;
173  min=snapshotMin;
174  max=snapshotMax;
175  System.arraycopy(snapshotPixels,0,pixels,0,width*height);
176  }
177 
178  public void reset(ImageProcessor mask) {
179  if (mask==null || snapshotPixels==null)
180  return;
181  if (mask.getWidth()!=roiWidth||mask.getHeight()!=roiHeight)
182  throw new IllegalArgumentException(maskSizeError(mask));
183  byte[] mpixels = (byte[])mask.getPixels();
184  for (int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
185  int i = y * width + roiX;
186  int mi = my * roiWidth;
187  for (int x=roiX; x<(roiX+roiWidth); x++) {
188  if (mpixels[mi++]==0)
189  pixels[i] = snapshotPixels[i];
190  i++;
191  }
192  }
193  newSnapshot = true;
194  }
195 
198  public int getPixel(int x, int y) {
199  if (x>=0 && x<width && y>=0 && y<height)
200  return Float.floatToIntBits(pixels[y*width+x]);
201  else
202  return 0;
203  }
204 
208  public int[] getPixel(int x, int y, int[] iArray) {
209  if (iArray==null) iArray = new int[1];
210  iArray[0] = (int)getPixelValue(x, y);
211  return iArray;
212  }
213 
215  public void putPixel(int x, int y, int[] iArray) {
216  putPixelValue(x, y, iArray[0]);
217  }
218 
220  public double getInterpolatedPixel(double x, double y) {
221  if (x<0.0) x = 0.0;
222  if (x>=width-1.0) x = width-1.001;
223  if (y<0.0) y = 0.0;
224  if (y>=height-1.0) y = height-1.001;
225  return getInterpolatedPixel(x, y, pixels);
226  }
227 
230  public void putPixel(int x, int y, int value) {
231  if (x>=0 && x<width && y>=0 && y<height)
232  pixels[y*width + x] = Float.intBitsToFloat(value);
233  }
234 
236  public void putPixelValue(int x, int y, double value) {
237  if (x>=0 && x<width && y>=0 && y<height)
238  pixels[y*width + x] = (float)value;
239  }
240 
241  public float getPixelValue(int x, int y) {
242  if (x>=0 && x<width && y>=0 && y<height)
243  return pixels[y*width + x];
244  else
245  return 0f;
246  }
247 
249  public void drawPixel(int x, int y) {
250  if (x>=clipXMin && x<=clipXMax && y>=clipYMin && y<=clipYMax)
251  putPixel(x, y, Float.floatToIntBits(fillColor));
252  }
253 
256  public Object getPixels() {
257  return (Object)pixels;
258  }
259 
260  public Object getPixelsCopy() {
261  if (newSnapshot && snapshotPixels!=null)
262  return snapshotPixels;
263  else {
264  float[] pixels2 = new float[width*height];
265  System.arraycopy(pixels, 0, pixels2, 0, width*height);
266  return pixels2;
267  }
268  }
269 
270  public void setPixels(Object pixels) {
271  this.pixels = (float[])pixels;
272  resetPixels(pixels);
273  snapshotPixels = null;
274  if (pixels==null)
275  pixels8 = null;
276  }
277 
280  public void copyBits(ImageProcessor ip, int xloc, int yloc, int mode) {
281  //if (!(ip instanceof FloatProcessor))
282  // throw new IllegalArgumentException("32-bit (real) image required");
283  new FloatBlitter(this).copyBits(ip, xloc, yloc, mode);
284  }
285 
286  public void applyTable(int[] lut) {}
287 
288  private float[] getCopyOfPixels() {
289  if (pixelsModified) {
290  float[] pixelsCopy = new float[width * height];
291  System.arraycopy(pixels, 0, pixelsCopy, 0, width*height);
292  return pixelsCopy;
293  }
294  else
295  return snapshotPixels;
296  }
297 
298  private void process(int op, double value) {
299  float c, v1, v2;
300  boolean resetMinMax = roiWidth==width && roiHeight==height && !(op==FILL);
301  c = (float)value;
302  for (int y=roiY; y<(roiY+roiHeight); y++) {
303  int i = y * width + roiX;
304  for (int x=roiX; x<(roiX+roiWidth); x++) {
305  v1 = pixels[i];
306  switch(op) {
307  case INVERT:
308  v2 = max - (v1 - min);
309  break;
310  case FILL:
311  v2 = fillColor;
312  break;
313  case ADD:
314  v2 = v1 + c;
315  break;
316  case MULT:
317  v2 = v1 * c;
318  break;
319  case GAMMA:
320  if (v1<=0f)
321  v2 = 0f;
322  else
323  v2 = (float)Math.exp(c*Math.log(v1));
324  break;
325  case LOG:
326  if (v1<=0f)
327  v2 = 0f;
328  else
329  v2 = (float)Math.log(v1);
330  break;
331  case SQR:
332  v2 = v1*v1;
333  break;
334  case SQRT:
335  if (v1<=0f)
336  v2 = 0f;
337  else
338  v2 = (float)Math.sqrt(v1);
339  break;
340  case MINIMUM:
341  if (v1<value)
342  v2 = (int)value;
343  else
344  v2 = v1;
345  break;
346  case MAXIMUM:
347  if (v1>value)
348  v2 = (int)value;
349  else
350  v2 = v1;
351  break;
352  default:
353  v2 = v1;
354  }
355  pixels[i++] = v2;
356  }
357  if (y%20==0)
358  showProgress((double)(y-roiY)/roiHeight);
359  }
360  if (resetMinMax)
361  findMinAndMax();
362  }
363 
364  public void invert() {process(INVERT, 0.0);}
365  public void add(int value) {process(ADD, value);}
366  public void add(double value) {process(ADD, value);}
367  public void multiply(double value) {process(MULT, value);}
368  public void and(int value) {}
369  public void or(int value) {}
370  public void xor(int value) {}
371  public void gamma(double value) {process(GAMMA, value);}
372  public void log() {process(LOG, 0.0);}
373  public void sqr() {process(SQR, 0.0);}
374  public void sqrt() {process(SQRT, 0.0);}
375  public void min(double value) {process(MINIMUM, value);}
376  public void max(double value) {process(MAXIMUM, value);}
377 
378 
379 
381  public void fill() {process(FILL, 0.0);}
382 
386  public void fill(ImageProcessor mask) {
387  if (mask==null)
388  {fill(); return;}
389  if (mask.getWidth()!=roiWidth||mask.getHeight()!=roiHeight)
390  throw new IllegalArgumentException(maskSizeError(mask));
391  byte[] mpixels = (byte[])mask.getPixels();
392  for (int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
393  int i = y * width + roiX;
394  int mi = my * roiWidth;
395  for (int x=roiX; x<(roiX+roiWidth); x++) {
396  if (mpixels[mi++]!=0)
397  pixels[i] = fillColor;
398  i++;
399  }
400  }
401  }
402 
404  public void convolve3x3(int[] kernel) {
405  float p1, p2, p3, p4, p5, p6, p7, p8, p9;
406  float k1=kernel[0], k2=kernel[1], k3=kernel[2],
407  k4=kernel[3], k5=kernel[4], k6=kernel[5],
408  k7=kernel[6], k8=kernel[7], k9=kernel[8];
409 
410  float scale = 0f;
411  for (int i=0; i<kernel.length; i++)
412  scale += kernel[i];
413  if (scale==0) scale = 1f;
414  int inc = roiHeight/25;
415  if (inc<1) inc = 1;
416 
417  float[] pixels2 = (float[])getPixelsCopy();
418  int offset;
419  float sum;
420  int rowOffset = width;
421  for (int y=yMin; y<=yMax; y++) {
422  offset = xMin + y * width;
423  p1 = 0f;
424  p2 = pixels2[offset-rowOffset-1];
425  p3 = pixels2[offset-rowOffset];
426  p4 = 0f;
427  p5 = pixels2[offset-1];
428  p6 = pixels2[offset];
429  p7 = 0f;
430  p8 = pixels2[offset+rowOffset-1];
431  p9 = pixels2[offset+rowOffset];
432 
433  for (int x=xMin; x<=xMax; x++) {
434  p1 = p2; p2 = p3;
435  p3 = pixels2[offset-rowOffset+1];
436  p4 = p5; p5 = p6;
437  p6 = pixels2[offset+1];
438  p7 = p8; p8 = p9;
439  p9 = pixels2[offset+rowOffset+1];
440  sum = k1*p1 + k2*p2 + k3*p3
441  + k4*p4 + k5*p5 + k6*p6
442  + k7*p7 + k8*p8 + k9*p9;
443  sum /= scale;
444  pixels[offset++] = sum;
445  }
446  if (y%inc==0)
447  showProgress((double)(y-roiY)/roiHeight);
448  }
449  hideProgress();
450  }
451 
453  public void filter(int type) {
454  float p1, p2, p3, p4, p5, p6, p7, p8, p9;
455  int inc = roiHeight/25;
456  if (inc<1) inc = 1;
457 
458  float[] pixels2 = (float[])getPixelsCopy();
459  int offset;
460  float sum1, sum2;
461  int rowOffset = width;
462  for (int y=yMin; y<=yMax; y++) {
463  offset = xMin + y * width;
464  p1 = 0f;
465  p2 = pixels2[offset-rowOffset-1];
466  p3 = pixels2[offset-rowOffset];
467  p4 = 0f;
468  p5 = pixels2[offset-1];
469  p6 = pixels2[offset];
470  p7 = 0f;
471  p8 = pixels2[offset+rowOffset-1];
472  p9 = pixels2[offset+rowOffset];
473 
474  for (int x=xMin; x<=xMax; x++) {
475  p1 = p2; p2 = p3;
476  p3 = pixels2[offset-rowOffset+1];
477  p4 = p5; p5 = p6;
478  p6 = pixels2[offset+1];
479  p7 = p8; p8 = p9;
480  p9 = pixels2[offset+rowOffset+1];
481 
482  switch (type) {
483  case BLUR_MORE:
484  pixels[offset++] = (p1+p2+p3+p4+p5+p6+p7+p8+p9)/9f;
485  break;
486  case FIND_EDGES:
487  sum1 = p1 + 2*p2 + p3 - p7 - 2*p8 - p9;
488  sum2 = p1 + 2*p4 + p7 - p3 - 2*p6 - p9;
489  pixels[offset++] = (float)Math.sqrt(sum1*sum1 + sum2*sum2);
490  break;
491  }
492  }
493  if (y%inc==0)
494  showProgress((double)(y-roiY)/roiHeight);
495  }
496  if (type==BLUR_MORE)
497  hideProgress();
498  else
499  findMinAndMax();
500  }
501 
505  public void rotate(double angle) {
506  float[] pixels2 = (float[])getPixelsCopy();
507  double centerX = roiX + (roiWidth-1)/2.0;
508  double centerY = roiY + (roiHeight-1)/2.0;
509  int xMax = roiX + this.roiWidth - 1;
510 
511  double angleRadians = -angle/(180.0/Math.PI);
512  double ca = Math.cos(angleRadians);
513  double sa = Math.sin(angleRadians);
514  double tmp1 = centerY*sa-centerX*ca;
515  double tmp2 = -centerX*sa-centerY*ca;
516  double tmp3, tmp4, xs, ys;
517  int index, ixs, iys;
518  double dwidth=width,dheight=height;
519  double xlimit = width-1.0, xlimit2 = width-1.001;
520  double ylimit = height-1.0, ylimit2 = height-1.001;
521 
522  for (int y=roiY; y<(roiY + roiHeight); y++) {
523  index = y*width + roiX;
524  tmp3 = tmp1 - y*sa + centerX;
525  tmp4 = tmp2 + y*ca + centerY;
526  for (int x=roiX; x<=xMax; x++) {
527  xs = x*ca + tmp3;
528  ys = x*sa + tmp4;
529  if ((xs>=-0.01) && (xs<dwidth) && (ys>=-0.01) && (ys<dheight)) {
530  if (interpolate) {
531  if (xs<0.0) xs = 0.0;
532  if (xs>=xlimit) xs = xlimit2;
533  if (ys<0.0) ys = 0.0;
534  if (ys>=ylimit) ys = ylimit2;
535  pixels[index++] = (float)(getInterpolatedPixel(xs, ys, pixels2)+0.5);
536  } else {
537  ixs = (int)(xs+0.5);
538  iys = (int)(ys+0.5);
539  if (ixs>=width) ixs = width - 1;
540  if (iys>=height) iys = height -1;
541  pixels[index++] = pixels2[width*iys+ixs];
542  }
543  } else
544  pixels[index++] = 0;
545  }
546  if (y%20==0)
547  showProgress((double)(y-roiY)/roiHeight);
548  }
549  hideProgress();
550  }
551 
552  public void flipVertical() {
553  int index1,index2;
554  float tmp;
555  for (int y=0; y<roiHeight/2; y++) {
556  index1 = (roiY+y)*width+roiX;
557  index2 = (roiY+roiHeight-1-y)*width+roiX;
558  for (int i=0; i<roiWidth; i++) {
559  tmp = pixels[index1];
560  pixels[index1++] = pixels[index2];
561  pixels[index2++] = tmp;
562  }
563  }
564  newSnapshot = false;
565  }
566 
567  public void noise(double range) {
568  Random rnd=new Random();
569 
570  for (int y=roiY; y<(roiY+roiHeight); y++) {
571  int i = y * width + roiX;
572  for (int x=roiX; x<(roiX+roiWidth); x++) {
573  float RandomBrightness = (float)(rnd.nextGaussian()*range);
574  pixels[i] = pixels[i] + RandomBrightness;
575  i++;
576  }
577  if (y%20==0)
578  showProgress((double)(y-roiY)/roiHeight);
579  }
580  findMinAndMax();
581  }
582 
583  public ImageProcessor crop() {
584  ImageProcessor ip2 = createProcessor(roiWidth, roiHeight);
585  float[] pixels2 = (float[])ip2.getPixels();
586  for (int ys=roiY; ys<roiY+roiHeight; ys++) {
587  int offset1 = (ys-roiY)*roiWidth;
588  int offset2 = ys*width+roiX;
589  for (int xs=0; xs<roiWidth; xs++)
590  pixels2[offset1++] = pixels[offset2++];
591  }
592  return ip2;
593  }
594 
598  public void scale(double xScale, double yScale) {
599  double xCenter = roiX + roiWidth/2.0;
600  double yCenter = roiY + roiHeight/2.0;
601  int xmin, xmax, ymin, ymax;
602 
603  if ((xScale>1.0) && (yScale>1.0)) {
604  //expand roi
605  xmin = (int)(xCenter-(xCenter-roiX)*xScale);
606  if (xmin<0) xmin = 0;
607  xmax = xmin + (int)(roiWidth*xScale) - 1;
608  if (xmax>=width) xmax = width - 1;
609  ymin = (int)(yCenter-(yCenter-roiY)*yScale);
610  if (ymin<0) ymin = 0;
611  ymax = ymin + (int)(roiHeight*yScale) - 1;
612  if (ymax>=height) ymax = height - 1;
613  } else {
614  xmin = roiX;
615  xmax = roiX + roiWidth - 1;
616  ymin = roiY;
617  ymax = roiY + roiHeight - 1;
618  }
619  float[] pixels2 = (float[])getPixelsCopy();
620  boolean checkCoordinates = (xScale < 1.0) || (yScale < 1.0);
621  int index1, index2, xsi, ysi;
622  double ys, xs;
623  double xlimit = width-1.0, xlimit2 = width-1.001;
624  double ylimit = height-1.0, ylimit2 = height-1.001;
625  for (int y=ymin; y<=ymax; y++) {
626  ys = (y-yCenter)/yScale + yCenter;
627  ysi = (int)ys;
628  if (ys<0.0) ys = 0.0;
629  if (ys>=ylimit) ys = ylimit2;
630  index1 = y*width + xmin;
631  index2 = width*(int)ys;
632  for (int x=xmin; x<=xmax; x++) {
633  xs = (x-xCenter)/xScale + xCenter;
634  xsi = (int)xs;
635  if (checkCoordinates && ((xsi<xmin) || (xsi>xmax) || (ysi<ymin) || (ysi>ymax)))
636  pixels[index1++] = (float)min;
637  else {
638  if (interpolate) {
639  if (xs<0.0) xs = 0.0;
640  if (xs>=xlimit) xs = xlimit2;
641  pixels[index1++] = (float)getInterpolatedPixel(xs, ys, pixels2);
642  } else
643  pixels[index1++] = pixels2[index2+xsi];
644  }
645  }
646  if (y%20==0)
647  showProgress((double)(y-ymin)/height);
648  }
649  hideProgress();
650  }
651 
653  private final double getInterpolatedPixel(double x, double y, float[] pixels) {
654  int xbase = (int)x;
655  int ybase = (int)y;
656  double xFraction = x - xbase;
657  double yFraction = y - ybase;
658  int offset = ybase * width + xbase;
659  double lowerLeft = pixels[offset];
660  double lowerRight = pixels[offset + 1];
661  double upperRight = pixels[offset + width + 1];
662  double upperLeft = pixels[offset + width];
663  double upperAverage = upperLeft + xFraction * (upperRight - upperLeft);
664  double lowerAverage = lowerLeft + xFraction * (lowerRight - lowerLeft);
665  return lowerAverage + yFraction * (upperAverage - lowerAverage);
666  }
667 
669  public ImageProcessor resize(int dstWidth, int dstHeight) {
670  double srcCenterX = roiX + roiWidth/2.0;
671  double srcCenterY = roiY + roiHeight/2.0;
672  double dstCenterX = dstWidth/2.0;
673  double dstCenterY = dstHeight/2.0;
674  double xScale = (double)dstWidth/roiWidth;
675  double yScale = (double)dstHeight/roiHeight;
676  if (interpolate) {
677  dstCenterX += xScale/2.0;
678  dstCenterY += yScale/2.0;
679  }
680  ImageProcessor ip2 = createProcessor(dstWidth, dstHeight);
681  float[] pixels2 = (float[])ip2.getPixels();
682  double xs, ys;
683  double xlimit = width-1.0, xlimit2 = width-1.001;
684  double ylimit = height-1.0, ylimit2 = height-1.001;
685  int index1, index2;
686  for (int y=0; y<=dstHeight-1; y++) {
687  ys = (y-dstCenterY)/yScale + srcCenterY;
688  if (interpolate) {
689  if (ys<0.0) ys = 0.0;
690  if (ys>=ylimit) ys = ylimit2;
691  }
692  index1 = width*(int)ys;
693  index2 = y*dstWidth;
694  for (int x=0; x<=dstWidth-1; x++) {
695  xs = (x-dstCenterX)/xScale + srcCenterX;
696  if (interpolate) {
697  if (xs<0.0) xs = 0.0;
698  if (xs>=xlimit) xs = xlimit2;
699  pixels2[index2++] = (float)getInterpolatedPixel(xs, ys, pixels);
700  } else
701  pixels2[index2++] = pixels[index1+(int)xs];
702  }
703  if (y%20==0)
704  showProgress((double)y/dstHeight);
705  }
706  hideProgress();
707  return ip2;
708  }
709 
711  public void setColor(Color color) {
712  int bestIndex = getBestIndex(color);
713  if (bestIndex>0 && getMin()==0.0 && getMax()==0.0) {
714  fillColor = bestIndex;
715  setMinAndMax(0.0,255.0);
716  } else if (bestIndex==0 && getMin()>0.0 && (color.getRGB()&0xffffff)==0)
717  fillColor = 0f;
718  else
719  fillColor = (float)(min + (max-min)*(bestIndex/255.0));
720  }
721 
723  public void setValue(double value) {
724  fillColor = (float)value;
725  }
726 
727  public void setThreshold(double minThreshold, double maxThreshold, int lutUpdate) {
728  if (minThreshold!=NO_THRESHOLD && max>min) {
729  double minT = Math.round(((minThreshold-min)/(max-min))*255.0);
730  double maxT = Math.round(((maxThreshold-min)/(max-min))*255.0);
731  super.setThreshold(minT, maxT, lutUpdate);
732  this.minThreshold = minThreshold;
733  this.maxThreshold = maxThreshold;
734  } else
735  super.resetThreshold();
736  }
737 
739  public void convolve(float[] kernel, int kernelWidth, int kernelHeight) {
740  snapshot();
741  new ij.plugin.filter.Convolver().convolve(this, kernel, kernelWidth, kernelHeight);
742  }
743 
745  public void threshold(int level) {}
747  public void autoThreshold() {}
749  public void medianFilter() {}
751  public int[] getHistogram() {return null;}
753  public void erode() {}
755  public void dilate() {}
756 
757 
758 }
759