source: main/tags/2.80/indexers/mg/src/images/felics.c@ 24539

Last change on this file since 24539 was 3745, checked in by mdewsnip, 21 years ago

Addition of MG package for search and retrieval

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/**************************************************************************
2 *
3 * felics.c -- The main guts of the felics algorithm
4 * Copyright (C) 1994 Neil Sharman and Kerry Guise
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: felics.c 3745 2003-02-20 21:20:24Z mdewsnip $
21 *
22 **************************************************************************/
23
24#include "sysfuncs.h"
25
26#include "bitio_m.h"
27#include "bitio_m_stdio.h"
28
29
30#undef putw
31#define putw(x) { \
32 short z; \
33 byteptr = (unsigned char *)(x); \
34 for (z = 0; z < sizeof(int); z++) \
35 (void) putc((int) byteptr[z], fp_out); \
36}
37#define INTSIZE sizeof(int) * 8
38#define BOOLEAN short
39#define TRUE 1
40#define FALSE 0
41
42#define IN_RANGE 0
43#define OUT_OF_RANGE 1
44#define BELOW_RANGE 0
45#define ABOVE_RANGE 1
46
47
48void
49encode (unsigned int *line, int width, int height, int maxval, int maxk,
50 FILE * fp_in, FILE * fp_out, int (*get) (FILE *))
51{
52 int x, y;
53 unsigned long P, L, H, N1, N2, delta;
54 unsigned long cumul_param[256][INTSIZE];
55 unsigned max_cumul;
56
57 memset (cumul_param, '0', sizeof (cumul_param));
58
59 if (maxk)
60 max_cumul = maxk;
61 else
62 CEILLOG_2 (maxval, max_cumul);
63
64 ENCODE_START (fp_out)
65
66 for (y = 0; y < height; y++)
67 for (x = 0; x < width; x++)
68 {
69 if (y > 0)
70 {
71 if (x > 0)
72 { /* ******** */
73 N1 = line[x]; /* ****1*** */
74 N2 = line[x - 1]; /* ***2P*** */
75 } /* ******** */
76 else
77 { /* |******* */
78 N1 = line[x]; /* |12***** */
79 N2 = line[x + 1]; /* |P***** */
80 } /* |******* */
81 }
82 else
83 {
84 if (x > 1)
85 {
86 N1 = line[x - 1]; /* -------- */
87 N2 = line[x - 2]; /* **12P*** */
88 } /* ******** */
89 else if (x > 0)
90 {
91 N1 = line[x - 1]; /* +------- */
92 N2 = N1; /* |3P***** */
93 } /* |******* */
94 else
95 {
96 line[x] = get (fp_in); /* +------- */
97 BINARY_ENCODE (line[x] + 1, maxval + 1); /* |P****** */
98 continue; /* |******* */
99 }
100 }
101
102
103 H = N1 > N2 ? N1 : N2;
104 L = N1 < N2 ? N1 : N2;
105 delta = H - L;
106
107 line[x] = P = get (fp_in);
108
109 if ((L <= P) && (P <= H))
110 {
111 /* IN-RANGE */
112 unsigned long range, logofrange, thresh, numlong;
113 int nbits;
114
115 ENCODE_BIT (IN_RANGE);
116
117 P -= L;
118
119 range = delta + 1;
120
121 if (range > 1)
122 {
123 /* 2**i <= delta + 1 < 2**(i+1) ; find i ... */
124 CEILLOG_2 (range, logofrange);
125
126 /* number of n-bit values in the range */
127 thresh = (1 << logofrange) - range;
128
129 /* number of n+1-bit values in the range */
130 numlong = range - thresh;
131
132 /* rotate the n-bit codes into the centre */
133 P -= (numlong >> 1);
134 if ((long) P < 0)
135 P += range;
136
137 if (P < thresh)
138 nbits = logofrange - 1;
139 else
140 {
141 nbits = logofrange;
142 P += thresh;
143 }
144 while (--nbits >= 0)
145 ENCODE_BIT ((P >> nbits) & 1);
146 }
147 }
148 else
149 {
150 /* OUT_OF_RANGE */
151 unsigned long diff, parm, i, min;
152
153 ENCODE_BIT (OUT_OF_RANGE);
154
155 if (P < L)
156 {
157 ENCODE_BIT (BELOW_RANGE);
158 diff = L - P - 1;
159 }
160 else
161 {
162 ENCODE_BIT (ABOVE_RANGE);
163 diff = P - H - 1;
164 }
165
166 /* Now code 'diff' as a Golomb-Rice code */
167
168 parm = 0;
169 min = cumul_param[delta][0];
170 for (i = 1; i < max_cumul; i++)
171 if (cumul_param[delta][i] < min)
172 {
173 min = cumul_param[delta][i];
174 parm = i;
175 }
176
177 UNARY_ENCODE ((diff >> parm) + 1);
178 BINARY_ENCODE ((diff & ((1 << parm) - 1)) + 1, 1 << parm);
179
180 for (i = 0; i < max_cumul; i++)
181 cumul_param[delta][i] += (diff >> i) + 1 + i;
182 }
183
184 }
185
186 ENCODE_DONE
187
188}
189
190
191
192
193
194
195void
196decode (unsigned int *line, int width, int height, int maxval, int maxk,
197 FILE * fp_in, FILE * fp_out)
198{
199 int x, y;
200 unsigned int P, L, H, N1, N2, delta;
201 unsigned long cumul_param[256][INTSIZE];
202 unsigned max_cumul;
203
204 memset (cumul_param, '0', sizeof (cumul_param));
205
206 if (maxk)
207 max_cumul = maxk;
208 else
209 CEILLOG_2 (maxval, max_cumul);
210
211 DECODE_START (fp_in);
212
213 for (y = 0; y < height; y++)
214 for (x = 0; x < width; x++)
215 {
216 if (y > 0)
217 {
218 if (x > 0)
219 { /* ******** */
220 N1 = line[x]; /* ****1*** */
221 N2 = line[x - 1]; /* ***2P*** */
222 } /* ******** */
223 else
224 { /* |******* */
225 N1 = line[x]; /* |12***** */
226 N2 = line[x + 1]; /* |P***** */
227 } /* |******* */
228 }
229 else
230 {
231 if (x > 1)
232 {
233 N1 = line[x - 1]; /* -------- */
234 N2 = line[x - 2]; /* **12P*** */
235 } /* ******** */
236 else if (x > 0)
237 {
238 N1 = line[x - 1]; /* +------- */
239 N2 = N1; /* |3P***** */
240 } /* |******* */
241 else
242 {
243 BINARY_DECODE (line[x], maxval + 1);
244 line[x]--;
245 if (maxval < 256)
246 putc (line[x], fp_out); /* +------- */
247 else /* |P****** */
248 fprintf (fp_out, "%u ", line[x]); /* |******* */
249 continue;
250 }
251 }
252
253
254 H = N1 > N2 ? N1 : N2;
255 L = N1 < N2 ? N1 : N2;
256 delta = H - L;
257
258 if (DECODE_BIT == IN_RANGE)
259 {
260 unsigned long i, range, logofrange, thresh, numlong;
261 unsigned xx, l;
262
263 range = delta + 1;
264
265 if (range > 1)
266 {
267 /* 2**i <= delta + 1 < 2**(i+1) ; find i ... */
268 CEILLOG_2 (range, logofrange);
269
270 /* number of n-bit values in the range */
271 thresh = (1 << logofrange) - range;
272 for (P = i = 0; i < logofrange - 1; i++)
273 DECODE_ADD (P);
274 xx = P;
275 l = logofrange - 1;
276 if (P >= thresh)
277 {
278 DECODE_ADD (P);
279 xx = P;
280 l++;
281 P -= thresh;
282 }
283
284 /* number of n+1-bit values in the range */
285 numlong = range - thresh;
286
287 /* rotate the n-bit codes into the centre */
288 P += (numlong >> 1);
289 if ((long) P >= range)
290 P -= range;
291
292 P += L;
293 }
294 else
295 P = L;
296 }
297 else
298 {
299 int out_of_range = DECODE_BIT;
300 unsigned long diff, unary, binary, i, min, parm;
301
302 /* Now code 'diff' as a Golomb-Rice code */
303
304 parm = 0;
305 min = cumul_param[delta][0];
306 for (i = 1; i < max_cumul; i++)
307 if (cumul_param[delta][i] < min)
308 {
309 min = cumul_param[delta][i];
310 parm = i;
311 }
312
313 UNARY_DECODE (unary);
314 diff = (unary - 1) << parm;
315 BINARY_DECODE (binary, 1 << parm);
316 diff |= binary - 1;
317
318 for (i = 0; i < max_cumul; i++)
319 cumul_param[delta][i] += (diff >> i) + 1 + i;
320
321 if (out_of_range == BELOW_RANGE)
322 {
323 P = L - diff - 1;
324 }
325 else
326 {
327 P = diff + H + 1;
328 }
329 }
330
331 line[x] = P;
332
333 if (maxval < 256)
334 (void) putc (P, fp_out);
335 else
336 fprintf (fp_out, "%u ", P);
337 }
338
339 DECODE_DONE
340}
Note: See TracBrowser for help on using the repository browser.