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