rsc | 8a3b2ce | 2004-04-24 17:05:43 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <bio.h> |
| 4 | #include "sky.h" |
| 5 | |
| 6 | static void qtree_expand(Biobuf*, uchar*, int, int, uchar*); |
| 7 | static void qtree_copy(uchar*, int, int, uchar*, int); |
| 8 | static void qtree_bitins(uchar*, int, int, Pix*, int, int); |
| 9 | static void read_bdirect(Biobuf*, Pix*, int, int, int, uchar*, int); |
| 10 | |
| 11 | void |
| 12 | qtree_decode(Biobuf *infile, Pix *a, int n, int nqx, int nqy, int nbitplanes) |
| 13 | { |
| 14 | int log2n, k, bit, b, nqmax; |
| 15 | int nx,ny,nfx,nfy,c; |
| 16 | int nqx2, nqy2; |
| 17 | unsigned char *scratch; |
| 18 | |
| 19 | /* |
| 20 | * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 |
| 21 | */ |
| 22 | nqmax = nqy; |
| 23 | if(nqx > nqmax) |
| 24 | nqmax = nqx; |
| 25 | log2n = log(nqmax)/LN2+0.5; |
| 26 | if (nqmax > (1<<log2n)) |
| 27 | log2n++; |
| 28 | |
| 29 | /* |
| 30 | * allocate scratch array for working space |
| 31 | */ |
| 32 | nqx2 = (nqx+1)/2; |
| 33 | nqy2 = (nqy+1)/2; |
| 34 | scratch = (uchar*)malloc(nqx2*nqy2); |
| 35 | if(scratch == nil) { |
| 36 | fprint(2, "qtree_decode: insufficient memory\n"); |
| 37 | exits("memory"); |
| 38 | } |
| 39 | |
| 40 | /* |
| 41 | * now decode each bit plane, starting at the top |
| 42 | * A is assumed to be initialized to zero |
| 43 | */ |
| 44 | for(bit = nbitplanes-1; bit >= 0; bit--) { |
| 45 | /* |
| 46 | * Was bitplane was quadtree-coded or written directly? |
| 47 | */ |
| 48 | b = input_nybble(infile); |
| 49 | if(b == 0) { |
| 50 | /* |
| 51 | * bit map was written directly |
| 52 | */ |
| 53 | read_bdirect(infile, a, n, nqx, nqy, scratch, bit); |
| 54 | } else |
| 55 | if(b != 0xf) { |
| 56 | fprint(2, "qtree_decode: bad format code %x\n",b); |
| 57 | exits("format"); |
| 58 | } else { |
| 59 | /* |
| 60 | * bitmap was quadtree-coded, do log2n expansions |
| 61 | * read first code |
| 62 | */ |
| 63 | |
| 64 | scratch[0] = input_huffman(infile); |
| 65 | |
| 66 | /* |
| 67 | * do log2n expansions, reading codes from file as necessary |
| 68 | */ |
| 69 | nx = 1; |
| 70 | ny = 1; |
| 71 | nfx = nqx; |
| 72 | nfy = nqy; |
| 73 | c = 1<<log2n; |
| 74 | for(k = 1; k<log2n; k++) { |
| 75 | /* |
| 76 | * this somewhat cryptic code generates the sequence |
| 77 | * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy |
| 78 | */ |
| 79 | c = c>>1; |
| 80 | nx = nx<<1; |
| 81 | ny = ny<<1; |
| 82 | if(nfx <= c) |
| 83 | nx--; |
| 84 | else |
| 85 | nfx -= c; |
| 86 | if(nfy <= c) |
| 87 | ny--; |
| 88 | else |
| 89 | nfy -= c; |
| 90 | qtree_expand(infile, scratch, nx, ny, scratch); |
| 91 | } |
| 92 | |
| 93 | /* |
| 94 | * copy last set of 4-bit codes to bitplane bit of array a |
| 95 | */ |
| 96 | qtree_bitins(scratch, nqx, nqy, a, n, bit); |
| 97 | } |
| 98 | } |
| 99 | free(scratch); |
| 100 | } |
| 101 | |
| 102 | /* |
| 103 | * do one quadtree expansion step on array a[(nqx+1)/2,(nqy+1)/2] |
| 104 | * results put into b[nqx,nqy] (which may be the same as a) |
| 105 | */ |
| 106 | static |
| 107 | void |
| 108 | qtree_expand(Biobuf *infile, uchar *a, int nx, int ny, uchar *b) |
| 109 | { |
| 110 | uchar *b1; |
| 111 | |
| 112 | /* |
| 113 | * first copy a to b, expanding each 4-bit value |
| 114 | */ |
| 115 | qtree_copy(a, nx, ny, b, ny); |
| 116 | |
| 117 | /* |
| 118 | * now read new 4-bit values into b for each non-zero element |
| 119 | */ |
| 120 | b1 = &b[nx*ny]; |
| 121 | while(b1 > b) { |
| 122 | b1--; |
| 123 | if(*b1 != 0) |
| 124 | *b1 = input_huffman(infile); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | * copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding |
| 130 | * each value to 2x2 pixels |
| 131 | * a,b may be same array |
| 132 | */ |
| 133 | static |
| 134 | void |
| 135 | qtree_copy(uchar *a, int nx, int ny, uchar *b, int n) |
| 136 | { |
| 137 | int i, j, k, nx2, ny2; |
| 138 | int s00, s10; |
| 139 | |
| 140 | /* |
| 141 | * first copy 4-bit values to b |
| 142 | * start at end in case a,b are same array |
| 143 | */ |
| 144 | nx2 = (nx+1)/2; |
| 145 | ny2 = (ny+1)/2; |
| 146 | k = ny2*(nx2-1) + ny2-1; /* k is index of a[i,j] */ |
| 147 | for (i = nx2-1; i >= 0; i--) { |
| 148 | s00 = 2*(n*i+ny2-1); /* s00 is index of b[2*i,2*j] */ |
| 149 | for (j = ny2-1; j >= 0; j--) { |
| 150 | b[s00] = a[k]; |
| 151 | k -= 1; |
| 152 | s00 -= 2; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | /* |
| 157 | * now expand each 2x2 block |
| 158 | */ |
| 159 | for(i = 0; i<nx-1; i += 2) { |
| 160 | s00 = n*i; /* s00 is index of b[i,j] */ |
| 161 | s10 = s00+n; /* s10 is index of b[i+1,j] */ |
| 162 | for(j = 0; j<ny-1; j += 2) { |
| 163 | b[s10+1] = b[s00] & 1; |
| 164 | b[s10 ] = (b[s00]>>1) & 1; |
| 165 | b[s00+1] = (b[s00]>>2) & 1; |
| 166 | b[s00 ] = (b[s00]>>3) & 1; |
| 167 | s00 += 2; |
| 168 | s10 += 2; |
| 169 | } |
| 170 | if(j < ny) { |
| 171 | /* |
| 172 | * row size is odd, do last element in row |
| 173 | * s00+1, s10+1 are off edge |
| 174 | */ |
| 175 | b[s10 ] = (b[s00]>>1) & 1; |
| 176 | b[s00 ] = (b[s00]>>3) & 1; |
| 177 | } |
| 178 | } |
| 179 | if(i < nx) { |
| 180 | /* |
| 181 | * column size is odd, do last row |
| 182 | * s10, s10+1 are off edge |
| 183 | */ |
| 184 | s00 = n*i; |
| 185 | for (j = 0; j<ny-1; j += 2) { |
| 186 | b[s00+1] = (b[s00]>>2) & 1; |
| 187 | b[s00 ] = (b[s00]>>3) & 1; |
| 188 | s00 += 2; |
| 189 | } |
| 190 | if(j < ny) { |
| 191 | /* |
| 192 | * both row and column size are odd, do corner element |
| 193 | * s00+1, s10, s10+1 are off edge |
| 194 | */ |
| 195 | b[s00 ] = (b[s00]>>3) & 1; |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding |
| 202 | * each value to 2x2 pixels and inserting into bitplane BIT of B. |
| 203 | * A,B may NOT be same array (it wouldn't make sense to be inserting |
| 204 | * bits into the same array anyway.) |
| 205 | */ |
| 206 | static |
| 207 | void |
| 208 | qtree_bitins(uchar *a, int nx, int ny, Pix *b, int n, int bit) |
| 209 | { |
| 210 | int i, j; |
| 211 | Pix *s00, *s10; |
| 212 | Pix px; |
| 213 | |
| 214 | /* |
| 215 | * expand each 2x2 block |
| 216 | */ |
| 217 | for(i=0; i<nx-1; i+=2) { |
| 218 | s00 = &b[n*i]; /* s00 is index of b[i,j] */ |
| 219 | s10 = s00+n; /* s10 is index of b[i+1,j] */ |
| 220 | for(j=0; j<ny-1; j+=2) { |
| 221 | px = *a++; |
| 222 | s10[1] |= ( px & 1) << bit; |
| 223 | s10[0] |= ((px>>1) & 1) << bit; |
| 224 | s00[1] |= ((px>>2) & 1) << bit; |
| 225 | s00[0] |= ((px>>3) & 1) << bit; |
| 226 | s00 += 2; |
| 227 | s10 += 2; |
| 228 | } |
| 229 | if(j < ny) { |
| 230 | /* |
| 231 | * row size is odd, do last element in row |
| 232 | * s00+1, s10+1 are off edge |
| 233 | */ |
| 234 | px = *a++; |
| 235 | s10[0] |= ((px>>1) & 1) << bit; |
| 236 | s00[0] |= ((px>>3) & 1) << bit; |
| 237 | } |
| 238 | } |
| 239 | if(i < nx) { |
| 240 | /* |
| 241 | * column size is odd, do last row |
| 242 | * s10, s10+1 are off edge |
| 243 | */ |
| 244 | s00 = &b[n*i]; |
| 245 | for(j=0; j<ny-1; j+=2) { |
| 246 | px = *a++; |
| 247 | s00[1] |= ((px>>2) & 1) << bit; |
| 248 | s00[0] |= ((px>>3) & 1) << bit; |
| 249 | s00 += 2; |
| 250 | } |
| 251 | if(j < ny) { |
| 252 | /* |
| 253 | * both row and column size are odd, do corner element |
| 254 | * s00+1, s10, s10+1 are off edge |
| 255 | */ |
| 256 | s00[0] |= ((*a>>3) & 1) << bit; |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | static |
| 262 | void |
| 263 | read_bdirect(Biobuf *infile, Pix *a, int n, int nqx, int nqy, uchar *scratch, int bit) |
| 264 | { |
| 265 | int i; |
| 266 | |
| 267 | /* |
| 268 | * read bit image packed 4 pixels/nybble |
| 269 | */ |
| 270 | for(i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { |
| 271 | scratch[i] = input_nybble(infile); |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | * insert in bitplane BIT of image A |
| 276 | */ |
| 277 | qtree_bitins(scratch, nqx, nqy, a, n, bit); |
| 278 | } |