5 import java.awt.image.*;
14 protected int[] pixels;
15 protected int[] snapshotPixels = null;
16 private int bgColor = 0xffffffff;
17 private int min=0, max=255;
21 private static double rWeight=0.299, gWeight=0.587, bWeight=0.114;
25 width = img.getWidth(null);
26 height = img.getHeight(null);
27 pixels =
new int[width * height];
28 PixelGrabber pg =
new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
31 }
catch (InterruptedException e){};
39 this(width, height,
new int[width*height]);
44 if (pixels!=null && width*height!=pixels.length)
45 throw new IllegalArgumentException(WRONG_LENGTH);
55 void createColorModel() {
56 cm =
new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
60 if (source==null || (ij.IJ.isMacintosh()&&!ij.IJ.isJava2())) {
61 source =
new MemoryImageSource(width, height, cm, pixels, 0, width);
62 source.setAnimated(
true);
63 source.setFullBufferUpdates(
true);
64 img = Toolkit.getDefaultToolkit().createImage(source);
65 }
else if (newPixels) {
66 source.newPixels(pixels, cm, 0, width);
76 int[] pixels =
new int[width*height];
77 for (
int i=0; i<width*height; i++)
82 public Color getColor(
int x,
int y) {
83 int c = pixels[y*width+x];
84 int r = (c&0xff0000)>>16;
85 int g = (c&0xff00)>>8;
87 return new Color(r,g,b);
93 fgColor = color.getRGB();
100 fgColor = (int)value;
121 public void setMinAndMax(
double min,
double max,
int channels) {
127 int[] lut =
new int[256];
128 for (
int i=0; i<256; i++) {
130 v = (int)(256.0*v/(max-min));
145 snapshotWidth = width;
146 snapshotHeight = height;
147 if (snapshotPixels==null || (snapshotPixels!=null && snapshotPixels.length!=pixels.length))
148 snapshotPixels =
new int[width * height];
149 System.arraycopy(pixels, 0, snapshotPixels, 0, width*height);
155 if (snapshotPixels==null)
157 System.arraycopy(snapshotPixels, 0, pixels, 0, width*height);
163 if (mask==null || snapshotPixels==null)
166 throw new IllegalArgumentException(maskSizeError(mask));
167 byte[] mpixels = (byte[])mask.
getPixels();
168 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
169 int i = y * width + roiX;
170 int mi = my * roiWidth;
171 for (
int x=roiX; x<(roiX+roiWidth); x++) {
172 if (mpixels[mi++]==0)
173 pixels[i] = snapshotPixels[i];
187 throw new IllegalArgumentException(maskSizeError(mask));
188 byte[] mpixels = (byte[])mask.
getPixels();
189 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
190 int i = y * width + roiX;
191 int mi = my * roiWidth;
192 for (
int x=roiX; x<(roiX+roiWidth); x++) {
193 if (mpixels[mi++]!=0)
203 return snapshotPixels;
205 int[] pixels2 =
new int[width*height];
206 System.arraycopy(pixels, 0, pixels2, 0, width*height);
214 return snapshotPixels;
218 if (x>=0 && x<width && y>=0 && y<height)
219 return pixels[y*width+x];
228 public int[]
getPixel(
int x,
int y,
int[] iArray) {
229 if (iArray==null) iArray =
new int[3];
231 iArray[0] = (c&0xff0000)>>16;
232 iArray[1] = (c&0xff00)>>8;
240 int r=iArray[0], g=iArray[1], b=iArray[2];
241 putPixel(x, y, 0xff000000+(r<<16)+(g<<8)+b);
246 int ix = (int)(x+0.5);
247 int iy = (int)(y+0.5);
249 if (ix>=width) ix = width-1;
251 if (iy>=height) iy = height-1;
257 if (x>=0 && x<width && y>=0 && y<height)
258 pixels[y*width + x] = value|0xff000000;
265 if (x>=0 && x<width && y>=0 && y<height) {
270 int gray = (int)(value+0.5);
271 pixels[y*width + x] = 0xff000000 + (gray<<16) + (gray<<8) + gray;
280 if (x>=0 && x<width && y>=0 && y<height) {
281 int c = pixels[y*width+x];
282 int r = (c&0xff0000)>>16;
283 int g = (c&0xff00)>>8;
285 return (
float)(r*rWeight + g*gWeight + b*bWeight);
294 if (x>=clipXMin && x<=clipXMax && y>=clipYMin && y<=clipYMax)
295 pixels[y*width + x] = fgColor;
302 return (Object)pixels;
307 this.pixels = (
int[])pixels;
309 snapshotPixels = null;
314 public void getHSB(byte[] H, byte[] S, byte[] B) {
316 float[] hsb =
new float[3];
317 for (
int i=0; i < width*height; i++) {
319 r = (c&0xff0000)>>16;
322 hsb = Color.RGBtoHSB(r, g, b, hsb);
323 H[i] = (byte)((
int)(hsb[0]*255.0));
324 S[i] = (byte)((
int)(hsb[1]*255.0));
325 B[i] = (byte)((
int)(hsb[2]*255.0));
333 int size = width*height;
334 float[] brightness =
new float[size];
335 float[] hsb =
new float[3];
336 for (
int i=0; i<size; i++) {
338 r = (c&0xff0000)>>16;
341 hsb = Color.RGBtoHSB(r, g, b, hsb);
342 brightness[i] = hsb[2];
348 public void getRGB(byte[] R, byte[] G, byte[] B) {
350 for (
int i=0; i < width*height; i++) {
352 r = (c&0xff0000)>>16;
363 public void setRGB(byte[] R, byte[] G, byte[] B) {
365 for (
int i=0; i < width*height; i++)
366 pixels[i] = 0xff000000 | ((R[i]&0xff)<<16) | ((G[i]&0xff)<<8) | B[i]&0xff;
371 public void setHSB(byte[] H, byte[] S, byte[] B) {
372 float hue, saturation, brightness;
373 for (
int i=0; i < width*height; i++) {
374 hue = (float)((H[i]&0xff)/255.0);
375 saturation = (float)((S[i]&0xff)/255.0);
376 brightness = (float)((B[i]&0xff)/255.0);
377 pixels[i] = Color.HSBtoRGB(hue, saturation, brightness);
384 int size = width*height;
385 float[] hsb =
new float[3];
386 float[] brightness = (
float[])fp.
getPixels();
387 if (brightness.length!=size)
388 throw new IllegalArgumentException(
"fp is wrong size");
389 for (
int i=0; i<size; i++) {
391 r = (c&0xff0000)>>16;
394 hsb = Color.RGBtoHSB(r, g, b, hsb);
395 float bvalue = brightness[i];
396 if (bvalue<0f) bvalue = 0f;
397 if (bvalue>1.0f) bvalue = 1.0f;
398 pixels[i] = Color.HSBtoRGB(hsb[0], hsb[1], bvalue);
406 throw new IllegalArgumentException(
"8-bit or RGB image required");
414 for (
int y=roiY; y<(roiY+roiHeight); y++) {
415 int i = y * width + roiX;
416 for (
int x=roiX; x<(roiX+roiWidth); x++) {
418 r = lut[(c&0xff0000)>>16];
419 g = lut[(c&0xff00)>>8];
421 pixels[i] = 0xff000000 + (r<<16) + (g<<8) + b;
428 public void applyTable(
int[] lut,
int channels) {
429 int c, r=0, g=0, b=0;
430 for (
int y=roiY; y<(roiY+roiHeight); y++) {
431 int i = y * width + roiX;
432 for (
int x=roiX; x<(roiX+roiWidth); x++) {
435 r = lut[(c&0xff0000)>>16];
438 }
else if (channels==2) {
439 r = (c&0xff0000)>>16;
440 g = lut[(c&0xff00)>>8];
442 }
else if (channels==1) {
443 r = (c&0xff0000)>>16;
446 }
else if ((channels&6)==6) {
447 r = lut[(c&0xff0000)>>16];
448 g = lut[(c&0xff00)>>8];
450 }
else if ((channels&5)==5) {
451 r = lut[(c&0xff0000)>>16];
454 }
else if ((channels&3)==3) {
455 r = (c&0xff0000)>>16;
456 g = lut[(c&0xff00)>>8];
459 pixels[i] = 0xff000000 + (r<<16) + (g<<8) + b;
468 for (
int y=roiY; y<(roiY+roiHeight); y++) {
469 int i = y * width + roiX;
470 for (
int x=roiX; x<(roiX+roiWidth); x++)
471 pixels[i++] = fgColor;
473 showProgress((
double)(y-roiY)/roiHeight);
479 public final int RGB_NOISE=0, RGB_MEDIAN=1, RGB_FIND_EDGES=2,
480 RGB_ERODE=3, RGB_DILATE=4, RGB_THRESHOLD=5;
485 byte[] R =
new byte[width*height];
486 byte[] G =
new byte[width*height];
487 byte[] B =
new byte[width*height];
489 Rectangle roi =
new Rectangle(roiX, roiY, roiWidth, roiHeight);
501 r.
noise(arg); showProgress(0.40);
502 g.
noise(arg); showProgress(0.65);
503 b.
noise(arg); showProgress(0.90);
516 r.
erode(); showProgress(0.40);
517 g.
erode(); showProgress(0.65);
518 b.
erode(); showProgress(0.90);
521 r.
dilate(); showProgress(0.40);
522 g.
dilate(); showProgress(0.65);
523 b.
dilate(); showProgress(0.90);
548 public void findEdges() {
561 public void autoThreshold() {
568 public void scale(
double xScale,
double yScale) {
569 double xCenter = roiX + roiWidth/2.0;
570 double yCenter = roiY + roiHeight/2.0;
571 int xmin, xmax, ymin, ymax;
573 if ((xScale>1.0) && (yScale>1.0)) {
575 xmin = (int)(xCenter-(xCenter-roiX)*xScale);
576 if (xmin<0) xmin = 0;
577 xmax = xmin + (int)(roiWidth*xScale) - 1;
578 if (xmax>=width) xmax = width - 1;
579 ymin = (int)(yCenter-(yCenter-roiY)*yScale);
580 if (ymin<0) ymin = 0;
581 ymax = ymin + (int)(roiHeight*yScale) - 1;
582 if (ymax>=height) ymax = height - 1;
585 xmax = roiX + roiWidth - 1;
587 ymax = roiY + roiHeight - 1;
590 boolean checkCoordinates = (xScale < 1.0) || (yScale < 1.0);
591 int index1, index2, xsi, ysi;
593 double xlimit = width-1.0, xlimit2 = width-1.001;
594 double ylimit = height-1.0, ylimit2 = height-1.001;
595 for (
int y=ymin; y<=ymax; y++) {
596 ys = (y-yCenter)/yScale + yCenter;
598 if (ys<0.0) ys = 0.0;
599 if (ys>=ylimit) ys = ylimit2;
600 index1 = y*width + xmin;
601 index2 = width*(int)ys;
602 for (
int x=xmin; x<=xmax; x++) {
603 xs = (x-xCenter)/xScale + xCenter;
605 if (checkCoordinates && ((xsi<xmin) || (xsi>xmax) || (ysi<ymin) || (ysi>ymax)))
606 pixels[index1++] = (byte)bgColor;
609 if (xs<0.0) xs = 0.0;
610 if (xs>=xlimit) xs = xlimit2;
613 pixels[index1++] = pixels2[index2+xsi];
617 showProgress((
double)(y-ymin)/height);
623 int[] pixels2 =
new int[roiWidth*roiHeight];
624 for (
int ys=roiY; ys<roiY+roiHeight; ys++) {
625 int offset1 = (ys-roiY)*roiWidth;
626 int offset2 = ys*width+roiX;
627 for (
int xs=0; xs<roiWidth; xs++)
628 pixels2[offset1++] = pixels[offset2++];
637 if (x>=width-1.0) x = width-1.001;
639 if (y>=height-1.0) y = height-1.001;
647 double xFraction = x - xbase;
648 double yFraction = y - ybase;
649 int offset = ybase * width + xbase;
651 int lowerLeft = pixels[offset];
652 int rll = (lowerLeft&0xff0000)>>16;
653 int gll = (lowerLeft&0xff00)>>8;
654 int bll = lowerLeft&0xff;
656 int lowerRight = pixels[offset + 1];
657 int rlr = (lowerRight&0xff0000)>>16;
658 int glr = (lowerRight&0xff00)>>8;
659 int blr = lowerRight&0xff;
661 int upperRight = pixels[offset + width + 1];
662 int rur = (upperRight&0xff0000)>>16;
663 int gur = (upperRight&0xff00)>>8;
664 int bur = upperRight&0xff;
666 int upperLeft = pixels[offset + width];
667 int rul = (upperLeft&0xff0000)>>16;
668 int gul = (upperLeft&0xff00)>>8;
669 int bul = upperLeft&0xff;
672 double upperAverage, lowerAverage;
673 upperAverage = rul + xFraction * (rur - rul);
674 lowerAverage = rll + xFraction * (rlr - rll);
675 r = (int)(lowerAverage + yFraction * (upperAverage - lowerAverage)+0.5);
676 upperAverage = gul + xFraction * (gur - gul);
677 lowerAverage = gll + xFraction * (glr - gll);
678 g = (int)(lowerAverage + yFraction * (upperAverage - lowerAverage)+0.5);
679 upperAverage = bul + xFraction * (bur - bul);
680 lowerAverage = bll + xFraction * (blr - bll);
681 b = (int)(lowerAverage + yFraction * (upperAverage - lowerAverage)+0.5);
683 return 0xff000000 | ((r&0xff)<<16) | ((g&0xff)<<8) | b&0xff;
690 double srcCenterX = roiX + roiWidth/2.0;
691 double srcCenterY = roiY + roiHeight/2.0;
692 double dstCenterX = dstWidth/2.0;
693 double dstCenterY = dstHeight/2.0;
694 double xScale = (double)dstWidth/roiWidth;
695 double yScale = (double)dstHeight/roiHeight;
696 double xlimit = width-1.0, xlimit2 = width-1.001;
697 double ylimit = height-1.0, ylimit2 = height-1.001;
699 dstCenterX += xScale/2.0;
700 dstCenterY += yScale/2.0;
706 for (
int y=0; y<=dstHeight-1; y++) {
707 ys = (y-dstCenterY)/yScale + srcCenterY;
709 if (ys<0.0) ys = 0.0;
710 if (ys>=ylimit) ys = ylimit2;
712 index1 = width*(int)ys;
714 for (
int x=0; x<=dstWidth-1; x++) {
715 xs = (x-dstCenterX)/xScale + srcCenterX;
717 if (xs<0.0) xs = 0.0;
718 if (xs>=xlimit) xs = xlimit2;
721 pixels2[index2++] = pixels[index1+(int)xs];
724 showProgress((
double)y/dstHeight);
737 double centerX = roiX + (roiWidth-1)/2.0;
738 double centerY = roiY + (roiHeight-1)/2.0;
739 int xMax = roiX + this.roiWidth - 1;
741 double angleRadians = -angle/(180.0/Math.PI);
742 double ca = Math.cos(angleRadians);
743 double sa = Math.sin(angleRadians);
744 double tmp1 = centerY*sa-centerX*ca;
745 double tmp2 = -centerX*sa-centerY*ca;
746 double tmp3, tmp4, xs, ys;
748 double dwidth = width, dheight=height;
749 double xlimit = width-1.0, xlimit2 = width-1.001;
750 double ylimit = height-1.0, ylimit2 = height-1.001;
752 for (
int y=roiY; y<(roiY + roiHeight); y++) {
753 index = y*width + roiX;
754 tmp3 = tmp1 - y*sa + centerX;
755 tmp4 = tmp2 + y*ca + centerY;
756 for (
int x=roiX; x<=xMax; x++) {
759 if ((xs>=-0.01) && (xs<dwidth) && (ys>=-0.01) && (ys<dheight)) {
761 if (xs<0.0) xs = 0.0;
762 if (xs>=xlimit) xs = xlimit2;
763 if (ys<0.0) ys = 0.0;
764 if (ys>=ylimit) ys = ylimit2;
769 if (ixs>=width) ixs = width - 1;
770 if (iys>=height) iys = height -1;
771 pixels[index++] = pixels2[width*iys+ixs];
774 pixels[index++] = bgColor;
777 showProgress((
double)(y-roiY)/roiHeight);
785 for (
int y=0; y<roiHeight/2; y++) {
786 index1 = (roiY+y)*width+roiX;
787 index2 = (roiY+roiHeight-1-y)*width+roiX;
788 for (
int i=0; i<roiWidth; i++) {
789 tmp = pixels[index1];
790 pixels[index1++] = pixels[index2];
791 pixels[index2++] = tmp;
799 int p1, p2, p3, p4, p5, p6, p7, p8, p9;
800 int k1=kernel[0], k2=kernel[1], k3=kernel[2],
801 k4=kernel[3], k5=kernel[4], k6=kernel[5],
802 k7=kernel[6], k8=kernel[7], k9=kernel[8];
805 for (
int i=0; i<kernel.length; i++)
807 if (scale==0) scale = 1;
808 int inc = roiHeight/25;
813 int rsum = 0, gsum = 0, bsum = 0;
814 int rowOffset = width;
815 for (
int y=yMin; y<=yMax; y++) {
816 offset = xMin + y * width;
818 p2 = pixels2[offset-rowOffset-1];
819 p3 = pixels2[offset-rowOffset];
821 p5 = pixels2[offset-1];
822 p6 = pixels2[offset];
824 p8 = pixels2[offset+rowOffset-1];
825 p9 = pixels2[offset+rowOffset];
827 for (
int x=xMin; x<=xMax; x++) {
829 p3 = pixels2[offset-rowOffset+1];
831 p6 = pixels2[offset+1];
833 p9 = pixels2[offset+rowOffset+1];
835 rsum = k1*((p1 & 0xff0000) >> 16)
836 + k2*((p2 & 0xff0000) >> 16)
837 + k3*((p3 & 0xff0000) >> 16)
838 + k4*((p4 & 0xff0000) >> 16)
839 + k5*((p5 & 0xff0000) >> 16)
840 + k6*((p6 & 0xff0000) >> 16)
841 + k7*((p7 & 0xff0000) >> 16)
842 + k8*((p8 & 0xff0000) >> 16)
843 + k9*((p9 & 0xff0000) >> 16);
845 if(rsum>255) rsum = 255;
848 gsum = k1*((p1 & 0xff00) >> 8)
849 + k2*((p2 & 0xff00) >> 8)
850 + k3*((p3 & 0xff00) >> 8)
851 + k4*((p4 & 0xff00) >> 8)
852 + k5*((p5 & 0xff00) >> 8)
853 + k6*((p6 & 0xff00) >> 8)
854 + k7*((p7 & 0xff00) >> 8)
855 + k8*((p8 & 0xff00) >> 8)
856 + k9*((p9 & 0xff00) >> 8);
858 if(gsum>255) gsum = 255;
859 else if(gsum<0) gsum = 0;
861 bsum = k1*(p1 & 0xff)
871 if (bsum>255) bsum = 255;
872 if (bsum<0) bsum = 0;
874 pixels[offset++] = 0xff000000
875 | ((rsum << 16) & 0xff0000)
876 | ((gsum << 8 ) & 0xff00)
880 showProgress((
double)(y-roiY)/roiHeight);
887 int p1, p2, p3, p4, p5, p6, p7, p8, p9;
888 int inc = roiHeight/25;
892 int offset, rsum=0, gsum=0, bsum=0;
893 int rowOffset = width;
894 for (
int y=yMin; y<=yMax; y++) {
895 offset = xMin + y * width;
897 p2 = pixels2[offset-rowOffset-1];
898 p3 = pixels2[offset-rowOffset];
900 p5 = pixels2[offset-1];
901 p6 = pixels2[offset];
903 p8 = pixels2[offset+rowOffset-1];
904 p9 = pixels2[offset+rowOffset];
906 for (
int x=xMin; x<=xMax; x++) {
908 p3 = pixels2[offset-rowOffset+1];
910 p6 = pixels2[offset+1];
912 p9 = pixels2[offset+rowOffset+1];
913 rsum = (p1 & 0xff0000) + (p2 & 0xff0000) + (p3 & 0xff0000) + (p4 & 0xff0000) + (p5 & 0xff0000)
914 + (p6 & 0xff0000) + (p7 & 0xff0000) + (p8 & 0xff0000) + (p9 & 0xff0000);
915 gsum = (p1 & 0xff00) + (p2 & 0xff00) + (p3 & 0xff00) + (p4 & 0xff00) + (p5 & 0xff00)
916 + (p6 & 0xff00) + (p7 & 0xff00) + (p8 & 0xff00) + (p9 & 0xff00);
917 bsum = (p1 & 0xff) + (p2 & 0xff) + (p3 & 0xff) + (p4 & 0xff) + (p5 & 0xff)
918 + (p6 & 0xff) + (p7 & 0xff) + (p8 & 0xff) + (p9 & 0xff);
919 pixels[offset++] = 0xff000000 | ((rsum/9) & 0xff0000) | ((gsum/9) & 0xff00) | (bsum/9);
922 showProgress((
double)(y-roiY)/roiHeight);
931 int[] histogram =
new int[256];
932 for (
int y=roiY; y<(roiY+roiHeight); y++) {
933 int i = y * width + roiX;
934 for (
int x=roiX; x<(roiX+roiWidth); x++) {
936 r = (c&0xff0000)>>16;
939 v = (int)(r*rWeight + g*gWeight + b*bWeight + 0.5);
943 showProgress((
double)(y-roiY)/roiHeight);
952 throw new IllegalArgumentException(maskSizeError(mask));
953 byte[] mpixels = (byte[])mask.
getPixels();
955 int[] histogram =
new int[256];
956 for (
int y=roiY, my=0; y<(roiY+roiHeight); y++, my++) {
957 int i = y * width + roiX;
958 int mi = my * roiWidth;
959 for (
int x=roiX; x<(roiX+roiWidth); x++) {
960 if (mpixels[mi++]!=0) {
962 r = (c&0xff0000)>>16;
965 v = (int)(r*rWeight + g*gWeight + b*bWeight + 0.5);
971 showProgress((
double)(y-roiY)/roiHeight);
978 public void convolve(
float[] kernel,
int kernelWidth,
int kernelHeight) {
979 int size = width*height;
980 byte[] r =
new byte[size];
981 byte[] g =
new byte[size];
982 byte[] b =
new byte[size];
990 ip2.
convolve(kernel, kernelWidth, kernelHeight);
994 ip2.
convolve(kernel, kernelWidth, kernelHeight);
998 ip2.
convolve(kernel, kernelWidth, kernelHeight);
1016 double[] weights =
new double[3];
1017 weights[0] = rWeight;
1018 weights[1] = gWeight;
1019 weights[2] = bWeight;