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

1    package ip.transforms; 
2     
3    import math.transforms.fft.FFT2d; 
4    import math.transforms.fft.IFFT2d; 
5    import math.transforms.fft.ImageUtils; 
6     
7    import java.awt.*; 
8    import java.awt.image.ImageObserver; 
9    import java.awt.image.MemoryImageSource; 
10   import java.awt.image.PixelGrabber; 
11    
12   // Calculate the transforms.fft of input image, using transforms.fft.FFT2d. 
13    
14   public class FFTImage implements ImageObserver { 
15    
16       int intImage[]; 
17       int imageWidth, imageHeight; 
18       // image.length, or imageWidth * imageHeight 
19       int N; 
20       // scale is used to scale the FFT input to prevent overflow, 
21       // N = imageWidth * imageHeight is often used. 
22       int scale; 
23       // Scale the FFT output magnitude to get the best display result. 
24       float magScale; 
25    
26       boolean fftShift; 
27    
28       short alpha[]; 
29       float redRe[], greenRe[], blueRe[]; 
30       float redIm[], greenIm[], blueIm[]; 
31    
32       public boolean imageUpdate(Image img, int infoflags, 
33                                  int x, int y, int width, int height) { 
34           initImage(img); 
35           return true; 
36       } 
37    
38       public FFTImage(Image img) { 
39    
40           initImage(img); 
41       } 
42    
43       /** 
44        *    uses one image to filter another. 
45        *    only works if the two images are the same size. 
46        */ 
47       public static Image filter(Image img1, Image img2) { 
48           FFTImage fimg1 = new FFTImage(img1); 
49           FFTImage fimg2 = new FFTImage(img2); 
50           fimg1.fft(); 
51           fimg2.fft(); 
52           fimg1.mult(fimg2); 
53           fimg1.ifft(); 
54           return fimg1.getImage(); 
55       } 
56    
57       public Image getImage() { 
58           Toolkit tk = Toolkit.getDefaultToolkit(); 
59           return tk.createImage( 
60                   new MemoryImageSource( 
61                           imageWidth, 
62                           imageHeight, 
63                           tk.getColorModel(), 
64                           intImage, 0, 
65                           imageWidth)); 
66       } 
67    
68       private void initImage(Image img) { 
69           if (img == null) return; 
70           int width = img.getWidth(this); 
71           int height = img.getHeight(this); 
72    
73    
74           int intImage[] = new int[width * height]; 
75    
76           PixelGrabber grabber = 
77                   new PixelGrabber( 
78                           img, 0, 0, 
79                           width, height, true); 
80           imageWidth = grabber.getWidth(); 
81           imageHeight = grabber.getHeight(); 
82    
83           try { 
84               grabber.grabPixels(); 
85           } catch (InterruptedException e) { 
86           } 
87           initVariables((int[]) grabber.getPixels(), imageWidth, 100.0f, true); 
88       } 
89    
90    
91       /** 
92        *  complex multiply, for filtering 
93        */ 
94       public void mult(FFTImage f) { 
95           for (int i = 0; i < redRe.length; i++) { 
96               redRe[i] *= f.redRe[i] / 255.0f; 
97               greenRe[i] *= f.greenRe[i] / 255.0f; 
98               blueRe[i] *= f.blueRe[i] / 255.0f; 
99               redIm[i] *= f.redIm[i] / 255.0f; 
100              greenIm[i] *= f.greenIm[i] / 255.0f; 
101              blueIm[i] *= f.blueIm[i] / 255.0f; 
102          } 
103      } 
104   
105      // getPels(), width, 100.0f, true 
106      public FFTImage(int intImage[], int imageWidth, 
107                      float magScale, boolean fftShift) { 
108          initVariables(intImage, imageWidth, magScale, fftShift); 
109   
110      } 
111   
112      private void initVariables(int[] intImage, int imageWidth, float magScale, boolean fftShift) { 
113          this.intImage = intImage; 
114          this.imageWidth = imageWidth; 
115          N = intImage.length; 
116          imageHeight = N / imageWidth; 
117          this.magScale = magScale; 
118          this.fftShift = fftShift; 
119          scale = N; 
120   
121          alpha = ImageUtils.getAlpha(intImage); 
122          short red[] = ImageUtils.getRed(intImage); 
123          short green[] = ImageUtils.getGreen(intImage); 
124          short blue[] = ImageUtils.getBlue(intImage); 
125   
126          // If fftShift is true, shift the zero frequency to the center. 
127          redRe = fftReorder(red); 
128          greenRe = fftReorder(green); 
129          blueRe = fftReorder(blue); 
130          redIm = new float[N]; 
131          greenIm = new float[N]; 
132          blueIm = new float[N]; 
133      } 
134   
135      public void fft() { 
136          intImage = getFftIntArray(); 
137      } 
138   
139      public int[] getFftIntArray() { 
140          new FFT2d(redRe, redIm, imageWidth); 
141          new FFT2d(greenRe, greenIm, imageWidth); 
142          new FFT2d(blueRe, blueIm, imageWidth); 
143   
144          float resultRed[] = magnitude(redRe, redIm); 
145          float resultGreen[] = magnitude(greenRe, greenIm); 
146          float resultBlue[] = magnitude(blueRe, blueIm); 
147   
148          int resultImage[] = ImageUtils.argbToInt(alpha, resultRed, 
149                  resultGreen, resultBlue); 
150          return resultImage; 
151      } 
152   
153      public void ifft() { 
154          intImage = getIfftIntArray(); 
155      } 
156   
157      public int[] getIfftIntArray() { 
158          new IFFT2d(redRe, redIm, imageWidth); 
159          new IFFT2d(greenRe, greenIm, imageWidth); 
160          new IFFT2d(blueRe, blueIm, imageWidth); 
161   
162          short resultRed[] = ifftReorder(redRe); 
163          short resultGreen[] = ifftReorder(greenRe); 
164          short resultBlue[] = ifftReorder(blueRe); 
165   
166          int resultImage[] = ImageUtils.argbToInt(alpha, resultRed, 
167                  resultGreen, resultBlue); 
168          return resultImage; 
169      } 
170   
171      // reorder color data of transforms.fft input. 
172      // 1. Convert color data from short to float. 
173      // 2. Scale the color data by scale. 
174      // 3. If fftShift is true, shift the zero frequency in the center of matrix. 
175      private float[] fftReorder(short color[]) { 
176          float result[] = new float[N]; 
177   
178          if (!fftShift) {   // Without zero frequency shift. 
179              for (int i = 0; i < N; i++) 
180                  result[i] = (float) color[i] / scale; 
181          } else {            // With zero frequency shift. 
182              int k = 0; 
183              float alternateSign = 1; 
184              for (int i = 0; i < imageHeight; i++) 
185                  for (int j = 0; j < imageWidth; j++) { 
186                      alternateSign = ((i + j) % 2 == 0) ? -1 : 1; 
187                      result[i * imageWidth + j] = (float) (color[k++] * alternateSign / scale); 
188                  } 
189          } 
190          return result; 
191      } // End of function fftReorder(). 
192   
193      private short[] ifftReorder(float re[]) { 
194          short result[] = new short[N]; 
195   
196          if (!fftShift) {   // Without zero frequency shift. 
197              for (int i = 0; i < N; i++) 
198                  result[i] = (short) (re[i] * scale); 
199          } else {            // With zero frequency shift. 
200              int k = 0; 
201              float alternateSign = 1; 
202              for (int i = 0; i < imageHeight; i++) 
203                  for (int j = 0; j < imageWidth; j++) { 
204                      alternateSign = ((i + j) % 2 == 0) ? -1 : 1; 
205                      result[i * imageWidth + j] = (short) (re[k++] * alternateSign * scale); 
206                  } 
207          } 
208          return result; 
209      } // End of function fftReorder(). 
210   
211      // Scale the FFT output magnitude to get the best display result. 
212      private float[] magnitude(float re[], float im[]) { 
213          float result[] = new float[N]; 
214          for (int i = 0; i < N; i++) { 
215              result[i] = (float) (magScale * 
216                      Math.log(1 + Math.sqrt(re[i] * re[i] + im[i] * im[i]))); 
217              if (result[i] > 255) 
218                  result[i] = 255; 
219          } 
220          return result; 
221      } // End of function magnitude(). 
222   
223  } // End of class FFTImage. 
224