URI:
       tqtree.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tqtree.c (5811B)
       ---
            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 }