Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "sky.h"
6 static void unshuffle(Pix*, int, int, Pix*);
7 static void unshuffle1(Pix*, int, Pix*);
9 void
10 hinv(Pix *a, int nx, int ny)
11 {
12 int nmax, log2n, h0, hx, hy, hc, i, j, k;
13 int nxtop, nytop, nxf, nyf, c;
14 int oddx, oddy;
15 int shift;
16 int s10, s00;
17 Pix *tmp;
19 /*
20 * log2n is log2 of max(nx, ny) rounded up to next power of 2
21 */
22 nmax = ny;
23 if(nx > nmax)
24 nmax = nx;
25 log2n = log(nmax)/LN2 + 0.5;
26 if(nmax > (1<<log2n))
27 log2n++;
29 /*
30 * get temporary storage for shuffling elements
31 */
32 tmp = (Pix*)malloc(((nmax+1)/2) * sizeof(*tmp));
33 if(tmp == nil) {
34 fprint(2, "hinv: insufficient memory\n");
35 exits("memory");
36 }
38 /*
39 * do log2n expansions
40 *
41 * We're indexing a as a 2-D array with dimensions (nx,ny).
42 */
43 shift = 1;
44 nxtop = 1;
45 nytop = 1;
46 nxf = nx;
47 nyf = ny;
48 c = 1<<log2n;
49 for(k = log2n-1; k>=0; k--) {
50 /*
51 * this somewhat cryptic code generates the sequence
52 * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n
53 */
54 c = c>>1;
55 nxtop = nxtop<<1;
56 nytop = nytop<<1;
57 if(nxf <= c)
58 nxtop--;
59 else
60 nxf -= c;
61 if(nyf <= c)
62 nytop--;
63 else
64 nyf -= c;
66 /*
67 * halve divisors on last pass
68 */
69 if(k == 0)
70 shift = 0;
72 /*
73 * unshuffle in each dimension to interleave coefficients
74 */
75 for(i = 0; i<nxtop; i++)
76 unshuffle1(&a[ny*i], nytop, tmp);
77 for(j = 0; j<nytop; j++)
78 unshuffle(&a[j], nxtop, ny, tmp);
79 oddx = nxtop & 1;
80 oddy = nytop & 1;
81 for(i = 0; i<nxtop-oddx; i += 2) {
82 s00 = ny*i; /* s00 is index of a[i,j] */
83 s10 = s00+ny; /* s10 is index of a[i+1,j] */
84 for(j = 0; j<nytop-oddy; j += 2) {
85 /*
86 * Multiply h0,hx,hy,hc by 2 (1 the last time through).
87 */
88 h0 = a[s00 ] << shift;
89 hx = a[s10 ] << shift;
90 hy = a[s00+1] << shift;
91 hc = a[s10+1] << shift;
93 /*
94 * Divide sums by 4 (shift right 2 bits).
95 * Add 1 to round -- note that these values are always
96 * positive so we don't need to do anything special
97 * for rounding negative numbers.
98 */
99 a[s10+1] = (h0 + hx + hy + hc + 2) >> 2;
100 a[s10 ] = (h0 + hx - hy - hc + 2) >> 2;
101 a[s00+1] = (h0 - hx + hy - hc + 2) >> 2;
102 a[s00 ] = (h0 - hx - hy + hc + 2) >> 2;
103 s00 += 2;
104 s10 += 2;
106 if(oddy) {
107 /*
108 * do last element in row if row length is odd
109 * s00+1, s10+1 are off edge
110 */
111 h0 = a[s00 ] << shift;
112 hx = a[s10 ] << shift;
113 a[s10 ] = (h0 + hx + 2) >> 2;
114 a[s00 ] = (h0 - hx + 2) >> 2;
117 if(oddx) {
118 /*
119 * do last row if column length is odd
120 * s10, s10+1 are off edge
121 */
122 s00 = ny*i;
123 for(j = 0; j<nytop-oddy; j += 2) {
124 h0 = a[s00 ] << shift;
125 hy = a[s00+1] << shift;
126 a[s00+1] = (h0 + hy + 2) >> 2;
127 a[s00 ] = (h0 - hy + 2) >> 2;
128 s00 += 2;
130 if(oddy) {
131 /*
132 * do corner element if both row and column lengths are odd
133 * s00+1, s10, s10+1 are off edge
134 */
135 h0 = a[s00 ] << shift;
136 a[s00 ] = (h0 + 2) >> 2;
140 free(tmp);
143 static
144 void
145 unshuffle(Pix *a, int n, int n2, Pix *tmp)
147 int i;
148 int nhalf, twon2, n2xnhalf;
149 Pix *p1, *p2, *pt;
151 twon2 = n2<<1;
152 nhalf = (n+1)>>1;
153 n2xnhalf = n2*nhalf; /* pointer to a[i] */
155 /*
156 * copy 2nd half of array to tmp
157 */
158 pt = tmp;
159 p1 = &a[n2xnhalf]; /* pointer to a[i] */
160 for(i=nhalf; i<n; i++) {
161 *pt = *p1;
162 pt++;
163 p1 += n2;
166 /*
167 * distribute 1st half of array to even elements
168 */
169 p2 = &a[n2xnhalf]; /* pointer to a[i] */
170 p1 = &a[n2xnhalf<<1]; /* pointer to a[2*i] */
171 for(i=nhalf-1; i>=0; i--) {
172 p1 -= twon2;
173 p2 -= n2;
174 *p1 = *p2;
177 /*
178 * now distribute 2nd half of array (in tmp) to odd elements
179 */
180 pt = tmp;
181 p1 = &a[n2]; /* pointer to a[i] */
182 for(i=1; i<n; i+=2) {
183 *p1 = *pt;
184 p1 += twon2;
185 pt++;
189 static
190 void
191 unshuffle1(Pix *a, int n, Pix *tmp)
193 int i;
194 int nhalf;
195 Pix *p1, *p2, *pt;
197 nhalf = (n+1) >> 1;
199 /*
200 * copy 2nd half of array to tmp
201 */
202 pt = tmp;
203 p1 = &a[nhalf]; /* pointer to a[i] */
204 for(i=nhalf; i<n; i++) {
205 *pt = *p1;
206 pt++;
207 p1++;
210 /*
211 * distribute 1st half of array to even elements
212 */
213 p2 = &a[nhalf]; /* pointer to a[i] */
214 p1 = &a[nhalf<<1]; /* pointer to a[2*i] */
215 for(i=nhalf-1; i>=0; i--) {
216 p1 -= 2;
217 p2--;
218 *p1 = *p2;
221 /*
222 * now distribute 2nd half of array (in tmp) to odd elements
223 */
224 pt = tmp;
225 p1 = &a[1]; /* pointer to a[i] */
226 for(i=1; i<n; i+=2) {
227 *p1 = *pt;
228 p1 += 2;
229 pt++;