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