5 import java.awt.image.*;
12 private int min, max, snapshotMin, snapshotMax;
13 private short[] pixels;
14 private short[] snapshotPixels;
15 private byte[] pixels8;
17 private boolean fixedScale;
21 public ShortProcessor(
int width,
int height,
short[] pixels, ColorModel cm) {
22 if (pixels!=null && width*height!=pixels.length)
23 throw new IllegalArgumentException(WRONG_LENGTH);
37 this(width, height,
new short[width*height], null);
42 public ShortProcessor(
int width,
int height,
short[] pixels, ColorModel cm,
boolean unsigned) {
43 this(width, height, pixels, cm);
52 public void findMinAndMax() {
55 int size = width*height;
59 for (
int i=0; i<size; i++) {
60 value = pixels[i]&0xffff;
72 boolean firstTime = pixels8==null;
73 if (firstTime || !lutAnimation) {
75 int size = width*height;
77 pixels8 =
new byte[size];
80 double scale = 256.0/(max-min+1);
81 for (
int i=0; i<size; i++) {
82 value = (pixels[i]&0xffff)-min;
83 if (value<0) value = 0;
84 value = (int)(value*scale);
85 if (value>255) value = 255;
86 pixels8[i] = (byte)value;
90 makeDefaultColorModel();
91 if (source==null || (ij.IJ.isMacintosh()&&(!ij.IJ.isJava2()||lutAnimation))) {
92 source =
new MemoryImageSource(width, height, cm, pixels8, 0, width);
93 source.setAnimated(
true);
94 source.setFullBufferUpdates(
true);
95 img = Toolkit.getDefaultToolkit().createImage(source);
96 }
else if (newPixels) {
97 source.newPixels(pixels8, cm, 0, width);
101 lutAnimation =
false;
114 snapshotHeight=height;
117 if (snapshotPixels==null || (snapshotPixels!=null && snapshotPixels.length!=pixels.length))
118 snapshotPixels =
new short[width * height];
119 System.arraycopy(pixels, 0, snapshotPixels, 0, width*height);
124 if (snapshotPixels==null)
128 System.arraycopy(snapshotPixels, 0, pixels, 0, width*height);
133 if (mask==null || snapshotPixels==null)
136 throw new IllegalArgumentException(maskSizeError(mask));
137 byte[] mpixels = (byte[])mask.
getPixels();
138 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
139 int i = y * width + roiX;
140 int mi = my * roiWidth;
141 for (
int x=roiX; x<(roiX+roiWidth); x++) {
142 if (mpixels[mi++]==0)
143 pixels[i] = snapshotPixels[i];
171 if (min==0.0 && max==0.0)
193 if (x>=0 && x<width && y>=0 && y<height)
194 return pixels[y*width+x]&0xffff;
202 if (x>=width-1.0) x = width-1.001;
204 if (y>=height-1.0) y = height-1.001;
215 return cTable[(int)(value+0.5)];
223 if (x>=0 && x<width && y>=0 && y<height) {
224 if (value>65535) value = 65535;
225 if (value<0) value = 0;
226 pixels[y*width + x] = (short)value;
235 if (x>=0 && x<width && y>=0 && y<height) {
240 pixels[y*width + x] = (short)(value+0.5);
246 if (x>=clipXMin && x<=clipXMax && y>=clipYMin && y<=clipYMax)
251 if (x>=0 && x<width && y>=0 && y<height) {
253 return pixels[y*width + x]&0xffff;
255 return cTable[pixels[y*width + x]&0xffff];
264 return (Object)pixels;
271 return snapshotPixels;
273 short[] pixels2 =
new short[width*height];
274 System.arraycopy(pixels, 0, pixels2, 0, width*height);
280 this.pixels = (
short[])pixels;
282 snapshotPixels = null;
287 void getRow2(
int x,
int y,
int[] data,
int length) {
289 for (
int i=0; i<length; i++)
290 data[i] = pixels[y*width+x+i]&0xffff;
293 void putColumn2(
int x,
int y,
int[] data,
int length) {
295 for (
int i=0; i<length; i++)
296 pixels[(y+i)*width+x] = (short)data[i];
303 throw new IllegalArgumentException(
"16-bit image required");
309 if (lut.length!=65536)
310 throw new IllegalArgumentException(
"lut.length!=65536");
311 int lineStart, lineEnd, v;
312 for (
int y=roiY; y<(roiY+roiHeight); y++) {
313 lineStart = y * width + roiX;
314 lineEnd = lineStart + roiWidth;
315 for (
int i=lineEnd; --i>=lineStart;) {
316 v = lut[pixels[i]&0xffff];
317 pixels[i] = (short)v;
323 private void process(
int op,
double value) {
325 double range = max-min;
326 boolean resetMinMax = roiWidth==width && roiHeight==height && !(op==FILL);
328 for (
int y=roiY; y<(roiY+roiHeight); y++) {
329 int i = y * width + roiX;
330 for (
int x=roiX; x<(roiX+roiWidth); x++) {
331 v1 = pixels[i]&0xffff;
334 v2 = max - (v1 - min);
340 v2 = v1 + (int)value;
343 v2 = (int)Math.round(v1 * value);
346 v2 = v1 & (int)value;
349 v2 = v1 | (int)value;
352 v2 = v1 ^ (int)value;
355 if (range<=0.0 || v1==min)
358 v2 = (int)(Math.exp(value*Math.log((v1-min)/range))*range+min);
364 v2 = (int)(Math.log(v1)*(max/Math.log(max)));
370 v2 = (int)Math.sqrt(v1);
391 pixels[i++] = (short)v2;
394 showProgress((
double)(y-roiY)/roiHeight);
401 public void invert() {
403 process(INVERT, 0.0);
406 public void add(
int value) {process(ADD, value);}
407 public void add(
double value) {process(ADD, value);}
408 public void multiply(
double value) {process(MULT, value);}
409 public void and(
int value) {process(AND, value);}
410 public void or(
int value) {process(OR, value);}
411 public void xor(
int value) {process(XOR, value);}
412 public void gamma(
double value) {process(GAMMA, value);}
413 public void log() {process(LOG, 0.0);}
414 public void sqr() {process(SQR, 0.0);}
415 public void sqrt() {process(SQRT, 0.0);}
416 public void min(
double value) {process(MINIMUM, value);}
417 public void max(
double value) {process(MAXIMUM, value);}
431 throw new IllegalArgumentException(maskSizeError(mask));
432 byte[] mpixels = (byte[])mask.
getPixels();
433 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
434 int i = y * width + roiX;
435 int mi = my * roiWidth;
436 for (
int x=roiX; x<(roiX+roiWidth); x++) {
437 if (mpixels[mi++]!=0)
438 pixels[i] = (short)fgColor;
449 int k1=kernel[0], k2=kernel[1], k3=kernel[2],
450 k4=kernel[3], k5=kernel[4], k6=kernel[5],
451 k7=kernel[6], k8=kernel[7], k9=kernel[8];
454 for (
int i=0; i<kernel.length; i++)
456 if (scale==0) scale = 1;
457 int inc = roiHeight/25;
462 int rowOffset = width;
463 for (
int y=yMin; y<=yMax; y++) {
464 offset = xMin + y * width;
466 p2 = pixels2[offset-rowOffset-1]&0xffff;
467 p3 = pixels2[offset-rowOffset]&0xffff;
469 p5 = pixels2[offset-1]&0xffff;
470 p6 = pixels2[offset]&0xffff;
472 p8 = pixels2[offset+rowOffset-1]&0xffff;
473 p9 = pixels2[offset+rowOffset]&0xffff;
475 for (
int x=xMin; x<=xMax; x++) {
477 p3 = pixels2[offset-rowOffset+1]&0xffff;
479 p6 = pixels2[offset+1]&0xffff;
481 p9 = pixels2[offset+rowOffset+1]&0xffff;
482 sum = k1*p1 + k2*p2 + k3*p3
483 + k4*p4 + k5*p5 + k6*p6
484 + k7*p7 + k8*p8 + k9*p9;
486 if(sum>65535) sum = 65535;
488 pixels[offset++] = (short)sum;
491 showProgress((
double)(y-roiY)/roiHeight);
498 int p1, p2, p3, p4, p5, p6, p7, p8, p9;
499 int inc = roiHeight/25;
503 int offset, sum1, sum2, sum=0;
504 int rowOffset = width;
505 for (
int y=yMin; y<=yMax; y++) {
506 offset = xMin + y * width;
508 p2 = pixels2[offset-rowOffset-1]&0xffff;
509 p3 = pixels2[offset-rowOffset]&0xffff;
511 p5 = pixels2[offset-1]&0xffff;
512 p6 = pixels2[offset]&0xffff;
514 p8 = pixels2[offset+rowOffset-1]&0xffff;
515 p9 = pixels2[offset+rowOffset]&0xffff;
517 for (
int x=xMin; x<=xMax; x++) {
519 p3 = pixels2[offset-rowOffset+1]&0xffff;
521 p6 = pixels2[offset+1]&0xffff;
523 p9 = pixels2[offset+rowOffset+1]&0xffff;
527 sum = (p1+p2+p3+p4+p5+p6+p7+p8+p9)/9;
530 sum1 = p1 + 2*p2 + p3 - p7 - 2*p8 - p9;
531 sum2 = p1 + 2*p4 + p7 - p3 - 2*p6 - p9;
532 sum = (int)Math.sqrt(sum1*sum1 + sum2*sum2);
536 pixels[offset++] = (short)sum;
539 showProgress((
double)(y-roiY)/roiHeight);
552 double centerX = roiX + (roiWidth-1)/2.0;
553 double centerY = roiY + (roiHeight-1)/2.0;
554 int xMax = roiX + this.roiWidth - 1;
556 double angleRadians = -angle/(180.0/Math.PI);
557 double ca = Math.cos(angleRadians);
558 double sa = Math.sin(angleRadians);
559 double tmp1 = centerY*sa-centerX*ca;
560 double tmp2 = -centerX*sa-centerY*ca;
561 double tmp3, tmp4, xs, ys;
563 double dwidth=width,dheight=height;
564 double xlimit = width-1.0, xlimit2 = width-1.001;
565 double ylimit = height-1.0, ylimit2 = height-1.001;
567 int background = cTable!=null && cTable[0]==-32768?32768:0;
569 for (
int y=roiY; y<(roiY + roiHeight); y++) {
570 index = y*width + roiX;
571 tmp3 = tmp1 - y*sa + centerX;
572 tmp4 = tmp2 + y*ca + centerY;
573 for (
int x=roiX; x<=xMax; x++) {
576 if ((xs>=-0.01) && (xs<dwidth) && (ys>=-0.01) && (ys<dheight)) {
578 if (xs<0.0) xs = 0.0;
579 if (xs>=xlimit) xs = xlimit2;
580 if (ys<0.0) ys = 0.0;
581 if (ys>=ylimit) ys = ylimit2;
586 if (ixs>=width) ixs = width - 1;
587 if (iys>=height) iys = height -1;
588 pixels[index++] = pixels2[width*iys+ixs];
591 pixels[index++] = (short)background;
594 showProgress((
double)(y-roiY)/roiHeight);
602 for (
int y=0; y<roiHeight/2; y++) {
603 index1 = (roiY+y)*width+roiX;
604 index2 = (roiY+roiHeight-1-y)*width+roiX;
605 for (
int i=0; i<roiWidth; i++) {
606 tmp = pixels[index1];
607 pixels[index1++] = pixels[index2];
608 pixels[index2++] = tmp;
617 public void scale(
double xScale,
double yScale) {
618 double xCenter = roiX + roiWidth/2.0;
619 double yCenter = roiY + roiHeight/2.0;
620 int xmin, xmax, ymin, ymax;
622 if ((xScale>1.0) && (yScale>1.0)) {
624 xmin = (int)(xCenter-(xCenter-roiX)*xScale);
625 if (xmin<0) xmin = 0;
626 xmax = xmin + (int)(roiWidth*xScale) - 1;
627 if (xmax>=width) xmax = width - 1;
628 ymin = (int)(yCenter-(yCenter-roiY)*yScale);
629 if (ymin<0) ymin = 0;
630 ymax = ymin + (int)(roiHeight*yScale) - 1;
631 if (ymax>=height) ymax = height - 1;
634 xmax = roiX + roiWidth - 1;
636 ymax = roiY + roiHeight - 1;
639 boolean checkCoordinates = (xScale < 1.0) || (yScale < 1.0);
640 int index1, index2, xsi, ysi;
642 double xlimit = width-1.0, xlimit2 = width-1.001;
643 double ylimit = height-1.0, ylimit2 = height-1.001;
644 for (
int y=ymin; y<=ymax; y++) {
645 ys = (y-yCenter)/yScale + yCenter;
647 if (ys<0.0) ys = 0.0;
648 if (ys>=ylimit) ys = ylimit2;
649 index1 = y*width + xmin;
650 index2 = width*(int)ys;
651 for (
int x=xmin; x<=xmax; x++) {
652 xs = (x-xCenter)/xScale + xCenter;
654 if (checkCoordinates && ((xsi<xmin) || (xsi>xmax) || (ysi<ymin) || (ysi>ymax)))
655 pixels[index1++] = (
short)min;
658 if (xs<0.0) xs = 0.0;
659 if (xs>=xlimit) xs = xlimit2;
662 pixels[index1++] = pixels2[index2+xsi];
666 showProgress((
double)(y-ymin)/height);
675 double xFraction = x - xbase;
676 double yFraction = y - ybase;
677 int offset = ybase * width + xbase;
678 int lowerLeft = pixels[offset]&0xffff;
679 int lowerRight = pixels[offset + 1]&0xffff;
680 int upperRight = pixels[offset + width + 1]&0xffff;
681 int upperLeft = pixels[offset + width]&0xffff;
682 double upperAverage = upperLeft + xFraction * (upperRight - upperLeft);
683 double lowerAverage = lowerLeft + xFraction * (lowerRight - lowerLeft);
684 return lowerAverage + yFraction * (upperAverage - lowerAverage);
689 double srcCenterX = roiX + roiWidth/2.0;
690 double srcCenterY = roiY + roiHeight/2.0;
691 double dstCenterX = dstWidth/2.0;
692 double dstCenterY = dstHeight/2.0;
693 double xScale = (double)dstWidth/roiWidth;
694 double yScale = (double)dstHeight/roiHeight;
696 dstCenterX += xScale/2.0;
697 dstCenterY += yScale/2.0;
700 short[] pixels2 = (
short[])ip2.
getPixels();
702 double xlimit = width-1.0, xlimit2 = width-1.001;
703 double ylimit = height-1.0, ylimit2 = height-1.001;
705 for (
int y=0; y<=dstHeight-1; y++) {
706 ys = (y-dstCenterY)/yScale + srcCenterY;
708 if (ys<0.0) ys = 0.0;
709 if (ys>=ylimit) ys = ylimit2;
711 index1 = width*(int)ys;
713 for (
int x=0; x<=dstWidth-1; x++) {
714 xs = (x-dstCenterX)/xScale + srcCenterX;
716 if (xs<0.0) xs = 0.0;
717 if (xs>=xlimit) xs = xlimit2;
720 pixels2[index2++] = pixels[index1+(int)xs];
723 showProgress((
double)y/dstHeight);
731 short[] pixels2 = (
short[])ip2.
getPixels();
732 for (
int ys=roiY; ys<roiY+roiHeight; ys++) {
733 int offset1 = (ys-roiY)*roiWidth;
734 int offset2 = ys*width+roiX;
735 for (
int xs=0; xs<roiWidth; xs++)
736 pixels2[offset1++] = pixels[offset2++];
747 }
else if (bestIndex==0 &&
getMin()>0.0 && (color.getRGB()&0xffffff)==0)
756 fgColor = (int)value;
757 if (fgColor<0) fgColor = 0;
758 if (fgColor>65535) fgColor = 65535;
766 int[] histogram =
new int[65536];
767 for (
int y=roiY; y<(roiY+roiHeight); y++) {
768 int i = y*width + roiX;
769 for (
int x=roiX; x<(roiX+roiWidth); x++)
770 histogram[pixels[i++]&0xffff]++;
777 throw new IllegalArgumentException(maskSizeError(mask));
778 byte[] mpixels = (byte[])mask.
getPixels();
779 int[] histogram =
new int[65536];
780 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
781 int i = y * width + roiX;
782 int mi = my * roiWidth;
783 for (
int x=roiX; x<(roiX+roiWidth); x++) {
784 if (mpixels[mi++]!=0)
785 histogram[pixels[i]&0xffff]++;
792 public void setThreshold(
double minThreshold,
double maxThreshold,
int lutUpdate) {
794 double minT = Math.round(((minThreshold-min)/(max-min))*255.0);
795 double maxT = Math.round(((maxThreshold-min)/(max-min))*255.0);
796 super.setThreshold(minT, maxT, lutUpdate);
797 this.minThreshold = Math.round(minThreshold);
798 this.maxThreshold = Math.round(maxThreshold);
800 super.resetThreshold();
804 public void convolve(
float[] kernel,
int kernelWidth,
int kernelHeight) {
807 new ij.plugin.filter.Convolver().convolve(ip2, kernel, kernelWidth, kernelHeight);
809 short[] pixels2 = (
short[])ip2.
getPixels();
810 System.arraycopy(pixels2, 0, pixels, 0, pixels.length);
814 Random rnd=
new Random();
816 for (
int y=roiY; y<(roiY+roiHeight); y++) {
817 int i = y * width + roiX;
818 for (
int x=roiX; x<(roiX+roiWidth); x++) {
819 int RandomBrightness = (int)Math.round(rnd.nextGaussian()*range);
820 v = (pixels[i] & 0xffff) + RandomBrightness;
822 if (v > 65535) v = 65535;
823 pixels[i] = (short)v;
831 for (
int i=0; i<width*height; i++) {
832 if ((pixels[i]&0xffff)<=level)
835 pixels[i] = (short)255;