1 /*
2  * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3  * Copyright (c) 2002-2007, Professor Benoit Macq
4  * Copyright (c) 2001-2003, David Janssens
5  * Copyright (c) 2002-2003, Yannick Verschueren
6  * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
7  * Copyright (c) 2005, Herve Drolon, FreeImage Team
8  * Copyright (c) 2008;2011-2012, Centre National d'Etudes Spatiales (CNES), France
9  * Copyright (c) 2012, CS Systemes d'Information, France
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "opj_includes.h"
35 
36 /*
37 ==========================================================
38    Tag-tree coder interface
39 ==========================================================
40 */
41 
opj_tgt_create(OPJ_UINT32 numleafsh,OPJ_UINT32 numleafsv)42 opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv) {
43         OPJ_INT32 nplh[32];
44         OPJ_INT32 nplv[32];
45         opj_tgt_node_t *node = 00;
46         opj_tgt_node_t *l_parent_node = 00;
47         opj_tgt_node_t *l_parent_node0 = 00;
48         opj_tgt_tree_t *tree = 00;
49         OPJ_UINT32 i;
50         OPJ_INT32  j,k;
51         OPJ_UINT32 numlvls;
52         OPJ_UINT32 n;
53 
54         tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t));
55         if(!tree) {
56                 fprintf(stderr, "ERROR in tgt_create while allocating tree\n");
57                 return 00;
58         }
59         memset(tree,0,sizeof(opj_tgt_tree_t));
60 
61         tree->numleafsh = numleafsh;
62         tree->numleafsv = numleafsv;
63 
64         numlvls = 0;
65         nplh[0] = (OPJ_INT32)numleafsh;
66         nplv[0] = (OPJ_INT32)numleafsv;
67         tree->numnodes = 0;
68         do {
69                 n = (OPJ_UINT32)(nplh[numlvls] * nplv[numlvls]);
70                 nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2;
71                 nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2;
72                 tree->numnodes += n;
73                 ++numlvls;
74         } while (n > 1);
75 
76         /* ADD */
77         if (tree->numnodes == 0) {
78                 opj_free(tree);
79                 fprintf(stderr, "WARNING in tgt_create tree->numnodes == 0, no tree created.\n");
80                 return 00;
81         }
82 
83         tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t));
84         if(!tree->nodes) {
85                 fprintf(stderr, "ERROR in tgt_create while allocating node of the tree\n");
86                 opj_free(tree);
87                 return 00;
88         }
89         memset(tree->nodes,0,tree->numnodes * sizeof(opj_tgt_node_t));
90         tree->nodes_size = tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t);
91 
92         node = tree->nodes;
93         l_parent_node = &tree->nodes[tree->numleafsh * tree->numleafsv];
94         l_parent_node0 = l_parent_node;
95 
96         for (i = 0; i < numlvls - 1; ++i) {
97                 for (j = 0; j < nplv[i]; ++j) {
98                         k = nplh[i];
99                         while (--k >= 0) {
100                                 node->parent = l_parent_node;
101                                 ++node;
102                                 if (--k >= 0) {
103                                         node->parent = l_parent_node;
104                                         ++node;
105                                 }
106                                 ++l_parent_node;
107                         }
108                         if ((j & 1) || j == nplv[i] - 1) {
109                                 l_parent_node0 = l_parent_node;
110                         } else {
111                                 l_parent_node = l_parent_node0;
112                                 l_parent_node0 += nplh[i];
113                         }
114                 }
115         }
116         node->parent = 0;
117         opj_tgt_reset(tree);
118         return tree;
119 }
120 
121 /**
122  * Reinitialises a tag-tree from an existing one.
123  *
124  * @param       p_tree                          the tree to reinitialize.
125  * @param       p_num_leafs_h           the width of the array of leafs of the tree
126  * @param       p_num_leafs_v           the height of the array of leafs of the tree
127  * @return      a new tag-tree if successful, NULL otherwise
128 */
opj_tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h,OPJ_UINT32 p_num_leafs_v)129 opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v)
130 {
131         OPJ_INT32 l_nplh[32];
132         OPJ_INT32 l_nplv[32];
133         opj_tgt_node_t *l_node = 00;
134         opj_tgt_node_t *l_parent_node = 00;
135         opj_tgt_node_t *l_parent_node0 = 00;
136         OPJ_UINT32 i;
137         OPJ_INT32 j,k;
138         OPJ_UINT32 l_num_levels;
139         OPJ_UINT32 n;
140         OPJ_UINT32 l_node_size;
141 
142         if (! p_tree){
143                 return 00;
144         }
145 
146         if ((p_tree->numleafsh != p_num_leafs_h) || (p_tree->numleafsv != p_num_leafs_v)) {
147                 p_tree->numleafsh = p_num_leafs_h;
148                 p_tree->numleafsv = p_num_leafs_v;
149 
150                 l_num_levels = 0;
151                 l_nplh[0] = (OPJ_INT32)p_num_leafs_h;
152                 l_nplv[0] = (OPJ_INT32)p_num_leafs_v;
153                 p_tree->numnodes = 0;
154                 do
155                 {
156                         n = (OPJ_UINT32)(l_nplh[l_num_levels] * l_nplv[l_num_levels]);
157                         l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2;
158                         l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2;
159                         p_tree->numnodes += n;
160                         ++l_num_levels;
161                 }
162                 while (n > 1);
163 
164                 /* ADD */
165                 if (p_tree->numnodes == 0) {
166                         opj_tgt_destroy(p_tree);
167                         return 00;
168                 }
169                 l_node_size = p_tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t);
170 
171                 if (l_node_size > p_tree->nodes_size) {
172                         opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size);
173                         if (! new_nodes) {
174                                 fprintf(stderr, "ERROR Not enough memory to reinitialize the tag tree\n");
175                                 opj_tgt_destroy(p_tree);
176                                 return 00;
177                         }
178                         p_tree->nodes = new_nodes;
179                         memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0 , l_node_size - p_tree->nodes_size);
180                         p_tree->nodes_size = l_node_size;
181                 }
182                 l_node = p_tree->nodes;
183                 l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv];
184                 l_parent_node0 = l_parent_node;
185 
186                 for (i = 0; i < l_num_levels - 1; ++i) {
187                         for (j = 0; j < l_nplv[i]; ++j) {
188                                 k = l_nplh[i];
189                                 while (--k >= 0) {
190                                         l_node->parent = l_parent_node;
191                                         ++l_node;
192                                         if (--k >= 0) {
193                                                 l_node->parent = l_parent_node;
194                                                 ++l_node;
195                                         }
196                                         ++l_parent_node;
197                                         }
198                                 if ((j & 1) || j == l_nplv[i] - 1)
199                                 {
200                                         l_parent_node0 = l_parent_node;
201                                 }
202                                 else
203                                 {
204                                         l_parent_node = l_parent_node0;
205                                         l_parent_node0 += l_nplh[i];
206                                 }
207                         }
208                 }
209                 l_node->parent = 0;
210         }
211         opj_tgt_reset(p_tree);
212 
213         return p_tree;
214 }
215 
opj_tgt_destroy(opj_tgt_tree_t * p_tree)216 void opj_tgt_destroy(opj_tgt_tree_t *p_tree)
217 {
218         if (! p_tree) {
219                 return;
220         }
221 
222         if (p_tree->nodes) {
223                 opj_free(p_tree->nodes);
224                 p_tree->nodes = 00;
225         }
226         opj_free(p_tree);
227 }
228 
opj_tgt_reset(opj_tgt_tree_t * p_tree)229 void opj_tgt_reset(opj_tgt_tree_t *p_tree) {
230         OPJ_UINT32 i;
231         opj_tgt_node_t * l_current_node = 00;;
232 
233         if (! p_tree) {
234                 return;
235         }
236 
237         l_current_node = p_tree->nodes;
238         for     (i = 0; i < p_tree->numnodes; ++i)
239         {
240                 l_current_node->value = 999;
241                 l_current_node->low = 0;
242                 l_current_node->known = 0;
243                 ++l_current_node;
244         }
245 }
246 
opj_tgt_setvalue(opj_tgt_tree_t * tree,OPJ_UINT32 leafno,OPJ_INT32 value)247 void opj_tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value) {
248         opj_tgt_node_t *node;
249         node = &tree->nodes[leafno];
250         while (node && node->value > value) {
251                 node->value = value;
252                 node = node->parent;
253         }
254 }
255 
opj_tgt_encode(opj_bio_t * bio,opj_tgt_tree_t * tree,OPJ_UINT32 leafno,OPJ_INT32 threshold)256 void opj_tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) {
257         opj_tgt_node_t *stk[31];
258         opj_tgt_node_t **stkptr;
259         opj_tgt_node_t *node;
260         OPJ_INT32 low;
261 
262         stkptr = stk;
263         node = &tree->nodes[leafno];
264         while (node->parent) {
265                 *stkptr++ = node;
266                 node = node->parent;
267         }
268 
269         low = 0;
270         for (;;) {
271                 if (low > node->low) {
272                         node->low = low;
273                 } else {
274                         low = node->low;
275                 }
276 
277                 while (low < threshold) {
278                         if (low >= node->value) {
279                                 if (!node->known) {
280                                         opj_bio_write(bio, 1, 1);
281                                         node->known = 1;
282                                 }
283                                 break;
284                         }
285                         opj_bio_write(bio, 0, 1);
286                         ++low;
287                 }
288 
289                 node->low = low;
290                 if (stkptr == stk)
291                         break;
292                 node = *--stkptr;
293         }
294 }
295 
opj_tgt_decode(opj_bio_t * bio,opj_tgt_tree_t * tree,OPJ_UINT32 leafno,OPJ_INT32 threshold)296 OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) {
297         opj_tgt_node_t *stk[31];
298         opj_tgt_node_t **stkptr;
299         opj_tgt_node_t *node;
300         OPJ_INT32 low;
301 
302         stkptr = stk;
303         node = &tree->nodes[leafno];
304         while (node->parent) {
305                 *stkptr++ = node;
306                 node = node->parent;
307         }
308 
309         low = 0;
310         for (;;) {
311                 if (low > node->low) {
312                         node->low = low;
313                 } else {
314                         low = node->low;
315                 }
316                 while (low < threshold && low < node->value) {
317                         if (opj_bio_read(bio, 1)) {
318                                 node->value = low;
319                         } else {
320                                 ++low;
321                         }
322                 }
323                 node->low = low;
324                 if (stkptr == stk) {
325                         break;
326                 }
327                 node = *--stkptr;
328         }
329 
330         return (node->value < threshold) ? 1 : 0;
331 }
332