Print

Print


Commit in CDMS/src/CDMS/ImageNavigatorII on MAIN
Stitcher.java+135-1291.1 -> 1.2
Updated with commenting/documentation and cleaner code.  Also should be slightly faster, only writing non-blank images.

CDMS/src/CDMS/ImageNavigatorII
Stitcher.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Stitcher.java	28 Jul 2010 17:32:33 -0000	1.1
+++ Stitcher.java	28 Jul 2010 22:03:01 -0000	1.2
@@ -6,138 +6,144 @@
 import java.io.*;
 import javax.imageio.ImageIO;
 import java.util.*;
- 
+
+/*
+ * Looking in the $path given, this program takes the autorun.txt file and the images of 
+ * the form $imageFileName (replace the counting element with "#"), and stitches them 
+ * together into larger images.  Because an image containing all the stitched images 
+ * would be far too large for most computers to handle, these are saved in images of 
+ * width and height $tileW and $tileH, labeled "row_col.png."  It is recommended that 
+ * these are a powers of 2 (Tiler.java has only been extensively tested with these 
+ * both set to 2048).
+ * 
+ * File Structure:
+ * 	>Image Set Folder
+ * 		>gmapviewer.htm	[the website navigator file!]
+ * 		>original_images	[place the autorun.txt file and images in this folder before running this program]
+ * 		>resources	[do not touch these files, they are used by the Google API for the navigator]
+ * 		>stitched_images	[stitched images will be saved here]
+ * 		>tiles	[when you run Tiler.java, the tiles for the navigator will be placed here.]
+ * 
+ * @author Chris Wilen
+ */
+
 public class Stitcher {
     public static void main(String[] args) throws IOException {
-    	try {
-    		//read in the file and create a list of command lines (split by SET_PART_REPEAT)(dont use arg 0)
-    	    String path = "/Users/chriswilen/Documents/Work/Summer_2010/IZipG18M_TB_75x3/tiles/gmapviewer/dropbox";
-    	    String autorunFile = "/origional_images/"+"Autorun_IZipG18M_TB_75x3_11May10.txt";
-        	String imageFileName = "/"+"IZipG18M_TB_75x3-#.png";
-    		String[] lines = getLines(path+autorunFile);
-    	    
-    	    //split the arguments of each line into a list of arguments: number of repeats in row, corrected start X value
-    	    //also, declares some relevant variables: minimum start x, pixel size, maximum number of repeats
-    		ArrayList<Integer> cols = new ArrayList();
-    	    ArrayList<Double> ymins = new ArrayList();
-    	    ArrayList<Double> xmins = new ArrayList();
-    	    ArrayList<Double> moveX = new ArrayList();
-    	    double xMin = 1000;
-    	    int maxCols = 0;
-    	    double pxSize = 3.37085208/620;//1.396/100;
-    	    for (int i=1; i<lines.length; i++){
-    	    	int repeat = Integer.parseInt(lines[i].split(",")[1]);
-    	    	cols.add(repeat);
-    	    	moveX.add(  Double.parseDouble(lines[i].split(",")[3])*2.54*10  );
-    	    	double currentXMin = Double.parseDouble(lines[i].split(",")[11]);
-    	    	xmins.add(currentXMin);
-    	    	double currentYMin = Double.parseDouble(lines[i].split(",")[12]);
-    	    	ymins.add(currentYMin);
-    	    	if (currentXMin<xMin) xMin = currentXMin;
-    	    	if (repeat>maxCols) maxCols = repeat;
-    	    }
-    	    
-    	    //declare variables 
-    	    /*********************/
-            double theta = Math.atan(3/640);//Math.toRadians(0.0);
-        	BufferedImage image = ImageIO.read(new File(  path+"/origional_images/"+imageFileName.replace("#","1")  ));
-            int imgW = image.getWidth();
-            int imgH = image.getHeight();
-            int tileW = 2048;
-            int tileH = 2048;
-            double dX = moveX.get(0)/pxSize;
-            double dY = (ymins.get(0)-ymins.get(1))/pxSize;
-            System.out.println("{"+dX+","+dY+"}");
-            //find size of image holder and make holder
-            int holderW = (int)Math.ceil(imgW*Math.cos(theta)+imgH*Math.sin(theta));
-            int holderH = (int)Math.ceil(imgW*Math.sin(theta)+imgH*Math.cos(theta));
-            BufferedImage holder = new BufferedImage(holderW, holderH, image.getType());
-            //find size of total stitched image
-    	    double totalW = (maxCols-1)*dX + imgW*Math.cos(theta) + imgH*Math.sin(theta);
-    	    double totalH = (lines.length-1)*dX + imgW*Math.sin(theta) + imgH*Math.cos(theta);
-            AffineTransform at;
-    	    /*********************/
-            for (int row=0;row<Math.ceil(totalH/tileH); row++) {
-            	for (int col=0;col<Math.ceil(totalW/tileW); col++) {
-            		System.out.println("new tile("+row+","+col+")");
-            		//figure out which images to use
-            		//make a tiled image square
-            		//write the image to toStore
-            		BufferedImage toStore = new BufferedImage(tileW, tileH, image.getType());
-            		WritableRaster toStoreRaster = toStore.getRaster().createCompatibleWritableRaster();
-            		int[][] layers = new int[tileW][tileH];
-    	            Graphics2D g2 = holder.createGraphics();
-            		int lastImage = 0;
-            		for (int r=0; r<lines.length-1; r++) {
-            	    	int nCols = cols.get(r)+1;
-            	    	for (int c=0; c<nCols; c++) {
-            	    		//find out if the img might have a part in the tile
-            	    		double imgDiagonal = Math.sqrt(Math.pow(imgW, 2)+Math.pow(imgH, 2));
-            	    		double minTileRenderX = col*tileW-imgDiagonal;
-            	    		double maxTileRenderX = (col+1)*tileW+imgDiagonal;
-            	    		double minTileRenderY = row*tileW-imgDiagonal;
-            	    		double maxTileRenderY = (row+1)*tileW+imgDiagonal;
-            	    		double drawX = c*dX+(xmins.get(r)-xMin)/pxSize;
-            	    		double drawY = r*dY;
-            	    		lastImage++;
-            	    		//if it is in the tile, make a square with the image tilted appropriately
-            	        	if (drawX>minTileRenderX && drawX<maxTileRenderX && drawY>minTileRenderY && drawY<maxTileRenderY) {
-	            	        	String imagePath = path+"/origional_images/"+imageFileName.replace("#",""+lastImage);
-        	        			image = ImageIO.read(new File(imagePath));
-	            	    		at = AffineTransform.getTranslateInstance(imgH*Math.sin(theta), holderH-imgH);
-	            	            at.rotate(-theta, 0, imgH);
-	            	            g2.drawRenderedImage(image, at);
-	            	            
-	            	            WritableRaster holderRaster = holder.getRaster();
-		            	        
-	            	            //write the square with the tilted image to toStore, averaging with any values already there
-	            	            for (int y=0; y < holderH; ++y) {
-	            	            	for (int x=0; x < holderW; ++x) {
-	            	            		int drawXtoStore = (int)Math.round(drawX-col*tileW+x);
-		            	                int drawYtoStore = (int)Math.round(drawY-row*tileH+y);
-		            	                if (drawXtoStore > 0 && drawXtoStore < tileW && drawYtoStore > 0 && drawYtoStore < tileH) {
-		            	                	double sumR = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 0);
-			            	                double sumG = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 1);
-			            	                double sumB = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 2);
-			            	                double multiplier = 1;
-			            	                if (x<20) { multiplier = 1-x/20; }
-	            	                		if (x>(holderW-20)) { multiplier = (1/20)*(x-(imgW-20)); }
-			            	                int z = layers[drawXtoStore][drawYtoStore];
-			            	                sumR = (z*sumR + multiplier*holderRaster.getSample(x, y, 0))/(z+1);
-			            	                sumG = (z*sumG + multiplier*holderRaster.getSample(x, y, 1))/(z+1);
-			            	                sumB = (z*sumB + multiplier*holderRaster.getSample(x, y, 2))/(z+1);
-			            	                layers[drawXtoStore][drawYtoStore]++;
-			            	                /*sumR += holderRaster.getSample(x, y, 0);
-			            	                sumG += holderRaster.getSample(x, y, 1);
-			            	                sumB += holderRaster.getSample(x, y, 2);*/
-		            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 0, sumR);
-		            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 1, sumG);
-		            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 2, sumB);
-		            	                }
-	            	            	}
-	            	            }
-	            	            /*for (int ypx=0; ypx < tileW; ypx++) {
-	            	            	for (int xpx=0; xpx < tileW; xpx++) {
-	            	            		int divisor = layers[xpx][ypx];
-	            	            		if (divisor!=0) {
-		            	            		toStoreRaster.setSample(xpx, ypx, 0, toStoreRaster.getSample(xpx, ypx, 0)/divisor);
-		            	            		toStoreRaster.setSample(xpx, ypx, 1, toStoreRaster.getSample(xpx, ypx, 1)/divisor);
-		            	            		toStoreRaster.setSample(xpx, ypx, 2, toStoreRaster.getSample(xpx, ypx, 2)/divisor);
-	            	            		}
-		            	            }
-	            	            }*/
-		            	        toStore.setData(toStoreRaster);
-            	        	}
-            	        }
-            	    }
-            		ImageIO.write(toStore, "PNG", new File(path+"/stitched_tiles/tile"+row+"_"+col+".png"));
-            		g2.dispose();
-            	}
-            }
-    	} catch (IOException e) {
-    	}
+    	Date startDate = new Date();
+		//read in the file and create a list of command lines (split by SET_PART_REPEAT)(dont use arg 0)
+	    String path = "/Users/chriswilen/Documents/Work/Summer_2010/IZipG18M_TB_75x3/tiles/gmapviewer/";
+	    String autorunFile = "Autorun_IZipG18M_TB_75x3_11May10.txt";
+    	String imageFileName = "/"+"IZipG18M_TB_75x3-#.png";
+		String[] lines = getLines(path+"/original_images/"+autorunFile);
+	    
+	    //split the arguments of each line into a list of arguments: number of repeats in row, corrected start X value
+	    //also, declares some relevant variables: minimum start x, pixel size, maximum number of repeats
+		ArrayList<Integer> cols = new ArrayList<Integer>();
+	    ArrayList<Double> ymins = new ArrayList<Double>();
+	    ArrayList<Double> xmins = new ArrayList<Double>();
+	    ArrayList<Double> moveX = new ArrayList<Double>();
+	    double xMin = 1000;
+	    int maxCols = 0;
+	    double pxSize = 5.452/1000;//3.37085208/620;//x75.3 magnification: 5.452um
+	    for (int i=1; i<lines.length; i++){
+	    	int repeat = Integer.parseInt(lines[i].split(",")[1]);
+	    	cols.add(repeat);
+	    	moveX.add(  Double.parseDouble(lines[i].split(",")[3])*2.54*10  );
+	    	double currentXMin = Double.parseDouble(lines[i].split(",")[11]);
+	    	xmins.add(currentXMin);
+	    	double currentYMin = Double.parseDouble(lines[i].split(",")[12]);
+	    	ymins.add(currentYMin);
+	    	if (currentXMin<xMin) xMin = currentXMin;
+	    	if (repeat>maxCols) maxCols = repeat;
+	    }
+	    
+	    //declare variables 
+	    /*********************/
+        double theta = Math.atan(3/640);
+    	BufferedImage image = ImageIO.read(new File(  path+"/original_images/"+imageFileName.replace("#","1")  ));
+        int imgW = image.getWidth();
+        int imgH = image.getHeight();
+        int tileW = 2048;
+        int tileH = 2048;
+        double dX = moveX.get(0)/pxSize;
+        double dY = (ymins.get(0)-ymins.get(1))/pxSize;
+        System.out.println("Offset: {"+(dX-640)+","+(dY-480)+"}");
+        //find size of image holder and make holder
+        int holderW = (int)Math.ceil(imgW*Math.cos(theta)+imgH*Math.sin(theta));
+        int holderH = (int)Math.ceil(imgW*Math.sin(theta)+imgH*Math.cos(theta));
+        BufferedImage holder = new BufferedImage(holderW, holderH, image.getType());
+        //find size of total stitched image
+	    double totalW = (maxCols-1)*dX + imgW*Math.cos(theta) + imgH*Math.sin(theta);
+	    double totalH = (lines.length-1)*dX + imgW*Math.sin(theta) + imgH*Math.cos(theta);
+        AffineTransform at;
+	    /*********************/
+        for (int row=0;row<Math.ceil(totalH/tileH); row++) {
+        	for (int col=0;col<Math.ceil(totalW/tileW); col++) {
+        		System.out.println("new tile("+row+","+col+")");
+        		//figure out which images to use
+        		//make a tiled image square
+        		//write the image to toStore
+        		BufferedImage toStore = new BufferedImage(tileW, tileH, image.getType());
+        		WritableRaster toStoreRaster = toStore.getRaster().createCompatibleWritableRaster();
+        		int[][] layers = new int[tileW][tileH];
+	            Graphics2D g2 = holder.createGraphics();
+        		int lastImage = 0;
+        		boolean draw = false;
+        		for (int r=0; r<lines.length-1; r++) {
+        	    	int nCols = cols.get(r)+1;
+        	    	for (int c=0; c<nCols; c++) {
+        	    		//find out if the img might have a part in the tile
+        	    		double minTileRenderX = col*tileW-imgW;
+        	    		double maxTileRenderX = (col+1)*tileW+imgW;
+        	    		double minTileRenderY = row*tileW-imgH;
+        	    		double maxTileRenderY = (row+1)*tileW+imgH;
+        	    		double drawX = c*dX*Math.cos(theta)+(xmins.get(r)-xMin)/pxSize;
+        	    		double drawY = r*dY+c*dX*Math.sin(theta);
+        	    		lastImage++;
+        	    		//if it is in the tile, make a square with the image tilted appropriately
+        	        	if (drawX>minTileRenderX && drawX<maxTileRenderX && drawY>minTileRenderY && drawY<maxTileRenderY) {
+        	        		String imagePath = path+"/original_images/"+imageFileName.replace("#",""+lastImage);
+    	        			image = ImageIO.read(new File(imagePath));
+            	    		at = AffineTransform.getTranslateInstance(0, 0);
+            	            g2.drawRenderedImage(image, at);
+            	            
+            	            WritableRaster holderRaster = holder.getRaster();
+	            	        
+            	            //write the square with the tilted image to toStore, averaging with any values already there
+            	            for (int y=0; y < holderH; ++y) {
+            	            	for (int x=0; x < holderW; ++x) {
+            	            		int drawXtoStore = (int)Math.round(drawX-col*tileW+x);
+	            	                int drawYtoStore = (int)Math.round(drawY-row*tileH+y);
+	            	                if (drawXtoStore > 0 && drawXtoStore < tileW && drawYtoStore > 0 && drawYtoStore < tileH) {
+	            	                	double sumR = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 0);
+		            	                double sumG = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 1);
+		            	                double sumB = toStoreRaster.getSample(drawXtoStore, drawYtoStore, 2);
+		            	                double multiplier = 1;
+		            	                //if (x<20) { multiplier = 1-x/20; }
+            	                		//if (x>(holderW-20)) { multiplier = (1/20)*(x-(imgW-20)); }
+		            	                int z = layers[drawXtoStore][drawYtoStore];
+		            	                sumR = (z*sumR + multiplier*holderRaster.getSample(x, y, 0))/(z+1);
+		            	                sumG = (z*sumG + multiplier*holderRaster.getSample(x, y, 1))/(z+1);
+		            	                sumB = (z*sumB + multiplier*holderRaster.getSample(x, y, 2))/(z+1);
+		            	                layers[drawXtoStore][drawYtoStore]++;
+		            	                if(sumR!=0 || sumG!=0 || sumB!=0) draw=true;
+	            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 0, sumR);
+	            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 1, sumG);
+	            	            		toStoreRaster.setSample(drawXtoStore, drawYtoStore, 2, sumB);
+	            	                }
+            	            	}
+            	            }
+	            	        toStore.setData(toStoreRaster);
+        	        	}
+        	        }
+        	    }
+        		if (draw==true) ImageIO.write(toStore, "PNG", new File(path+"/stitched_images/"+row+"_"+col+".png"));
+        		g2.dispose();
+        	}
+        }
 
-    	
+        Date endDate = new Date();
+    	System.out.println("\nRuntime: "+(endDate.getTime()-startDate.getTime())/1000/60);
     }
     
     //takes an input path and returns a list of values split by the SET_PART-REPEAT
CVSspam 0.2.8