ImageFunctions.java

Go to the documentation of this file.
00001 package theba.core;
00002 
00003 import java.awt.Point;
00004 import java.awt.Rectangle;
00005 import java.io.FileOutputStream;
00006 import java.io.IOException;
00007 import java.util.ArrayList;
00008 import java.util.LinkedList;
00009 
00010 import javax.swing.JOptionPane;
00011 
00012 import theba.core.gui.ThebaGUI;
00013 import theba.core.io.DataConversion;
00014 import theba.core.math.Point3D;
00015 import theba.descriptors.AvgCurvature;
00016 import theba.descriptors.BendingEnergyDescriptor;
00017 import theba.descriptors.CircularityDescriptor;
00018 import theba.descriptors.EccentricityDescriptor;
00019 
00020 
00029 public class ImageFunctions {
00030         public static short[] cachedMap = null;
00031 
00037         public static double bendingEnergy(short[] pixels, int width, int height) {
00038                 return (new BendingEnergyDescriptor()).measure(pixels, width, height);
00039         }
00040 
00046         public static int floodFill2D(int xp, int yp, int width, int height,
00047                         final short[] input, short[] output, short value) {
00048                 if (input == null) {
00049                         System.err.println("Input was zero in floodFill2DMasked!");
00050                         return 0;
00051                 }
00052                 if (output == null) {
00053                         System.err.println("Output was zero in floodFill2DMasked!");
00054                         return 0;
00055                 }
00056                 if (input == output)
00057                         throw new RuntimeException("Input equals output!");
00058                 if (xp < 0 || yp < 0 || xp >= width || yp >= height) {
00059                         System.err.print("Coord out of bounds!");
00060                         return 0;
00061                 }
00062                 LinkedList<Point> queue = new LinkedList<Point> ();
00063                 queue.addFirst(new Point(xp, yp));
00064                 int count = 0;
00065                 short col = input[xp + yp * width];
00066                 while (queue.isEmpty() == false) {
00067                         Point p = queue.removeFirst();
00068                         int x = p.x;
00069                         int y = p.y;
00070                         int index = x + y * width;
00071                         if ((input[index]) == col) {
00072                                 count++;
00073                                 output[index] = value;
00074                                 if (x + 1 < width && output[index + 1] == 0) {
00075                                         queue.addFirst(new Point(x + 1, y));
00076                                 }
00077                                 if (y + 1 < height && output[index + width] == 0) {
00078                                         queue.addFirst(new Point(x, y + 1));
00079                                 }
00080                                 if (y - 1 >= 0 && output[index - width] == 0) {
00081                                         queue.addFirst(new Point(x, y - 1));
00082                                 }
00083                                 if (x - 1 >= 0 && output[index - 1] == 0) {
00084                                         queue.addFirst(new Point(x - 1, y));
00085                                 }
00086                         }
00087                 }
00088                 return count;
00089         }
00090 
00095         public static ArrayList<Point> borderTrace(short[] pixels, int width, int height) {
00096                 Point start = null;
00097                 // contour stores the object in a padded matrix
00098                 short[][] contour = new short[width + 2][height + 2];
00099                 for (int i = 0; i < width; i++) {
00100                         for (int j = 0; j < height; j++) {
00101                                 if (pixels[i + j * width] != 0) { // if lumen
00102                                         contour[i + 1][j + 1] = (short) 1;
00103                                         if (start == null)
00104                                                 start = new Point(i + 1, j + 1); // starting point in contour
00105                                 }
00106                         }
00107                 }
00108                 if (start == null) {
00109                         System.err.println("Warning! could not find lumen!");
00110                         return null;
00111                 }
00112                 // ok, now we have the upmost, rightmost pixel of the border
00113                 int i = start.x;
00114                 int j = start.y;
00115                 // create parametric countour, store it in x and y
00116                 // 8-conn
00117                 final int[][] path = { { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 },
00118                                 { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } };
00119                 int cane = 4;
00120                 final int[] next = { 1, 2, 3, 4, 5, 6, 7, 0 };
00121                 final int[] invert = { 4, 5, 6, 7, 0, 1, 2, 3 };
00122                 int[][] neighbor = new int[path.length][path[0].length]; // init to 0
00123                 for (int k = 0; k < neighbor.length; k++) {
00124                         neighbor[k][0] = path[k][0] + i;
00125                         neighbor[k][1] = path[k][1] + j;
00126                 }
00127                 ArrayList<Point> points = new ArrayList<Point>() ;
00128                 int cini;
00129                 boolean finished = false;
00130                 boolean continueLooking = true;
00131                 while (!finished) {
00132                         points.add(new Point(i - 1, j - 1));
00133                         cini = cane;
00134                         continueLooking = true;
00135                         while (continueLooking) {
00136                                 cane = next[cane];
00137                                 continueLooking = (contour[neighbor[cane][0]][neighbor[cane][1]] == 0)
00138                                                 && cane != cini;
00139                         }
00140                         if (contour[neighbor[cane][0]][neighbor[cane][1]] == 1) {
00141                                 i = i + path[cane][0];
00142                                 j = j + path[cane][1];
00143                                 for (int k = 0; k < neighbor.length; k++) {
00144                                         neighbor[k][0] = neighbor[k][0] + path[cane][0];
00145                                         neighbor[k][1] = neighbor[k][1] + path[cane][1];
00146                                 }
00147                                 cane = invert[cane];
00148                                 finished = (j == start.y && i == start.x); // if back at starting point then finished
00149                         } else {
00150                                 finished = true; // could not continue
00151                         }
00152                 }
00153                 return points;
00154         }
00155 
00156 
00157         public static double circlish(short[] mask, int width, int height) {
00158                 return (new CircularityDescriptor()).measure(mask, width, height);
00159         }
00160 
00166         public static int countOutlinePixels(final short[] input, int xp, int yp,
00167                         int width, int height, short val) {
00168                 if (xp < 0 || yp < 0 || xp >= width || yp >= height)
00169                         return 0;
00170                 LinkedList<Point> queue = new LinkedList<Point>();
00171                 queue.addFirst(new Point(xp, yp));
00172                 int count = 0;
00173                 short[] mark = new short[input.length];
00174                 while (queue.size() > 0) {
00175                         Point p = queue.removeLast();
00176                         int x = p.x;
00177                         int y = p.y;
00178                         int index = x + y * width;
00179                         if (input[index] != 0 && mark[index] != 2) {
00180                                 mark[index] = 2;
00181                                 if (x + 1 < width && mark[index + 1] == 0) {
00182                                         queue.addFirst(new Point(x + 1, y));
00183                                         if (input[index + 1] == 0)
00184                                                 count++;
00185                                         mark[index + 1] = (short) 1;
00186                                 }
00187                                 if (y + 1 < height && mark[index + width] == 0) {
00188                                         queue.addFirst(new Point(x, y + 1));
00189                                         if (input[index + width] == 0)
00190                                                 count++;
00191                                         mark[index + width] = (short) 1;
00192                                 }
00193                                 if (y - 1 >= 0 && mark[index - width] == 0) {
00194                                         queue.addFirst(new Point(x, y - 1));
00195                                         if (input[index - width] == 0)
00196                                                 count++;
00197                                         mark[index - width] = (short) 1;
00198                                 }
00199                                 if (x - 1 >= 0 && mark[index - 1] == 0) {
00200                                         queue.addFirst(new Point(x - 1, y));
00201                                         if (input[index - 1] == 0)
00202                                                 count++;
00203                                         mark[index - 1] = (short) 1;
00204                                 }
00205                         }
00206                 }
00207                 return count;
00208         }
00209 
00215         public static double curvature(short[] pixels, int width, int height) {
00216                 return (new AvgCurvature()).measure(pixels, width, height);
00217         }
00218 
00225         public static void delete3D(Stack volume, int xp, int yp, int zp) {
00226                 if (volume.getVoxel(xp, yp, zp) == 0)
00227                         return;
00228                 floodFill3D26(volume, xp, yp, zp, (short) 0);
00229                 ThebaGUI.getInstance().updateImage();
00230         }
00231 
00239         public static short[] dilate(short[] input, int width, int height) {
00240                 return dilate(input, width, height, new Rectangle(0, 0, width, height));
00241         }
00242 
00252         public static short[] dilate(short[] input, int width, int height,
00253                         Rectangle bounds) {
00254                 return dilate(input, new short[input.length], width, height, bounds);
00255         }
00256 
00266         public static short[] dilate(short[] input, short[] output, int width,
00267                         int height, Rectangle bounds) {
00268                 if (input == output)
00269                         throw new RuntimeException("input should not be equal to output!");
00270                 int startX = (int) bounds.getX();
00271                 int startY = (int) bounds.getY();
00272                 int stopX = startX + (int) bounds.getWidth();
00273                 if (stopX > width)
00274                         stopX = width;
00275                 int stopY = startY + (int) bounds.getHeight();
00276                 if (stopY > height)
00277                         stopY = height;
00278                 for (int x = startX; x < stopX; x++)
00279                         for (int y = startY; y < stopY; y++) {
00280                                 int index = x + y * width;
00281                                 int max = input[index];
00282                                 if (x > 0 && (input[index - 1]) > max)
00283                                         max = input[index - 1];
00284                                 else if (x < width - 1 && (input[index + 1]) > max)
00285                                         max = (input[index + 1]);
00286                                 else if (y > 0 && (input[index - width]) > max)
00287                                         max = (input[index - width]);
00288                                 else if (y < height - 1 && (input[index + width]) > max)
00289                                         max = input[index + width];
00290                                 output[index] = (short) max;
00291                         }
00292                 return output;
00293         }
00294 
00302         public static short[] dilate(short[] input, short[] output, int width,
00303                         int height, Rectangle bounds, short val) {
00304                 if (input == output)
00305                         throw new RuntimeException("input should not be equal to output!");
00306                 int startX = (int) bounds.getX();
00307                 int startY = (int) bounds.getY();
00308                 int stopX = startX + (int) bounds.getWidth();
00309                 if (stopX > width)
00310                         stopX = width;
00311                 int stopY = startY + (int) bounds.getHeight();
00312                 if (stopY > height)
00313                         stopY = height;
00314                 if (startX < 0 || startY < 0)
00315                         throw new RuntimeException("Bounds cannot be negative!");
00316                 for (int x = startX; x < stopX; x++)
00317                         for (int y = startY; y < stopY; y++) {
00318                                 int index = x + y * width;
00319                                 short max = 0;
00320                                 if (x > 0 && input[index - 1] > max)
00321                                         max = 1;
00322                                 else if (x < width - 1 && input[index + 1] > max)
00323                                         max = 1;
00324                                 else if (y > 0 && input[index - width] > max)
00325                                         max = 1;
00326                                 else if (y < height - 1 && input[index + width] > max)
00327                                         max = 1;
00328                                 if (max != 0 && input[index] == 0)
00329                                         output[index] = val;
00330                         }
00331                 return output;
00332         }
00333 
00344         public static short[] dilateMasked(short[] input, short[] output,
00345                         short[] mask, int width, int height, Rectangle bounds, short val) {
00346                 if (input == output)
00347                         throw new RuntimeException("input should not be equal to output!");
00348                 int startX = (int) bounds.getX();
00349                 int startY = (int) bounds.getY();
00350                 int stopX = startX + (int) bounds.getWidth();
00351                 if (stopX > width)
00352                         stopX = width;
00353                 int stopY = startY + (int) bounds.getHeight();
00354                 if (stopY > height)
00355                         stopY = height;
00356                 if (startX < 0 || startY < 0)
00357                         throw new RuntimeException("Bounds cannot be negative!");
00358                 int wmax = width - 1;
00359                 int hmax = height - 1;
00360                 for (int y = startY; y < stopY; y++) {
00361                         for (int x = startX; x < stopX; x++) {
00362                                 int index = x + y * width;
00363                                 if (mask[index] != 0 && input[index] == 0) {// ignore if outside
00364                                                                                                                         // mask
00365                                         short max = 0;
00366                                         // search under a four-connected element
00367                                         if (input[index] > max) {
00368                                                 max = 1;
00369                                         } else if (x > 0 && input[index - 1] > max)
00370                                                 max = 1;
00371                                         else if (x < wmax && input[index + 1] > max)
00372                                                 max = 1;
00373                                         else if (y > 0 && input[index - width] > max)
00374                                                 max = 1;
00375                                         else if (y < hmax && input[index + width] > max)
00376                                                 max = 1;
00377                                         if (max != 0 && input[index] == 0)
00378                                                 output[index] = val;
00379                                 }
00380                         }
00381                 }
00382                 return output;
00383         }
00384 
00391         public static void dilate3d(Stack voxels) {
00392                 int width = voxels.getWidth();
00393                 int height = voxels.getHeight();
00394                 int depth = voxels.getDepth();
00395                 short[] prevdata = new short[width * height];
00396                 short[] data = new short[width * height];
00397                 short[] nextdata = new short[width * height];
00398                 ThebaGUI control = ThebaGUI.getInstance();
00399                 System.arraycopy(voxels.getSlice(1), 0, nextdata, 0, nextdata.length);
00400                 System.arraycopy(voxels.getSlice(0), 0, data, 0, data.length);
00401                 for (int z = 0; z < depth; z++) {
00402                         control.setProgress(z);
00403                         if (control.isStopped())
00404                                 return;
00405                         int index = 0;
00406                         for (int y = 0; y < height; y++) {
00407                                 for (int x = 0; x < width; x++) {
00408                                         short max = data[index];
00409                                         if (x > 0)
00410                                                 max = max(max, data[index - 1]);
00411                                         if (x < width - 1)
00412                                                 max = max(max, data[index + 1]);
00413                                         if (y > 0)
00414                                                 max = max(max, data[index - width]);
00415                                         if (y < height - 1)
00416                                                 max = max(max, data[index + width]);
00417                                         if (z > 0)
00418                                                 max = max(max, prevdata[index]);
00419                                         if (z < depth - 1)
00420                                                 max = max(max, nextdata[index]);
00421                                         voxels.getSlice(z)[index] = max;
00422                                         index++;
00423                                 }
00424                         }
00425                         if (z > 0)
00426                                 System.arraycopy(data, 0, prevdata, 0, prevdata.length);
00427                         System.arraycopy(nextdata, 0, data, 0, data.length);
00428                         if (z < depth - 1)
00429                                 System.arraycopy(voxels.getSlice(z + 1), 0, nextdata, 0,
00430                                                 nextdata.length);
00431                 }
00432         }
00433 
00444         public static int dilateAndCount(final short[] input, short[] output,
00445                         short[] mask, int width, int height, Rectangle bounds) {
00446                 int count = 0;
00447                 if (input == output)
00448                         throw new RuntimeException("input should not be equal to outpu!");
00449                 int startX = (int) bounds.getX();
00450                 int startY = (int) bounds.getY();
00451                 int stopX = startX + (int) bounds.getWidth();
00452                 if (stopX > width)
00453                         stopX = width;
00454                 int stopY = startY + (int) bounds.getHeight();
00455                 if (stopY > height)
00456                         stopY = height;
00457                 for (int x = startX; x < stopX; x++)
00458                         for (int y = startY; y < stopY; y++) {
00459                                 int index = x + y * width;
00460                                 int max = input[index];
00461                                 // int ict = 0;
00462                                 if (x > 0 && (input[index - 1]) > max) {
00463                                         max = input[index - 1];
00464                                 }
00465                                 if (x < width - 1 && (input[index + 1]) > max) {
00466                                         max = (input[index + 1]);
00467                                 }
00468                                 if (y > 0 && (input[index - width]) > max) {
00469                                         max = (input[index - width]);
00470                                 }
00471                                 if (y < height - 1 && (input[index + width]) > max) {
00472                                         max = input[index + width];
00473                                 }
00474                                 if (mask[index] != 0 && max != 0/* && ict > 2 */) {
00475                                         if (input[index] == 0) {
00476                                                 count++;
00477                                                 output[index] = (short) (max + 1);
00478                                         } else {
00479                                                 output[index] = input[index];
00480                                         }
00481                                 }
00482                         }
00483                 return count;
00484         }
00485 
00493         public static short[] erode(short[] input, int width, int height) {
00494                 return erode(input, width, height, new Rectangle(0, 0, width, height));
00495         }
00496 
00506         public static short[] erode(short[] input, int width, int height,
00507                         Rectangle bounds) {
00508                 return erode(input, new short[input.length], width, height, bounds);
00509         }
00510 
00520         public static short[] erode(short[] input, short[] output, int width,
00521                         int height, Rectangle bounds) {
00522                 if (input == output)
00523                         throw new RuntimeException("input should not be equal to output!");
00524                 int startX = (int) bounds.getX();
00525                 int startY = (int) bounds.getY();
00526                 int stopX = startX + (int) bounds.getWidth();
00527                 if (stopX > width)
00528                         stopX = width;
00529                 int stopY = startY + (int) bounds.getHeight();
00530                 if (stopY > height)
00531                         stopY = height;
00532                 for (int x = startX; x < stopX; x++)
00533                         for (int y = startY; y < stopY; y++) {
00534                                 int index = x + y * width;
00535                                 int min = input[index];
00536                                 if (x > 0 && (input[index - 1]) < min)
00537                                         min = input[index - 1];
00538                                 else if (x < width - 1 && (input[index + 1]) < min)
00539                                         min = (input[index + 1]);
00540                                 else if (y > 0 && (input[index - width]) < min)
00541                                         min = (input[index - width]);
00542                                 else if (y < height - 1 && (input[index + width]) < min)
00543                                         min = input[index + width];
00544                                 output[index] = (short) min;
00545                         }
00546                 return output;
00547         }
00548 
00549         
00556         public static void erode3d(Stack voxels) {
00557                 int width = voxels.getWidth();
00558                 int height = voxels.getHeight();
00559                 int depth = voxels.getDepth();
00560                 short[] prevdata = new short[width * height];
00561                 short[] data = new short[width * height];
00562                 short[] nextdata = new short[width * height];
00563                 ThebaGUI control = ThebaGUI.getInstance();
00564                 System.arraycopy(voxels.getSlice(1), 0, nextdata, 0, nextdata.length);
00565                 System.arraycopy(voxels.getSlice(0), 0, data, 0, data.length);
00566                 for (int z = 0; z < depth; z++) {
00567                         control.setProgress(z);
00568                         if (control.isStopped())
00569                                 return;
00570                         int index = 0;
00571                         for (int y = 0; y < height; y++) {
00572                                 for (int x = 0; x < width; x++) {
00573                                         short min = data[index];
00574                                         if (x > 0)
00575                                                 min = min(min, data[index - 1]);
00576                                         if (x < width - 1)
00577                                                 min = min(min, data[index + 1]);
00578                                         if (y > 0)
00579                                                 min = min(min, data[index - width]);
00580                                         if (y < height - 1)
00581                                                 min = min(min, data[index + width]);
00582                                         if (z > 0)
00583                                                 min = min(min, prevdata[index]);
00584                                         if (z < depth - 1)
00585                                                 min = min(min, nextdata[index]);
00586                                         voxels.getSlice(z)[index] = min;
00587                                         index++;
00588                                 }
00589                         }
00590                         if (z > 0)
00591                                 System.arraycopy(data, 0, prevdata, 0, prevdata.length);
00592                         System.arraycopy(nextdata, 0, data, 0, data.length);
00593                         if (z < depth - 1)
00594                                 System.arraycopy(voxels.getSlice(z + 1), 0, nextdata, 0,
00595                                                 nextdata.length);
00596                 }
00597                 voxels.flush();
00598         }
00599         
00605         public static int floodFill2D(int xp, int yp, int width, int height,
00606                         final short[] input, short value) {
00607                 short[] mark = new short[input.length];
00608                 if (input == null) {
00609                         System.err.println("Input was zero in floodFill2DMasked!");
00610                         return 0;
00611                 }
00612                 if (xp < 0 || yp < 0 || xp >= width || yp >= height) {
00613                         System.err.print("Coord out of bounds!");
00614                         return 0;
00615                 }
00616                 LinkedList<Point> queue = new LinkedList<Point>();
00617                 queue.addFirst(new Point(xp, yp));
00618                 int count = 0;
00619                 short col = input[xp + yp * width];
00620                 while (queue.isEmpty() == false) {
00621                         Point p = queue.removeLast();
00622                         int x = p.x;
00623                         int y = p.y;
00624                         int index = x + y * width;
00625                         count++;
00626                         input[index] = value;
00627                         if (x + 1 < width && mark[index + 1] == 0
00628                                         && input[index + 1] == col) {
00629                                 mark[index + 1] = 1;
00630                                 queue.addFirst(new Point(x + 1, y));
00631                         }
00632                         if (y + 1 < height && mark[index + width] == 0
00633                                         && input[index + width] == col) {
00634                                 mark[index + width] = 1;
00635                                 queue.addFirst(new Point(x, y + 1));
00636                         }
00637                         if (y - 1 >= 0 && mark[index - width] == 0
00638                                         && input[index - width] == col) {
00639                                 mark[index - width] = 1;
00640                                 queue.addFirst(new Point(x, y - 1));
00641                         }
00642                         if (x - 1 >= 0 && mark[index - 1] == 0 && input[index - 1] == col) {
00643                                 mark[index - 1] = 1;
00644                                 queue.addFirst(new Point(x - 1, y));
00645                         }
00646                 }
00647                 return count;
00648         }
00649 
00655         public static int floodFill2D(final short[] input, short[] output, int xp,
00656                         int yp, int width, int height, short val) {
00657                 if (xp < 0 || yp < 0 || xp >= width || yp >= height)
00658                         return 0;
00659                 LinkedList<Point> queue = new LinkedList<Point>();
00660                 queue.addFirst(new Point(xp, yp));
00661                 int startindex = xp + yp * width;
00662                 if (input[startindex] != 0)
00663                         return 0;
00664                 int count = 0;
00665                 while (queue.size() > 0) {
00666                         Point p = queue.removeLast();
00667                         int x = p.x;
00668                         int y = p.y;
00669                         int index = x + y * width;
00670                         if (input[index] == 0 && output[index] == 0) {
00671                                 count++;
00672                                 output[index] = val;
00673                                 if (x + 1 < width && output[index + 1] == 0) {
00674                                         queue.addFirst(new Point(x + 1, y));
00675                                 }
00676                                 if (y + 1 < height && output[index + width] == 0) {
00677                                         queue.addFirst(new Point(x, y + 1));
00678                                 }
00679                                 if (y - 1 >= 0 && output[index - width] == 0) {
00680                                         queue.addFirst(new Point(x, y - 1));
00681                                 }
00682                                 if (x - 1 >= 0 && output[index - 1] == 0) {
00683                                         queue.addFirst(new Point(x - 1, y));
00684                                 }
00685                         }
00686                 }
00687                 return count;
00688         }
00689 
00696         public static int floodFill2DMasked(int xp, int yp, int width, int height,
00697                         short[] input, short[] mask, short[] output, short val) {
00698                 if (input == null) {
00699                         System.err.println("Input was zero in floodFill2DMasked!");
00700                         return 0;
00701                 }
00702                 if (mask == null) {
00703                         System.err.println("Mask was zero in floodFill2DMasked!");
00704                         return 0;
00705                 }
00706                 if (output == null) {
00707                         System.err.println("Output was zero in floodFill2DMasked!");
00708                         return 0;
00709                 }
00710                 if (input == output)
00711                         throw new RuntimeException("Input equals output!");
00712                 LinkedList<Point> queue = new LinkedList<Point>();
00713                 queue.addFirst(new Point(xp, yp));
00714                 int count = 0;
00715                 short col = input[xp + yp * width];
00716                 while (queue.isEmpty() == false) {
00717                         Point p = queue.removeLast();
00718                         int x = p.x;
00719                         int y = p.y;
00720                         int index = x + y * width;
00721                         if ((input[index]) == col && mask[index] != 0) {
00722                                 count++;
00723                                 output[index] = val;
00724                                 if (x + 1 < width && output[index + 1] == 0) {
00725                                         output[index + 1] = 1;
00726                                         queue.addFirst(new Point(x + 1, y));
00727                                 }
00728                                 if (y + 1 < height && output[index + width] == 0) {
00729                                         output[index + width] = 1;
00730                                         queue.addFirst(new Point(x, y + 1));
00731                                 }
00732                                 if (y - 1 >= 0 && output[index - width] == 0) {
00733                                         output[index - width] = 1;
00734                                         queue.addFirst(new Point(x, y - 1));
00735                                 }
00736                                 if (x - 1 >= 0 && output[index - 1] == 0) {
00737                                         output[index - 1] = 1;
00738                                         queue.addFirst(new Point(x - 1, y));
00739                                 }
00740                         } else {
00741                                 output[index] = 0; // make sure we dont keep border-pixels set to 1
00742                         }
00743                 }
00744                 return count;
00745         }
00746 
00752         public static long floodFill3D(Stack volume, int xp, int yp, int zp,
00753                         short val) {
00754                 long count = 0;
00755                 int depth = volume.getDepth();
00756                 int height = volume.getHeight();
00757                 int width = volume.getWidth();
00758                 if (xp < 0 || yp < 0 || xp >= width || yp >= height || zp < 0
00759                                 || zp > depth)
00760                         return 0;
00761                 int s = volume.getVoxelUnchecked(xp, yp, zp);
00762                 if (s == val)
00763                         return 0;
00764                 LinkedList<Point3D> queue = new LinkedList<Point3D>();
00765                 queue.addFirst(new Point3D(xp, yp, zp));
00766                 while (queue.isEmpty() == false) {
00767                         Point3D p = queue.removeLast();
00768                         int x = p.x;
00769                         int y = p.y;
00770                         int z = p.z;
00771                         int pixelIndex = x + y * width;
00772                         short[] pixels = volume.getSlice(z);
00773                         pixels[pixelIndex] = val;
00774                         count++;
00775                         if (x < width - 1 && pixels[pixelIndex + 1] == s) {
00776                                 queue.addFirst(new Point3D(x + 1, y, z));
00777                                 pixels[pixelIndex + 1] = -1;
00778                         }
00779                         if (x - 1 >= 0 && pixels[pixelIndex - 1] == s) {
00780                                 queue.addFirst(new Point3D(x - 1, y, z));
00781                                 pixels[pixelIndex - 1] = -1;
00782                         }
00783                         if (y < height - 1 && pixels[pixelIndex + width] == s) {
00784                                 queue.addFirst(new Point3D(x, y + 1, z));
00785                                 pixels[pixelIndex + width] = -1;
00786                         }
00787                         if (y - 1 >= 0 && pixels[pixelIndex - width] == s) {
00788                                 queue.addFirst(new Point3D(x, y - 1, z));
00789                                 pixels[pixelIndex - width] = -1;
00790                         }
00791                         if (z >= 1 && volume.getSlice(z - 1)[pixelIndex] == s) {
00792                                 queue.addFirst(new Point3D(x, y, z - 1));
00793                                 volume.getSlice((z - 1))[pixelIndex] = -1;
00794                         }
00795                         if (z < depth - 1 && volume.getSlice(z + 1)[pixelIndex] == s) {
00796                                 queue.addFirst(new Point3D(x, y, z + 1));
00797                                 volume.getSlice((z + 1))[pixelIndex] = -1;
00798                         }
00799                 }
00800                 return count;
00801         }
00802 
00814         public static long floodFill3D26(Stack volume, int xp, int yp, int zp,
00815                         short newValue) {
00816                 long count = 0;
00817                 int depth = volume.getDepth();
00818                 int height = volume.getHeight();
00819                 int width = volume.getWidth();
00820                 if (xp < 0 || yp < 0 || xp >= width || yp >= height || zp < 0
00821                                 || zp >= depth)
00822                         return 0;
00823                 int oldValue = volume.getVoxelUnchecked(xp, yp, zp);
00824                 if (oldValue == newValue)
00825                         return 0;
00826                 if (oldValue == 255) {
00827                         int ans = JOptionPane.showConfirmDialog(null,
00828                                                         "Are you sure you want to fill foreground pixels( label 255) ?",
00829                                                         "Warning", JOptionPane.YES_NO_OPTION);
00830                         if (ans == JOptionPane.NO_OPTION)
00831                                 return 0;
00832                 }
00833                 LinkedList<Point3D> queue = new LinkedList<Point3D>();
00834                 queue.addFirst(new Point3D(xp, yp, zp));
00835                 while (queue.isEmpty() == false) {
00836                         Point3D p = queue.removeLast();
00837                         int x = p.x;
00838                         int y = p.y;
00839                         int z = p.z;
00840                         count++;
00841                         volume.setVoxelUnchecked(x, y, z, newValue);
00842                         for (int i = -1; i < 2; i++)
00843                                 for (int j = -1; j < 2; j++)
00844                                         for (int k = -1; k < 2; k++) {
00845                                                 int xx = i + x;
00846                                                 int yy = j + y;
00847                                                 int zz = k + z;
00848                                                 if (xx < 0 || xx >= width)
00849                                                         continue;
00850                                                 if (yy < 0 || yy >= height)
00851                                                         continue;
00852                                                 if (zz < 0 || zz >= depth)
00853                                                         continue;
00854                                                 short voxel = volume.getVoxel(xx, yy, zz);
00855                                                 if (voxel == oldValue) {
00856                                                         queue.addFirst(new Point3D(xx, yy, zz));
00857                                                         volume.setVoxel(xx, yy, zz, 0);
00858                                                 }
00859                                         }
00860                 }
00861                 return count;
00862         }
00863 
00867         public static short[] geodist(short[] input, short[] mask, int width,
00868                         int height) {
00869                 short[] output = input.clone();
00870                 for (int i = 0; i < output.length; i++) {
00871                         if (input[i] != 0)
00872                                 output[i] = 1;
00873                 }
00874                 int count = 10;
00875                 int maxdilations = 100;
00876                 while (count > 0 && maxdilations > 0) {
00877                         maxdilations--;
00878                         count = dilateAndCount(output.clone(), output, mask, width, height,     new Rectangle(0, 0, width, height));
00879                 }
00880                 return output;
00881         }
00882 
00890         public static double[] getArcLenghts(int[] chaincode) {
00891                 if (chaincode == null)
00892                         return null;
00893                 // get arc lengths from chaincode
00894                 double arcLenghts[] = new double[chaincode.length];
00895                 arcLenghts[0] = 0;
00896                 for (int i = 1; i < arcLenghts.length; i++) {
00897                         // find length
00898                         if (chaincode[i] % 2 == 0 && chaincode[i - 1] % 2 == 0) { // both are even
00899                                 arcLenghts[i] = arcLenghts[i - 1] + 0.5 + 0.5;
00900                         } else if (chaincode[i] % 2 == 0 || chaincode[i - 1] % 2 == 0) { // one of them is even
00901                                 arcLenghts[i] = arcLenghts[i - 1] + Math.sqrt(2) / 2 + 0.5;
00902                         } else { // none of them even
00903                                 arcLenghts[i] = arcLenghts[i - 1] + Math.sqrt(2) / 2 + Math.sqrt(2) / 2;
00904                         }
00905                 }
00906                 return arcLenghts;
00907         }
00908 
00914         public static Point getAveragePoint(short[] lumenMask, int width, int height) {
00915                 double xp = 0;
00916                 double yp = 0;
00917                 double count = 0;
00918                 for (int x = 0; x < width; x++) {
00919                         for (int y = 0; y < height; y++) {
00920                                 if (lumenMask[x + y * width] != 0) {
00921                                         xp += x;
00922                                         yp += y;
00923                                         count++;
00924                                 }
00925                         }
00926                 }
00927                 return new Point((int) (xp / count), (int) (yp / count));
00928         }
00929 
00935         public static Point getAveragePoint(short[] lumenMask, int width,
00936                         int height, short currentId) {
00937                 double xp = 0;
00938                 double yp = 0;
00939                 double count = 0;
00940                 for (int x = 0; x < width; x++) {
00941                         for (int y = 0; y < height; y++) {
00942                                 if (lumenMask[x + y * width] == currentId) {
00943                                         xp += x;
00944                                         yp += y;
00945                                         count++;
00946                                 }
00947                         }
00948                 }
00949                 return new Point((int) (xp / count), (int) (yp / count));
00950         }
00951 
00961         public static short[] distance2d(short[] input, int width, int height) {
00962                 short[] pixels = input.clone();
00963                 for (int x = 0; x < width; x++) {
00964                         for (int y = 0; y < height; y++) {
00965                                 int index = x + y * width;
00966                                 if (pixels[index] != 0)
00967                                         pixels[index] = (short) 254;
00968                                 if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
00969                                         pixels[index] = 0;
00970                         }
00971                 }
00972                 final int[] wf = new int[] { 1, 1, 1, 1, 0, 0, 0, 0, 0 };
00973                 final int[] wb = new int[] { 0, 0, 0, 0, 0, 1, 1, 1, 1 };
00974                 // Note that we ignore pixels on the edge of the image to avoid problems
00975                 // Forward iteration:
00976                 for (int x = 1; x < width - 1; x++) {
00977                         for (int y = 1; y < height - 1; y++) {
00978                                 int index = x + y * width;
00979                                 int[] slask = new int[3 * 3];
00980                                 int min = 255;
00981                                 for (int j = -1; j < 2; j++) {
00982                                         for (int i = -1; i < 2; i++) {
00983                                                 int slaskindex = (i + 1) + (j + 1) * 3;
00984                                                 if (wf[slaskindex] != 0) {
00985                                                         slask[slaskindex] = Math.min(255, wf[slaskindex]
00986                                                                         + pixels[index + (i) + j * width]);
00987                                                         if (slask[slaskindex] < min)
00988                                                                 min = slask[slaskindex];
00989                                                 }
00990                                         }
00991                                 }
00992                                 if (min < (pixels[index])) {
00993                                         pixels[index] = (short) min;
00994                                 }
00995                         }
00996                 }
00997                 // Backward iteration:
00998                 for (int x = width - 2; x > 1; x--) {
00999                         for (int y = height - 2; y > 1; y--) {
01000                                 int index = x + y * width;
01001                                 int[] slask = new int[3 * 3];
01002                                 int min = 255;
01003                                 for (int j = -1; j < 2; j++) {
01004                                         for (int i = -1; i < 2; i++) {
01005                                                 int slaskindex = (i + 1) + (j + 1) * 3;
01006                                                 if (wb[slaskindex] != 0) {
01007                                                         slask[slaskindex] = Math.min(255, wb[slaskindex]
01008                                                                         + pixels[index + (i) + j * width]);
01009                                                         if (slask[slaskindex] < min)
01010                                                                 min = slask[slaskindex];
01011                                                 }
01012                                         }
01013                                 }
01014                                 if (min < (pixels[index])) {
01015                                         pixels[index] = (short) min;
01016                                 }
01017                         }
01018                 }
01019                 return pixels;
01020         }
01021 
01028         public static short[] distance2d(short[] input, int width, int height,
01029                         Rectangle bounds) {
01030                 short[] pixels = input.clone();
01031                 int startX = (int) bounds.getX();
01032                 int startY = (int) bounds.getY();
01033                 if (startX < 1)
01034                         startX = 1;
01035                 if (startY < 1)
01036                         startY = 1;
01037                 int stopX = startX + (int) bounds.getWidth();
01038                 if (stopX > width - 2)
01039                         stopX = width - 2;
01040                 int stopY = startY + (int) bounds.getHeight();
01041                 if (stopY > height - 2)
01042                         stopY = height - 2;
01043                 for (int x = 0; x < width; x++) {
01044                         for (int y = 0; y < height; y++) {
01045                                 int index = x + y * width;
01046                                 if (pixels[index] != 0)
01047                                         pixels[index] = (short) 254;
01048                                 if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
01049                                         pixels[index] = 0;
01050                         }
01051                 }
01052                 final int[] wf = new int[] { 1, 1, 1, 1, 0, 0, 0, 0, 0 };
01053                 final int[] wb = new int[] { 0, 0, 0, 0, 0, 1, 1, 1, 1 };
01054                 // Note that we ignore pixels on the edge of the image to avoid problems
01055                 // Forward iteration:
01056                 for (int x = startX; x < stopX; x++) {
01057                         for (int y = startY; y < stopY; y++) {
01058                                 int index = x + y * width;
01059                                 int[] slask = new int[3 * 3];
01060                                 int min = 255;
01061                                 for (int j = -1; j < 2; j++) {
01062                                         for (int i = -1; i < 2; i++) {
01063                                                 int slaskindex = (i + 1) + (j + 1) * 3;
01064                                                 if (wf[slaskindex] != 0) {
01065                                                         slask[slaskindex] = Math.min(255, wf[slaskindex]
01066                                                                         + pixels[index + (i) + j * width]);
01067                                                         if (slask[slaskindex] < min)
01068                                                                 min = slask[slaskindex];
01069                                                 }
01070                                         }
01071                                 }
01072                                 if (min < (pixels[index])) {
01073                                         pixels[index] = (short) min;
01074                                 }
01075                         }
01076                 }
01077                 // Backward iteration:
01078                 for (int x = stopX; x >= startX; x--) {
01079                         for (int y = stopY; y >= startY; y--) {
01080                                 int index = x + y * width;
01081                                 int[] slask = new int[3 * 3];
01082                                 int min = 255;
01083                                 for (int j = -1; j < 2; j++) {
01084                                         for (int i = -1; i < 2; i++) {
01085                                                 int slaskindex = (i + 1) + (j + 1) * 3;
01086                                                 if (wb[slaskindex] != 0) {
01087                                                         slask[slaskindex] = Math.min(255, wb[slaskindex]
01088                                                                         + pixels[index + (i) + j * width]);
01089                                                         if (slask[slaskindex] < min)
01090                                                                 min = slask[slaskindex];
01091                                                 }
01092                                         }
01093                                 }
01094                                 if (min < (pixels[index])) {
01095                                         pixels[index] = (short) min;
01096                                 }
01097                         }
01098                 }
01099                 return pixels;
01100         }
01101 
01110         public static void distance3d(Stack voxels) {
01111                 int width = voxels.getWidth();
01112                 int height = voxels.getHeight();
01113                 int depth = voxels.getDepth();
01114                 ThebaGUI control = ThebaGUI.getInstance();
01115                 // set borders to 0
01116                 for (int z = 0; z < depth; z++) {
01117                         for (int x = 0; x < width; x++) {
01118                                 for (int y = 0; y < height; y++) {
01119                                         int index = x + y * width;
01120                                         if (z == 0 || x == 0 || y == 0 || z == depth - 1
01121                                                         || y == height - 1 || x == width - 1)
01122                                                 voxels.getSlice(z)[index] = (short) 0;
01123                                         else
01124                                                 voxels.getSlice(z)[index] = (short) (0xff - (voxels
01125                                                                 .getSlice(z)[index]));
01126                                 }
01127                         }
01128                 }
01129                 // int a = 3, b = 4, c = 3, d = 4, e = 5;
01130                 int a = 3, b = 4, c = 5, d = 3, e = 7;
01131                 int[] wf = new int[] { e, d, e, d, c, d, e, d, e, b, a, b, a, 255, 255,
01132                                 255, 255, 255, };
01133                 int[] wb = new int[] { 255, 255, 255, 255, 255, a, b, a, b, e, d, e, d,
01134                                 c, d, e, d, e, };
01135                 int[] slask = new int[2 * 3 * 3];
01136                 // Note that we ignore pixels on the edge of the image to avoid problems
01137                 for (int z = 1; z < depth - 1; z++) {
01138                         control.setProgress(z / 2);
01139                         for (int x = 1; x < width - 1; x++) {
01140                                 for (int y = 1; y < height - 1; y++) {
01141                                         int index = x + y * width;
01142                                         for (int k = -1; k < 1; k++) {
01143                                                 for (int j = -1; j < 2; j++) {
01144                                                         for (int i = -1; i < 2; i++) {
01145                                                                 int slaskindex = (i + 1) + (j + 1) * 3
01146                                                                                 + (k + 1) * 3 * 3;
01147                                                                 slask[slaskindex] = (voxels.getSlice(z + k)[index
01148                                                                                 + (i) + j * width])
01149                                                                                 + wf[slaskindex];
01150                                                         }
01151                                                 }
01152                                         }
01153                                         int minval = slask[0]; // init to max
01154                                         for (int i = 1; i < slask.length; i++) {
01155                                                 if ((slask[i]) < minval)
01156                                                         minval = (slask[i]);
01157                                         }
01158                                         if ((voxels.getSlice(z)[index]) > minval) {
01159                                                 voxels.getSlice(z)[index] = (short) minval;
01160                                         }
01161                                 }
01162                         }
01163                 }
01164                 // Second backward iteration:
01165                 for (int z = depth - 2; z > 0; z--) {
01166                         control.setProgress((depth - z / 2));
01167                         for (int x = width - 2; x > 0; x--) {
01168                                 for (int y = height - 2; y > 0; y--) {
01169                                         int index = x + y * width;
01170                                         for (int k = 0; k < 2; k++) {
01171                                                 for (int j = -1; j < 2; j++) {
01172                                                         for (int i = -1; i < 2; i++) {
01173                                                                 int slaskindex = (i + 1) + (j + 1) * 3 + (k)
01174                                                                                 * 3 * 3;
01175                                                                 slask[slaskindex] = (voxels.getSlice(z + k)[index
01176                                                                                 + (i) + j * width])
01177                                                                                 + wb[slaskindex];
01178                                                         }
01179                                                 }
01180                                         }
01181                                         int minval = slask[0]; // init to max
01182                                         for (int i = 1; i < slask.length; i++) {
01183                                                 if ((slask[i]) < minval)
01184                                                         minval = (slask[i]);
01185                                         }
01186                                         if ((voxels.getSlice(z)[index]) > minval)
01187                                                 voxels.getSlice(z)[index] = (short) minval;
01188                                 }
01189                         }
01190                 }
01191                 try {
01192                         System.out.println("Writing to file dmap.raw");
01193                         FileOutputStream fs = new FileOutputStream("dmap.raw");
01194                         short[] buffer = new short[width]; // read and write one scanline at once
01195                         for (int z = 0; z < depth; z++)
01196                                 for (int y = 0; y < height; y++) {
01197                                         for (int x = 0; x < width; x++) {
01198                                                 buffer[x] = voxels.getSlice(z)[x + y * width];
01199                                         }
01200                                         byte[] out = DataConversion.shortToBytes(buffer);
01201                                         fs.write(out);
01202                                 }
01203                 } catch (IOException e1) {
01204                         e1.printStackTrace();
01205                 }
01206                 control.setProgressComplete();
01207         }
01208 
01214         public static double eccentricity(short[] pixels, int width, int height) {
01215                 return (new EccentricityDescriptor()).measure(pixels, width, height);
01216         }
01217 
01218         
01229         public static Rectangle getBounds(short[] image, int width, int height,
01230                         int margin) {
01231                 int xMax = 0, yMax = 0;
01232                 int xMin = width, yMin = height;
01233                 for (int x = 0; x < width; x++)
01234                         for (int y = 0; y < height; y++) {
01235                                 if (image[x + y * width] != 0) {
01236                                         if (x > xMax)
01237                                                 xMax = x;
01238                                         if (y > yMax)
01239                                                 yMax = y;
01240                                         if (x < xMin)
01241                                                 xMin = x;
01242                                         if (y < yMin)
01243                                                 yMin = y;
01244                                 }
01245                         }
01246                 if (xMax == 0 || yMax == 0 || xMin == width || yMin == height)
01247                         return null;
01248                 Rectangle bounds = new Rectangle(xMin, yMin, xMax - xMin, yMax - yMin);
01249                 bounds.x = bounds.x - margin;
01250                 bounds.y = bounds.y - margin;
01251                 bounds.width = bounds.width + 2 * margin;
01252                 bounds.height = bounds.height + 2 * margin;
01253                 if (bounds.x < 0)
01254                         bounds.x = 0;
01255                 if (bounds.y < 0)
01256                         bounds.y = 0;
01257                 if (bounds.width + bounds.x > width)
01258                         bounds.width = width - bounds.x;
01259                 if (bounds.height + bounds.y > height)
01260                         bounds.height = height - bounds.y;
01261                 if (bounds.height < 0)
01262                         bounds.height = 0;
01263                 if (bounds.width < 0)
01264                         bounds.width = 0;
01265                 return bounds;
01266         }
01267 
01274         public static Rectangle getBounds(short[] image, int width, int height,
01275                         int margin, short id) {
01276                 int xMax = 0, yMax = 0;
01277                 int xMin = width, yMin = height;
01278                 for (int x = 0; x < width; x++)
01279                         for (int y = 0; y < height; y++) {
01280                                 if (image[x + y * width] == id) {
01281                                         if (x > xMax)
01282                                                 xMax = x;
01283                                         if (y > yMax)
01284                                                 yMax = y;
01285                                         if (x < xMin)
01286                                                 xMin = x;
01287                                         if (y < yMin)
01288                                                 yMin = y;
01289                                 }
01290                         }
01291                 if (xMax == 0 || yMax == 0 || xMin == width || yMin == height)
01292                         return null;
01293                 Rectangle bounds = new Rectangle(xMin, yMin, xMax - xMin + 1, yMax
01294                                 - yMin + 1);
01295                 bounds.x = bounds.x - margin;
01296                 bounds.y = bounds.y - margin;
01297                 bounds.width = bounds.width + 2 * margin;
01298                 bounds.height = bounds.height + 2 * margin;
01299                 if (bounds.x < 0)
01300                         bounds.x = 0;
01301                 if (bounds.y < 0)
01302                         bounds.y = 0;
01303                 if (bounds.width + bounds.x > width)
01304                         bounds.width = bounds.x + bounds.width - width;
01305                 if (bounds.height + bounds.y > height)
01306                         bounds.height = bounds.y + bounds.height - height;
01307                 if (bounds.height < 0)
01308                         bounds.height = 0;
01309                 if (bounds.width < 0)
01310                         bounds.width = 0;
01311                 return bounds;
01312         }
01313 
01321         public static int[] getChaincode(ArrayList borderPoints) {
01322                 if (borderPoints == null)
01323                         return null;
01324                 
01325                 // Create 8-freeman chaincode
01326                 int chaincode[] = new int[borderPoints.size()];
01327                 chaincode[0] = 0;
01328                 Point prev = (Point) borderPoints.get(0);
01329                 Point current = null;
01330                 for (int i = 1; i < borderPoints.size(); i++) {
01331                         current = (Point) borderPoints.get(i);
01332                         if (prev.x == current.x) {
01333                                 if (prev.y < current.y) {
01334                                         chaincode[i] = 2;
01335                                 } else { // prev.y > current.y
01336                                         chaincode[i] = 6;
01337                                 }
01338                         } else if (prev.x < current.x) {
01339                                 if (prev.y < current.y) {
01340                                         chaincode[i] = 1;
01341                                 } else if (prev.y > current.y) {
01342                                         chaincode[i] = 7;
01343                                 } else { // prev.y==current.y
01344                                         chaincode[i] = 0;
01345                                 }
01346                         } else { // prev.x > current.x
01347                                 if (prev.y < current.y) {
01348                                         chaincode[i] = 3;
01349                                 } else if (prev.y > current.y) {
01350                                         chaincode[i] = 5;
01351                                 } else { // prev.y==current.y
01352                                         chaincode[i] = 4;
01353                                 }
01354                         }
01355                         prev = current;
01356                 }
01357                 return chaincode;
01358         }
01359 
01360         // There must be no duplicates in xa and no duplicates in ya!
01361         // xa and ya must be of equal length!
01362         // This is Nevilles Algorithm
01363         public static double getInterpolatedValue(double[] xa, double[] ya, double x) {
01364                 if (xa.length != ya.length) {
01365                         System.err.println("Wrong dimension in input, xa, ya must be equal in length");
01366                         return Double.NaN;
01367                 }
01368                 int ns = 1;
01369                 double y, dy;
01370                 double den, dif, dift, ho, hp, w;
01371                 int n = xa.length;
01372                 double[] c = new double[n];
01373                 double[] d = new double[n];
01374                 // find the index ns of the closest table entry
01375                 dif = Math.abs(x - xa[0]);
01376                 for (int i = 1; i <= n; i++) {
01377                         dift = Math.abs(x - xa[i - 1]);
01378                         if (dift > dif) {
01379                                 ns = i;
01380                                 dif = dift;
01381                         }
01382                         c[i - 1] = ya[i - 1];
01383                         d[i - 1] = ya[i - 1];
01384                 }
01385                 y = ya[ns - 1]; // initial approximation
01386                 for (int m = 1; m < n; m++) {
01387                         for (int i = 1; i <= n - m; i++) {
01388                                 ho = xa[i - 1] - x;
01389                                 hp = xa[i + m - 1] - x;
01390                                 w = c[i] - d[i - 1];
01391                                 den = ho - hp;
01392                                 if (den == 0.0) {
01393                                         // Illegal input -- two equal x-coordinates
01394                                         // "Fix" by saying that they're slightly different
01395                                         den = 0.0001;
01396                                 }
01397                                 den = w / den;
01398                                 d[i - 1] = hp * den;
01399                                 c[i - 1] = ho * den;
01400                         }
01401                         if (2 * ns < (n - m)) {
01402                                 dy = c[ns];
01403                         } else {
01404                                 dy = d[ns - 1];
01405                                 ns--;
01406                         }
01407                         y += dy;
01408                 }
01409                 return y;
01410         }
01411 
01419         public static short[] invertMask(short[] input, boolean in_place) {
01420                 short[] output;
01421                 if (in_place)
01422                         output = input;
01423                 else
01424                         output = new short[input.length];
01425                 for (int i = 0; i < input.length; i++) {
01426                         if (input[i] != 0)
01427                                 output[i] = 0;
01428                         else
01429                                 output[i] = 255;
01430                 }
01431                 return output;
01432         }
01433 
01445         public static short[] mask(short[] input, short[] mask, boolean in_place) {
01446                 if (in_place) {
01447                         for (int i = 0; i < input.length; i++) {
01448                                 if (mask[i] == 0)
01449                                         input[i] = 0;
01450                         }
01451                         return input;
01452                 }
01453                 short[] output = new short[input.length];
01454                 if ((input.length != mask.length))
01455                         throw new RuntimeException("all arrays must be of equal length!");
01456                 for (int i = 0; i < input.length; i++) {
01457                         if (mask[i] != 0)
01458                                 output[i] = input[i];
01459                         else
01460                                 output[i] = 0;
01461                 }
01462                 return output;
01463         }
01464 
01476         public static short[] mask(short[] input, short[] mask, boolean in_place,
01477                         int width, int height, Rectangle bounds) {
01478                 int startX = (int) bounds.getX() + 1;
01479                 int startY = (int) bounds.getY() + 1;
01480                 int stopX = startX + (int) bounds.getWidth();
01481                 if (stopX > width)      stopX = width;
01482                 int stopY = startY + (int) bounds.getHeight();
01483                 if (stopY > height)     stopY = height;
01484                 if (in_place) {
01485                         for (int x = startX; x < stopX; x++) {
01486                                 for (int y = startY; y < stopY; y++) {
01487                                         int i = x + y * width;
01488                                         if (mask[i] == 0)       input[i] = 0;
01489                                 }
01490                         }
01491                         return input;
01492                 }
01493                 short[] output = new short[input.length];
01494                 if ((input.length != mask.length))
01495                         throw new RuntimeException("all arrays must be of equal length!");
01496                 for (int x = startX; x < stopX; x++) {
01497                         for (int y = startY; y < stopY; y++) {
01498                                 int i = x + y * width;
01499                                 if (mask[i] != 0)       output[i] = input[i];
01500                                 else output[i] = 0;
01501                         }
01502                 }
01503                 return output;
01504         }
01505 
01511         public static void median3d(Stack voxels) {
01512                 int width = voxels.getWidth();
01513                 int height = voxels.getHeight();
01514                 int depth = voxels.getDepth();
01515                 short[] prevdata = new short[width * height];
01516                 short[] data = new short[width * height];
01517                 short[] nextdata = new short[width * height];
01518                 ThebaGUI control = ThebaGUI.getInstance();
01519                 System.arraycopy(voxels.getSlice(1), 0, nextdata, 0, nextdata.length);
01520                 System.arraycopy(voxels.getSlice(0), 0, data, 0, data.length);
01521                 for (int z = 1; z < depth - 1; z++) {
01522                         if (control.isStopped())
01523                                 return;
01524                         control.setProgress(z);
01525                         for (int x = 1; x < width - 1; x++) {
01526                                 for (int y = 1; y < height - 1; y++) {
01527                                         int offset = x + y * width;
01528                                         int count = 0;
01529                                         for (int i = -1; i < 2; i++) {
01530                                                 for (int j = -1; j < 2; j++) {
01531                                                         if ((data[offset]) > 0)
01532                                                                 count++;
01533                                                         if ((prevdata[offset]) > 0)
01534                                                                 count++;
01535                                                         if ((nextdata[offset]) > 0)
01536                                                                 count++;
01537                                                 }
01538                                         }
01539                                         if (count > 12)
01540                                                 voxels.getSlice(z)[offset] = 0xff;
01541                                 }
01542                         }
01543                         if (z > 0)
01544                                 System.arraycopy(data, 0, prevdata, 0, prevdata.length);
01545                         System.arraycopy(nextdata, 0, data, 0, data.length);
01546                         if (z < depth - 1)
01547                                 System.arraycopy(voxels.getSlice(z + 1), 0, nextdata, 0,
01548                                                 nextdata.length);
01549                 }
01550         }
01551 
01563         public static boolean touchBorder(short[] mask, int w, int h) {
01564                 boolean touch = false;
01565                 // check right side and left side
01566                 for (int y = 0; y < h; y++) {
01567                         if (mask[y * w] != 0) { // left
01568                                 touch = true;
01569                                 break;
01570                         }
01571                         if (mask[w - 1 + y * w] != 0) { // right
01572                                 touch = true;
01573                                 break;
01574                         }
01575                 }
01576                 if (!touch) {
01577                         for (int x = 0; x < w; x++) {
01578                                 // check bottom and top side
01579                                 if (mask[x] != 0) { // top
01580                                         touch = true;
01581                                         break;
01582                                 }
01583                                 if (mask[x + w * (h - 1)] != 0) {
01584                                         touch = true;
01585                                         break;
01586                                 }
01587                         }
01588                 }
01589                 return touch;
01590         }
01591 
01595         private static final short max(short x, short y) {
01596                 if (x > y)
01597                         return x;
01598                 return y;
01599         }
01600 
01604         private static final short min(short x, short y) {
01605                 if (x < y)
01606                         return x;
01607                 return y;
01608         }
01609 }

Generated on Fri Nov 13 08:57:07 2009 for Theba by  doxygen 1.6.1