/Users/lyon/j4p/src/ip/transforms/Wavelet.java

1    /**************************************************************** 
2     *                   CS410X  - JAVA Programming                 * 
3     *                                                              * 
4     *                        Assignment #4                         * 
5     *                                                              * 
6     *                      Haar - Wavelet 2D CODEC                 * 
7     *                                                              * 
8     *      Programmer: Matanya Elchanani, SID:0280923              * 
9     *      Date: Nov. 1st 1997                                     * 
10    *                                                              * 
11    *      File: Wavelet.java                                      * 
12    *                                                              * 
13    **************************************************************** 
14    This program is a 2D form of the previous homework assignment. 
15    I have used the same code (I think it is quite nifty to expend 
16    on a previous work) with minor changes: 
17    1. The prime matrix filler now works on a 2D matrix. 
18    2. The multilevel Forward and Inverse Haar-Wavelet methods were 
19    revised so they iterate through a 2D array, applying the 
20    transform to each row at a time. 
21    3. An overloaded 2D show method was added to be able to present 
22    the whole 2D array at the beginning. 
23    
24    The rest of this remark is taken from the previous code: 
25    
26    This program will fill an array with prime numbers. It will then 
27    Apply the Haar-Wavelet algorithm to the data and extract averages 
28    and difference coefficients repeatedly, until all data has been 
29    converted, and a single "father of all data" value is left as the 
30    first member of the array. The rest of the array will contain 
31    growing sets of difference coefficients. 
32    
33    The above array is then operated over with an inverse Haar-Wavelet 
34    algorithm, which uses the "father of all data" and the difference 
35    coefficients to gradually reconstruct the the original data. 
36    
37    Author's remark: Instead of using a set of matrices to hold the 
38    resulting coefficients (as the assignment suggested), I have chosen 
39    to use an overwrite of the original data in a vector. This is 
40    possible because for N data points, N/2 averages and N/2 
41    coefficients are written, so we can safely overwrite the old N data 
42    points. This method is much more efficient from a memory usage 
43    point, and keeps the data in a single dimension orientation (which 
44    is recommended as this is a single dimension CODEC). 
45    
46    As can be seen from the results, the usage of integers introduces 
47    rounding errors which eventually cause "noise" in the reconstructed 
48    data. Using floats to hold the averages and coefficients will solve 
49    the problem on the expence of wasting memory for holding floats. 
50    */ 
51    
52   package ip.transforms; 
53    
54   public class Wavelet { 
55       public static void main(String args[]) { 
56           int x[][] = 
57                   { 
58                       {9, 7, 5, 3}, 
59                       {3, 5, 7, 9}, 
60                       {2, 4, 6, 8}, 
61                       {4, 6, 8, 10} 
62                   }; 
63           demo(x); 
64           int y[][] = 
65                   { 
66                       {1, 2, 3, 4}, 
67                       {4, 3, 2, 1}, 
68                       {1, 2, 3, 4}, 
69                       {4, 3, 2, 1} 
70                   }; 
71           demo(y); 
72    
73       } 
74    
75       public static void demo(int x[][]) { 
76           show(x, x.length); 
77           System.out.println("Running Forward Haar Wavelet on the matrix:"); 
78           fhw(x); 
79           //x=transpose(x); 
80           //fhw(x); 
81           //System.out.println("Here is what you transmit"); 
82           //show(x); 
83           System.out.println("Running Inverse Haar Wavelet on the matrix:"); 
84           ihw(x); 
85           //x=transpose(x); 
86           //ihw(x); 
87    
88       } 
89    
90       public static void demo2d(int x[][]) { 
91           show(x, x.length); 
92           System.out.println("Running Forward Haar Wavelet on the matrix:"); 
93           fhw(x); 
94           x = transpose(x); 
95           fhw(x); 
96           System.out.println("Here is what you transmit"); 
97           show(x); 
98           System.out.println("Running Inverse Haar Wavelet on the matrix:"); 
99           ihw(x); 
100          x = transpose(x); 
101          ihw(x); 
102      } 
103   
104      static boolean printing = true; 
105   
106      public static void fihw2d(int x[][]) { 
107          printing = false; 
108          fhw(x); 
109          x = transpose(x); 
110          fhw(x); 
111          System.out.println("Here is what you transmit"); 
112          show(x); 
113          ihw(x); 
114          x = transpose(x); 
115          ihw(x); 
116      } 
117   
118      public static void fhw(int x[][]) { 
119          fhw(x, x.length, log2(x.length)); 
120      } 
121   
122      public static void ihw(int x[][]) { 
123          ihw(x, x.length, log2(x.length)); 
124      } 
125   
126      public static int log2(int n) { 
127          return (int) (Math.log(n) / Math.log(2)); 
128      } 
129   
130      public static void main2(String args[]) { 
131   
132   
133  /* Create the 2D data array and fill it with prime numbers */ 
134          int x[][] = new int[8][8]; 
135          fillprime(x); 
136   
137  /* Show our original data (resolution level 1) */ 
138          System.out.println("The original Data:"); 
139          show(x, 8); 
140   
141  /* Now gui.run the multilevel forward haar wavelet transform on the 
142     data, replacing the original array members with their averages 
143     and difference coefficients */ 
144          System.out.println("Running Forward Haar Wavelet on the matrix:"); 
145          fhw(x, 8, 3); 
146   
147  /* Now gui.run the multilevel inverse haar wavelet transform on the 
148     data, replacing the averages and difference coefficients with 
149     the reconstructed data */ 
150          System.out.println("Running Inverse Haar Wavelet on the matrix:"); 
151          ihw(x, 8, 3); 
152          System.out.println("That's all folks."); 
153      } 
154   
155   
156      /** 
157       * Print an array (or part of it) given the size to print. 
158       * This is an overloaded method for showing up a whole 2D 
159       * array. 
160       */ 
161      public static void show(int in[][]) { 
162          show(in, in[0].length); 
163      } 
164   
165      public static void show(int in[][], int size) { 
166   
167          for (int i = 0; i < in.length; i++) { 
168              for (int j = 0; j < size; j++) 
169                  System.out.print(in[i][j] + "\t"); 
170              System.out.println(""); 
171          } 
172          System.out.println("-------------------"); 
173      } 
174   
175      /** 
176       * Print an array (or part of it) given the size to print. 
177       * If colon is true, a coma will be printed half way between 
178       * the members (separating the avereges from the coefficients). 
179       */ 
180      public static void show(int in[], int size, boolean colon) { 
181          if (!printing) return; 
182   
183          for (int i = 0; i < size; i++) { 
184              if ((size / 2 == i) && colon) 
185                  System.out.print(", "); 
186              System.out.print(in[i] + "\t"); 
187          } 
188          System.out.println(""); 
189      } 
190   
191   
192      /** 
193       * Single level Forward Haar Wavelet transform. 
194       */ 
195      public static void fhw(int in[], int size) { 
196          int tmp[] = new int[size]; 
197   
198          for (int i = 0; i < size; i += 2) { 
199              tmp[i / 2] = (in[i] + in[i + 1]) / 2;   //compute the average 
200              tmp[size / 2 + i / 2] = (in[i] - in[i + 1]) / 2; // compute the coeff. 
201          } 
202   
203          for (int i = 0; i < size; i++) //put data back to the array 
204              in[i] = tmp[i]; 
205          show(in, size, true); // and show it 
206      } 
207   
208   
209      /** 
210       * Multilevel 2D forward haar wavelet transform. 
211       * This is an overloaded "fhw" method for applying forward 
212       * haar wavelet "level" times on the matrix, each time with 
213       * half the range, and doing that on each row in the 2D matrix. 
214       */ 
215      public static void fhw(int in[][], int size, int level) { 
216          int range = size; 
217          for (int j = 0; j < level; j++) { 
218              for (int i = 0; i < size; i++) { 
219                  fhw(in[i], range);  // Apply fhw to each row 
220              } 
221              System.out.println("-------------------"); 
222              range /= 2;  // next resolution level 
223          } 
224      } 
225   
226   
227      /** 
228       * Single level Inverse Haar Wavelet transform. 
229       */ 
230      public static void ihw(int in[], int size) { 
231          int tmp[] = new int[size]; 
232   
233          for (int i = 0; i < size; i += 2) {  // reconstruct two members 
234              tmp[i] = in[i / 2] + in[size / 2 + i / 2]; 
235              tmp[i + 1] = in[i / 2] - in[size / 2 + i / 2]; 
236          } 
237   
238          for (int i = 0; i < size; i++)  // put it in the array 
239              in[i] = tmp[i]; 
240          show(in, size, false);  // and show the results 
241      } 
242   
243   
244      /** 
245       * Multilevel 2D inverse haar wavelet transform. 
246       * This is an overloaded "ihw" method for applying inverse 
247       * haar wavelet "level" times on the matrix, each time with 
248       * double the range. 
249       */ 
250   
251      public static void ihw(int in[][], int size, int level) { 
252          int range = size >> (level - 1); 
253          for (int j = 0; j < level; j++) { 
254              for (int i = 0; i < size; i++) { 
255                  ihw(in[i], range);  // Apply ihw on each row 
256              } 
257              if (printing) 
258                  System.out.println("-------------------"); 
259              range *= 2;  // Next resolution level 
260          } 
261      } 
262   
263   
264      /** 
265       * Fill a 2D matrix with prime numbers. 
266       * 
267       */ 
268      public static void fillprime(int in[][]) { 
269          int primenum = 1; 
270          boolean itsprime; 
271   
272          for (int i = 0; i < in.length; i++) {  // fill the whole matrix 
273              for (int j = 0; j < in[i].length; j++) 
274                  do { 
275                      if (itsprime = isprime(primenum)) 
276                          in[i][j] = primenum;  // we have a prime, store it. 
277                      primenum++; 
278                  } while (!itsprime);  // loop as long as it's not a prime 
279          } 
280      } 
281   
282   
283      /** 
284       * Check if a number is prime. 
285       * 
286       */ 
287      public static boolean isprime(int x) { 
288          boolean prime = true;  // assume it is 
289          int div; 
290   
291          div = x / 2;  // check only half the range 
292          while ((div > 1) && prime) { 
293              prime = ((x % div) != 0); 
294              div--; 
295          } 
296          return (prime); 
297      } 
298   
299      public static int[][] transpose(int a[][]) { 
300          int b[][] = new int[a[0].length][a.length]; 
301          for (int x = 0; x < a.length; x++) 
302              for (int y = 0; y < a[0].length; y++) 
303                  b[y][x] = a[x][y]; 
304          return b; 
305      } 
306  }