5 import java.awt.image.*;
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;
18 private boolean fixedScale =
false;
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);
37 this(width, height,
new float[width*height], null);
43 for (
int i=0; i<pixels.length; i++)
44 this.pixels[i] = (
float)(pixels[i]);
51 for (
int i=0; i<pixels.length; i++)
52 this.pixels[i] = (
float)pixels[i];
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)) {
79 pixelsModified =
true;
90 if (min==0.0 && max==0.0)
92 this.min = (float)min;
93 this.max = (float)max;
118 boolean firstTime = pixels8==null;
119 if (firstTime || !lutAnimation) {
121 int size = width*height;
123 pixels8 =
new byte[size];
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;
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);
147 lutAnimation =
false;
160 snapshotHeight=height;
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;
171 if (snapshotPixels==null)
175 System.arraycopy(snapshotPixels,0,pixels,0,width*height);
179 if (mask==null || snapshotPixels==null)
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];
199 if (x>=0 && x<width && y>=0 && y<height)
200 return Float.floatToIntBits(pixels[y*width+x]);
208 public int[]
getPixel(
int x,
int y,
int[] iArray) {
209 if (iArray==null) iArray =
new int[1];
222 if (x>=width-1.0) x = width-1.001;
224 if (y>=height-1.0) y = height-1.001;
231 if (x>=0 && x<width && y>=0 && y<height)
232 pixels[y*width + x] = Float.intBitsToFloat(value);
237 if (x>=0 && x<width && y>=0 && y<height)
238 pixels[y*width + x] = (float)value;
242 if (x>=0 && x<width && y>=0 && y<height)
243 return pixels[y*width + x];
250 if (x>=clipXMin && x<=clipXMax && y>=clipYMin && y<=clipYMax)
251 putPixel(x, y, Float.floatToIntBits(fillColor));
257 return (Object)pixels;
261 if (newSnapshot && snapshotPixels!=null)
262 return snapshotPixels;
264 float[] pixels2 =
new float[width*height];
265 System.arraycopy(pixels, 0, pixels2, 0, width*height);
271 this.pixels = (
float[])pixels;
273 snapshotPixels = null;
288 private float[] getCopyOfPixels() {
289 if (pixelsModified) {
290 float[] pixelsCopy =
new float[width * height];
291 System.arraycopy(pixels, 0, pixelsCopy, 0, width*height);
295 return snapshotPixels;
298 private void process(
int op,
double value) {
300 boolean resetMinMax = roiWidth==width && roiHeight==height && !(op==FILL);
302 for (
int y=roiY; y<(roiY+roiHeight); y++) {
303 int i = y * width + roiX;
304 for (
int x=roiX; x<(roiX+roiWidth); x++) {
308 v2 = max - (v1 - min);
323 v2 = (float)Math.exp(c*Math.log(v1));
329 v2 = (float)Math.log(v1);
338 v2 = (float)Math.sqrt(v1);
358 showProgress((
double)(y-roiY)/roiHeight);
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);}
381 public void fill() {process(FILL, 0.0);}
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;
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];
411 for (
int i=0; i<kernel.length; i++)
413 if (scale==0) scale = 1f;
414 int inc = roiHeight/25;
420 int rowOffset = width;
421 for (
int y=yMin; y<=yMax; y++) {
422 offset = xMin + y * width;
424 p2 = pixels2[offset-rowOffset-1];
425 p3 = pixels2[offset-rowOffset];
427 p5 = pixels2[offset-1];
428 p6 = pixels2[offset];
430 p8 = pixels2[offset+rowOffset-1];
431 p9 = pixels2[offset+rowOffset];
433 for (
int x=xMin; x<=xMax; x++) {
435 p3 = pixels2[offset-rowOffset+1];
437 p6 = pixels2[offset+1];
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;
444 pixels[offset++] = sum;
447 showProgress((
double)(y-roiY)/roiHeight);
454 float p1, p2, p3, p4, p5, p6, p7, p8, p9;
455 int inc = roiHeight/25;
461 int rowOffset = width;
462 for (
int y=yMin; y<=yMax; y++) {
463 offset = xMin + y * width;
465 p2 = pixels2[offset-rowOffset-1];
466 p3 = pixels2[offset-rowOffset];
468 p5 = pixels2[offset-1];
469 p6 = pixels2[offset];
471 p8 = pixels2[offset+rowOffset-1];
472 p9 = pixels2[offset+rowOffset];
474 for (
int x=xMin; x<=xMax; x++) {
476 p3 = pixels2[offset-rowOffset+1];
478 p6 = pixels2[offset+1];
480 p9 = pixels2[offset+rowOffset+1];
484 pixels[offset++] = (p1+p2+p3+p4+p5+p6+p7+p8+p9)/9f;
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);
494 showProgress((
double)(y-roiY)/roiHeight);
507 double centerX = roiX + (roiWidth-1)/2.0;
508 double centerY = roiY + (roiHeight-1)/2.0;
509 int xMax = roiX + this.roiWidth - 1;
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;
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;
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++) {
529 if ((xs>=-0.01) && (xs<dwidth) && (ys>=-0.01) && (ys<dheight)) {
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;
539 if (ixs>=width) ixs = width - 1;
540 if (iys>=height) iys = height -1;
541 pixels[index++] = pixels2[width*iys+ixs];
547 showProgress((
double)(y-roiY)/roiHeight);
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;
568 Random rnd=
new Random();
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;
578 showProgress((
double)(y-roiY)/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++];
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;
603 if ((xScale>1.0) && (yScale>1.0)) {
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;
615 xmax = roiX + roiWidth - 1;
617 ymax = roiY + roiHeight - 1;
620 boolean checkCoordinates = (xScale < 1.0) || (yScale < 1.0);
621 int index1, index2, xsi, ysi;
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;
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;
635 if (checkCoordinates && ((xsi<xmin) || (xsi>xmax) || (ysi<ymin) || (ysi>ymax)))
636 pixels[index1++] = (
float)min;
639 if (xs<0.0) xs = 0.0;
640 if (xs>=xlimit) xs = xlimit2;
643 pixels[index1++] = pixels2[index2+xsi];
647 showProgress((
double)(y-ymin)/height);
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);
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;
677 dstCenterX += xScale/2.0;
678 dstCenterY += yScale/2.0;
681 float[] pixels2 = (
float[])ip2.
getPixels();
683 double xlimit = width-1.0, xlimit2 = width-1.001;
684 double ylimit = height-1.0, ylimit2 = height-1.001;
686 for (
int y=0; y<=dstHeight-1; y++) {
687 ys = (y-dstCenterY)/yScale + srcCenterY;
689 if (ys<0.0) ys = 0.0;
690 if (ys>=ylimit) ys = ylimit2;
692 index1 = width*(int)ys;
694 for (
int x=0; x<=dstWidth-1; x++) {
695 xs = (x-dstCenterX)/xScale + srcCenterX;
697 if (xs<0.0) xs = 0.0;
698 if (xs>=xlimit) xs = xlimit2;
701 pixels2[index2++] = pixels[index1+(int)xs];
704 showProgress((
double)y/dstHeight);
714 fillColor = bestIndex;
716 }
else if (bestIndex==0 &&
getMin()>0.0 && (color.getRGB()&0xffffff)==0)
719 fillColor = (float)(min + (max-min)*(bestIndex/255.0));
724 fillColor = (float)value;
727 public void setThreshold(
double minThreshold,
double maxThreshold,
int lutUpdate) {
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;
735 super.resetThreshold();
739 public void convolve(
float[] kernel,
int kernelWidth,
int kernelHeight) {
741 new ij.plugin.filter.Convolver().convolve(
this, kernel, kernelWidth, kernelHeight);