major change in the dwt-module, thanks to Ive (aka Reiner Wahler): thanks a lot ...
[openjpeg.git] / libopenjpeg / tgt.c
1 /*
2  * Copyright (c) 2001-2002, David Janssens
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "tgt.h"
28 #include "bio.h"
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 /* <summary> */
33 /* Reset tag-tree. */
34 /* </summary> */
35 void tgt_reset(tgt_tree_t * tree)
36 {
37   int i;
38   /* new */
39   if (!tree || tree == NULL)
40     return;
41
42   for (i = 0; i < tree->numnodes; i++) {
43     tree->nodes[i].value = 999;
44     tree->nodes[i].low = 0;
45     tree->nodes[i].known = 0;
46   }
47 }
48
49 /* <summary> */
50 /* Create tag-tree. */
51 /* </summary> */
52 tgt_tree_t *tgt_create(int numleafsh, int numleafsv)
53 {
54   int nplh[32];
55   int nplv[32];
56   tgt_node_t *node;
57   tgt_node_t *parentnode;
58   tgt_node_t *parentnode0;
59   tgt_tree_t *tree;
60   int i, j, k;
61   int numlvls;
62   int n;
63
64   tree = (tgt_tree_t *) malloc(sizeof(tgt_tree_t));
65   tree->numleafsh = numleafsh;
66   tree->numleafsv = numleafsv;
67
68   numlvls = 0;
69   nplh[0] = numleafsh;
70   nplv[0] = numleafsv;
71   tree->numnodes = 0;
72   do {
73     n = nplh[numlvls] * nplv[numlvls];
74     nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2;
75     nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2;
76     tree->numnodes += n;
77     ++numlvls;
78   } while (n > 1);
79
80   /* ADD */
81   if (tree->numnodes == 0) {
82     free(tree);
83     return NULL;
84   }
85
86   tree->nodes = (tgt_node_t *) malloc(tree->numnodes * sizeof(tgt_node_t));
87
88   node = tree->nodes;
89   parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv];
90   parentnode0 = parentnode;
91
92   for (i = 0; i < numlvls - 1; ++i) {
93     for (j = 0; j < nplv[i]; ++j) {
94       k = nplh[i];
95       while (--k >= 0) {
96         node->parent = parentnode;
97         ++node;
98         if (--k >= 0) {
99           node->parent = parentnode;
100           ++node;
101         }
102         ++parentnode;
103       }
104       if ((j & 1) || j == nplv[i] - 1) {
105         parentnode0 = parentnode;
106       } else {
107         parentnode = parentnode0;
108         parentnode0 += nplh[i];
109       }
110     }
111   }
112   node->parent = 0;
113
114   tgt_reset(tree);
115
116   return tree;
117 }
118
119 /* <summary> */
120 /* Destroy tag-tree. */
121 /* </summary> */
122 void tgt_destroy(tgt_tree_t * t)
123 {
124   free(t->nodes);
125   free(t);
126 }
127
128 /* <summary> */
129 /* Set the value of a leaf of the tag-tree. */
130 /* </summary> */
131 void tgt_setvalue(tgt_tree_t * tree, int leafno, int value)
132 {
133   tgt_node_t *node;
134   node = &tree->nodes[leafno];
135   while (node && node->value > value) {
136     node->value = value;
137     node = node->parent;
138   }
139 }
140
141 /* <summary> */
142 /* Encode the value of a leaf of the tag-tree. */
143 /* </summary> */
144 void tgt_encode(tgt_tree_t * tree, int leafno, int threshold)
145 {
146   tgt_node_t *stk[31];
147   tgt_node_t **stkptr;
148   tgt_node_t *node;
149   int low;
150
151   stkptr = stk;
152   node = &tree->nodes[leafno];
153   while (node->parent) {
154     *stkptr++ = node;
155     node = node->parent;
156   }
157
158   low = 0;
159   for (;;) {
160     if (low > node->low) {
161       node->low = low;
162     } else {
163       low = node->low;
164     }
165
166     while (low < threshold) {
167       if (low >= node->value) {
168         if (!node->known) {
169           bio_write(1, 1);
170           node->known = 1;
171         }
172         break;
173       }
174       bio_write(0, 1);
175       ++low;
176     }
177
178     node->low = low;
179     if (stkptr == stk)
180       break;
181     node = *--stkptr;
182   }
183
184 }
185
186 /* <summary> */
187 /* Decode the value of a leaf of the tag-tree. */
188 /* </summary> */
189 int tgt_decode(tgt_tree_t * tree, int leafno, int threshold)
190 {
191   tgt_node_t *stk[31];
192   tgt_node_t **stkptr;
193   tgt_node_t *node;
194   int low;
195
196   stkptr = stk;
197   node = &tree->nodes[leafno];
198   while (node->parent) {
199     *stkptr++ = node;
200     node = node->parent;
201   }
202
203   low = 0;
204   for (;;) {
205     if (low > node->low) {
206       node->low = low;
207     } else {
208       low = node->low;
209     }
210     while (low < threshold && low < node->value) {
211       if (bio_read(1)) {
212         node->value = low;
213       } else {
214         ++low;
215       }
216     }
217     node->low = low;
218     if (stkptr == stk) {
219       break;
220     }
221     node = *--stkptr;
222   }
223
224   return (node->value < threshold) ? 1 : 0;
225 }