3 import java.awt.image.ColorModel;
15 private boolean isFrequencyDomain;
20 private float[] tempArr;
21 private boolean showProgress =
true;
48 while(i<width) i *= 2;
49 return i==width && width==height;
79 throw new IllegalArgumentException(
"Image not power of 2 size or not square: "+width+
"x"+height);
82 makeSinCosTables(maxN);
83 makeBitReverseTable(maxN);
84 tempArr =
new float[maxN];
87 rc2DFHT(fht, inverse, maxN);
88 isFrequencyDomain = !inverse;
91 void makeSinCosTables(
int maxN) {
96 double dTheta = 2.0 * Math.PI/maxN;
97 for (
int i=0; i<n; i++) {
98 C[i] = (float)Math.cos(theta);
99 S[i] = (float)Math.sin(theta);
104 void makeBitReverseTable(
int maxN) {
105 bitrev =
new int[maxN];
106 int nLog2 = log2(maxN);
107 for (
int i=0; i<maxN; i++)
108 bitrev[i] = bitRevX(i, nLog2);
112 void rc2DFHT(
float[] x,
boolean inverse,
int maxN) {
114 for (
int row=0; row<maxN; row++)
115 dfht3(x, row*maxN, inverse, maxN);
119 for (
int row=0; row<maxN; row++)
120 dfht3(x, row*maxN, inverse, maxN);
127 for (
int row=0; row<maxN/2; row++) {
128 for (
int col=0; col<maxN/2; col++) {
129 mRow = (maxN - row) % maxN;
130 mCol = (maxN - col) % maxN;
131 A = x[row * maxN + col];
132 B = x[mRow * maxN + col];
133 C = x[row * maxN + mCol];
134 D = x[mRow * maxN + mCol];
135 E = ((A + D) - (B + C)) / 2;
136 x[row * maxN + col] = A - E;
137 x[mRow * maxN + col] = B + E;
138 x[row * maxN + mCol] = C + E;
139 x[mRow * maxN + mCol] = D - E;
145 void progress(
double percent) {
147 IJ.showProgress(percent);
151 void dfht3 (
float[] x,
int base,
boolean inverse,
int maxN) {
152 int i, stage, gpNum, gpIndex, gpSize, numGps, Nlog2;
154 int Ad0, Ad1, Ad2, Ad3, Ad4, CSAd;
155 float rt1, rt2, rt3, rt4;
158 BitRevRArr(x, base, Nlog2, maxN);
161 for (gpNum=0; gpNum<numGps; gpNum++) {
166 rt1 = x[base+Ad1] + x[base+Ad2];
167 rt2 = x[base+Ad1] - x[base+Ad2];
168 rt3 = x[base+Ad3] + x[base+Ad4];
169 rt4 = x[base+Ad3] - x[base+Ad4];
170 x[base+Ad1] = rt1 + rt3;
171 x[base+Ad2] = rt2 + rt4;
172 x[base+Ad3] = rt1 - rt3;
173 x[base+Ad4] = rt2 - rt4;
182 for (stage=2; stage<Nlog2; stage++) {
183 for (gpNum=0; gpNum<numGps; gpNum++) {
184 Ad0 = gpNum * gpSize * 2;
187 Ad3 = Ad1 + gpSize / 2;
190 x[base+Ad1] = x[base+Ad1] + x[base+Ad2];
191 x[base+Ad2] = rt1 - x[base+Ad2];
193 x[base+Ad3] = x[base+Ad3] + x[base+Ad4];
194 x[base+Ad4] = rt1 - x[base+Ad4];
195 for (bfNum=1; bfNum<numBfs; bfNum++) {
199 Ad3 = gpSize - bfNum + Ad0;
202 CSAd = bfNum * numGps;
203 rt1 = x[base+Ad2] * C[CSAd] + x[base+Ad4] * S[CSAd];
204 rt2 = x[base+Ad4] * C[CSAd] - x[base+Ad2] * S[CSAd];
206 x[base+Ad2] = x[base+Ad1] - rt1;
207 x[base+Ad1] = x[base+Ad1] + rt1;
208 x[base+Ad4] = x[base+Ad3] + rt2;
209 x[base+Ad3] = x[base+Ad3] - rt2;
220 for (i=0; i<maxN; i++)
221 x[base+i] = x[base+i] / maxN;
225 void transposeR (
float[] x,
int maxN) {
229 for (r=0; r<maxN; r++) {
230 for (c=r; c<maxN; c++) {
232 rTemp = x[r*maxN + c];
233 x[r*maxN + c] = x[c*maxN + r];
234 x[c*maxN + r] = rTemp;
242 while (!btst(x, count))
248 private boolean btst (
int x,
int bit) {
250 return ((x & (1<<bit)) != 0);
253 void BitRevRArr (
float[] x,
int base,
int bitlen,
int maxN) {
254 for (
int i=0; i<maxN; i++)
255 tempArr[i] = x[base+bitrev[i]];
256 for (
int i=0; i<maxN; i++)
257 x[base+i] = tempArr[i];
260 private int bitRevX (
int x,
int bitlen) {
262 for (
int i=0; i<=bitlen; i++)
263 if ((x & (1<<i)) !=0)
264 temp |= (1<<(bitlen-i-1));
265 return temp & 0x0000ffff;
268 private int bset (
int x,
int bit) {
276 if (!isFrequencyDomain)
277 throw new IllegalArgumentException(
"Frequency domain image required");
280 float min = Float.MAX_VALUE;
281 float max = Float.MIN_VALUE;
282 float[] fps =
new float[maxN*maxN];
283 byte[] ps =
new byte[maxN*maxN];
286 for (
int row=0; row<maxN; row++) {
287 FHTps(row, maxN, fht, fps);
289 for (
int col=0; col<maxN; col++) {
299 min = (float)Math.log(min);
300 max = (float)Math.log(max);
301 scale = (float)(253.0/(max-min));
303 for (
int row=0; row<maxN; row++) {
305 for (
int col=0; col<maxN; col++) {
310 r = (float)Math.log(r);
311 ps[base+col] = (byte)(((r-min)*scale+0.5)+1);
320 void FHTps(
int row,
int maxN,
float[] fht,
float[] ps) {
323 for (
int c=0; c<maxN; c++) {
324 l = ((maxN-row)%maxN) * maxN + (maxN-c)%maxN;
325 ps[base+c] = (sqr(fht[base+c]) + sqr(fht[l]))/2f;
329 ImageProcessor calculateAmplitude(
float[] fht,
int maxN) {
330 float[] amp =
new float[maxN*maxN];
331 for (
int row=0; row<maxN; row++) {
332 amplitude(row, maxN, fht, amp);
340 void amplitude(
int row,
int maxN,
float[] fht,
float[] amplitude) {
343 for (
int c=0; c<maxN; c++) {
344 l = ((maxN-row)%maxN) * maxN + (maxN-c)%maxN;
345 amplitude[base+c] = (float)Math.sqrt(sqr(fht[base+c]) + sqr(fht[l]));
364 ip.
setRoi(size,0,size,size);
366 ip.
setRoi(0,size,size,size);
372 ip.
setRoi(size,size,size,size);
389 for (
int i=0; i<pixels.length; i++) {
392 pixels[i] = (byte)v3;
413 int rowMod, cMod, colMod;
417 float[] tmp =
new float[maxN*maxN];
418 for (
int r =0; r<maxN; r++) {
419 rowMod = (maxN - r) % maxN;
420 for (
int c=0; c<maxN; c++) {
421 colMod = (maxN - c) % maxN;
422 h2e = (h2[r * maxN + c] + h2[rowMod * maxN + colMod]) / 2;
423 h2o = (h2[r * maxN + c] - h2[rowMod * maxN + colMod]) / 2;
425 tmp[r * maxN + c] = (float)(h1[r * maxN + c] * h2e - h1[rowMod * maxN + colMod] * h2o);
427 tmp[r * maxN + c] = (float)(h1[r * maxN + c] * h2e + h1[rowMod * maxN + colMod] * h2o);
438 int rowMod, cMod, colMod;
439 double mag, h2e, h2o;
442 float[] out =
new float[maxN*maxN];
443 for (
int r=0; r<maxN; r++) {
444 rowMod = (maxN - r) % maxN;
445 for (
int c=0; c<maxN; c++) {
446 colMod = (maxN - c) % maxN;
447 mag =h2[r*maxN+c] * h2[r*maxN+c] + h2[rowMod*maxN+colMod] * h2[rowMod*maxN+colMod];
450 h2e = (h2[r*maxN+c] + h2[rowMod*maxN+colMod]);
451 h2o = (h2[r*maxN+c] - h2[rowMod*maxN+colMod]);
452 double tmp = (h1[r*maxN+c] * h2e - h1[rowMod*maxN+colMod] * h2o);
453 out[r*maxN+c] = (float)(tmp/mag);
461 this.showProgress = showProgress;
468 fht.isFrequencyDomain = isFrequencyDomain;