Line data Source code
1 : /* libblx - Magellan BLX topo reader/writer library
2 : *
3 : * Copyright (c) 2008, Henrik Johansson <henrik@johome.net>
4 : * Copyright (c) 2008-2009, Even Rouault <even dot rouault at spatialys.com>
5 : *
6 : * SPDX-License-Identifier: MIT
7 : */
8 :
9 : #include "blx.h"
10 : #include <stdio.h>
11 : #include <string.h>
12 : #include <stdlib.h>
13 :
14 : #include "cpl_port.h"
15 :
16 : /* Constants */
17 : #define MAXLEVELS 5
18 : #define MAXCOMPONENTS 4
19 :
20 : static const int table1[] = {
21 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25 : 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
26 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
27 : 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
28 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
29 : 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
30 : 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
31 : 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
32 : 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
33 : 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10,
34 : 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14,
35 : 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 21, 22, 23, 24,
36 : 25, 26, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 255, 255, 255,
37 : 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
38 : 255};
39 :
40 : /* { byte, n of bits when compressed, bit pattern << (13-n of bits) } */
41 : static const int table2[][3] = {
42 : {0, 2, 0}, {255, 3, 2048}, {1, 3, 3072}, {2, 4, 4096},
43 : {3, 4, 4608}, {254, 5, 5120}, {4, 5, 5376}, {5, 5, 5632},
44 : {253, 6, 5888}, {6, 6, 6016}, {252, 6, 6144}, {7, 6, 6272},
45 : {251, 6, 6400}, {8, 6, 6528}, {9, 7, 6656}, {250, 7, 6720},
46 : {10, 7, 6784}, {249, 7, 6848}, {11, 7, 6912}, {248, 7, 6976},
47 : {12, 8, 7040}, {247, 8, 7072}, {16, 8, 7104}, {246, 8, 7136},
48 : {13, 8, 7168}, {245, 8, 7200}, {14, 8, 7232}, {244, 8, 7264},
49 : {15, 8, 7296}, {243, 8, 7328}, {242, 8, 7360}, {241, 8, 7392},
50 : {17, 9, 7424}, {18, 9, 7440}, {240, 9, 7456}, {239, 9, 7472},
51 : {19, 9, 7488}, {238, 9, 7504}, {20, 9, 7520}, {237, 9, 7536},
52 : {21, 9, 7552}, {236, 9, 7568}, {22, 9, 7584}, {235, 9, 7600},
53 : {234, 9, 7616}, {23, 9, 7632}, {233, 9, 7648}, {24, 10, 7664},
54 : {232, 10, 7672}, {231, 10, 7680}, {25, 10, 7688}, {230, 10, 7696},
55 : {229, 10, 7704}, {26, 10, 7712}, {228, 10, 7720}, {27, 10, 7728},
56 : {227, 10, 7736}, {225, 10, 7744}, {226, 10, 7752}, {28, 10, 7760},
57 : {29, 10, 7768}, {224, 10, 7776}, {30, 10, 7784}, {31, 10, 7792},
58 : {223, 10, 7800}, {32, 10, 7808}, {222, 10, 7816}, {33, 10, 7824},
59 : {221, 11, 7832}, {220, 11, 7836}, {34, 11, 7840}, {219, 11, 7844},
60 : {35, 11, 7848}, {218, 11, 7852}, {256, 11, 7856}, {36, 11, 7860},
61 : {217, 11, 7864}, {216, 11, 7868}, {37, 11, 7872}, {215, 11, 7876},
62 : {38, 11, 7880}, {214, 11, 7884}, {193, 11, 7888}, {213, 11, 7892},
63 : {39, 11, 7896}, {128, 11, 7900}, {212, 11, 7904}, {40, 11, 7908},
64 : {194, 11, 7912}, {211, 11, 7916}, {210, 11, 7920}, {41, 11, 7924},
65 : {209, 11, 7928}, {208, 11, 7932}, {42, 11, 7936}, {207, 11, 7940},
66 : {43, 11, 7944}, {195, 11, 7948}, {206, 11, 7952}, {205, 11, 7956},
67 : {204, 11, 7960}, {44, 11, 7964}, {203, 11, 7968}, {192, 11, 7972},
68 : {196, 11, 7976}, {45, 11, 7980}, {201, 11, 7984}, {200, 11, 7988},
69 : {197, 11, 7992}, {202, 11, 7996}, {127, 11, 8000}, {199, 11, 8004},
70 : {198, 11, 8008}, {46, 12, 8012}, {47, 12, 8014}, {48, 12, 8016},
71 : {49, 12, 8018}, {50, 12, 8020}, {51, 12, 8022}, {191, 12, 8024},
72 : {52, 12, 8026}, {183, 12, 8028}, {53, 12, 8030}, {54, 12, 8032},
73 : {55, 12, 8034}, {190, 12, 8036}, {56, 12, 8038}, {57, 12, 8040},
74 : {189, 12, 8042}, {58, 12, 8044}, {176, 12, 8046}, {59, 12, 8048},
75 : {126, 12, 8050}, {60, 12, 8052}, {188, 12, 8054}, {61, 12, 8056},
76 : {63, 12, 8058}, {62, 12, 8060}, {64, 12, 8062}, {129, 12, 8064},
77 : {187, 12, 8066}, {186, 12, 8068}, {65, 12, 8070}, {66, 12, 8072},
78 : {185, 12, 8074}, {184, 12, 8076}, {68, 12, 8078}, {174, 12, 8080},
79 : {67, 12, 8082}, {182, 13, 8084}, {69, 13, 8085}, {180, 13, 8086},
80 : {181, 13, 8087}, {71, 13, 8088}, {70, 13, 8089}, {179, 13, 8090},
81 : {125, 13, 8091}, {72, 13, 8092}, {130, 13, 8093}, {178, 13, 8094},
82 : {177, 13, 8095}, {73, 13, 8096}, {74, 13, 8097}, {124, 13, 8098},
83 : {76, 13, 8099}, {175, 13, 8100}, {75, 13, 8101}, {131, 13, 8102},
84 : {132, 13, 8103}, {79, 13, 8104}, {77, 13, 8105}, {123, 13, 8106},
85 : {80, 13, 8107}, {172, 13, 8108}, {171, 13, 8109}, {78, 13, 8110},
86 : {173, 13, 8111}, {81, 13, 8112}, {169, 13, 8113}, {122, 13, 8114},
87 : {82, 13, 8115}, {133, 13, 8116}, {168, 13, 8117}, {84, 13, 8118},
88 : {164, 13, 8119}, {167, 13, 8120}, {85, 13, 8121}, {170, 13, 8122},
89 : {166, 13, 8123}, {165, 13, 8124}, {121, 13, 8125}, {160, 13, 8126},
90 : {134, 13, 8127}, {136, 13, 8128}, {161, 13, 8129}, {120, 13, 8130},
91 : {88, 13, 8131}, {83, 13, 8132}, {119, 13, 8133}, {163, 13, 8134},
92 : {162, 13, 8135}, {159, 13, 8136}, {91, 13, 8137}, {135, 13, 8138},
93 : {90, 13, 8139}, {86, 13, 8140}, {137, 13, 8141}, {87, 13, 8142},
94 : {89, 13, 8143}, {158, 13, 8144}, {152, 13, 8145}, {138, 13, 8146},
95 : {139, 13, 8147}, {116, 13, 8148}, {140, 13, 8149}, {92, 13, 8150},
96 : {96, 13, 8151}, {157, 13, 8152}, {153, 13, 8153}, {97, 13, 8154},
97 : {94, 13, 8155}, {93, 13, 8156}, {117, 13, 8157}, {156, 13, 8158},
98 : {155, 13, 8159}, {95, 13, 8160}, {118, 13, 8161}, {143, 13, 8162},
99 : {151, 13, 8163}, {142, 13, 8164}, {104, 13, 8165}, {100, 13, 8166},
100 : {148, 13, 8167}, {144, 13, 8168}, {154, 13, 8169}, {115, 13, 8170},
101 : {113, 13, 8171}, {98, 13, 8172}, {146, 13, 8173}, {112, 13, 8174},
102 : {145, 13, 8175}, {149, 13, 8176}, {141, 13, 8177}, {150, 13, 8178},
103 : {103, 13, 8179}, {147, 13, 8180}, {99, 13, 8181}, {108, 13, 8182},
104 : {101, 13, 8183}, {114, 13, 8184}, {105, 13, 8185}, {102, 13, 8186},
105 : {107, 13, 8187}, {109, 13, 8188}, {110, 13, 8189}, {111, 13, 8190},
106 : {106, 13, 8191}, {0, 0, 8192}};
107 :
108 : static const int table3[] = {0x20, 0x2f, 0x44, 0x71, 0x95, 0x101};
109 :
110 32 : STATIC int compress_chunk(unsigned char *inbuf, int inlen,
111 : unsigned char *outbuf, int outbuflen)
112 : {
113 32 : int next, m = 0, j, outlen = 0;
114 32 : unsigned reg = 0;
115 :
116 32 : next = *inbuf++;
117 32 : inlen--;
118 541230 : while (next >= 0)
119 : {
120 : /* Find index of input byte in table2 and put it in j */
121 541198 : j = 0;
122 7158480 : while (next != table2[j][0])
123 6617280 : j++;
124 :
125 541198 : if (inlen)
126 : {
127 541134 : next = *inbuf++;
128 541134 : inlen--;
129 : }
130 : else
131 : {
132 64 : if (next == 0x100)
133 32 : next = -1;
134 : else
135 32 : next = 0x100;
136 : }
137 541198 : reg = (reg << table2[j][1]) | (table2[j][2] >> (13 - table2[j][1]));
138 541198 : m += table2[j][1];
139 :
140 893230 : while (m >= 8)
141 : {
142 352032 : if (outlen >= outbuflen)
143 0 : return -1;
144 352032 : *outbuf++ = (unsigned char)((reg >> (m - 8)) & 0xff);
145 352032 : outlen++;
146 352032 : m -= 8;
147 : }
148 : }
149 32 : if (outlen >= outbuflen)
150 0 : return -1;
151 32 : *outbuf++ = (unsigned char)((reg << (8 - m)) & 0xff);
152 :
153 32 : return outlen + 1;
154 : }
155 :
156 192 : STATIC int uncompress_chunk(unsigned char *inbuf, int inlen,
157 : unsigned char *outbuf, int outbuflen)
158 : {
159 192 : int i, j, k, m = 0, outlen = 0;
160 : unsigned reg, newdata;
161 :
162 192 : if (inlen < 4)
163 0 : return -1;
164 :
165 192 : reg = *(inbuf + 3) | (*(inbuf + 2) << 8) | (*(inbuf + 1) << 16) |
166 192 : ((unsigned)*(inbuf + 0) << 24);
167 192 : inbuf += 4;
168 192 : inlen -= 4;
169 :
170 192 : newdata = (reg >> 19) & 0x1fff;
171 :
172 : while (1)
173 : {
174 2579890 : j = newdata >> 5;
175 :
176 2579890 : if (table1[j] == 0xff)
177 : {
178 114604 : i = 1;
179 203816 : while ((int)newdata >= table2[table3[i]][2])
180 89212 : i++;
181 :
182 114604 : j = table3[i - 1];
183 :
184 114604 : k = j + ((newdata - table2[j][2]) >> (13 - table2[j][1]));
185 :
186 114604 : if (table2[k][0] == 0x100)
187 192 : break;
188 : else
189 : {
190 114412 : if (outlen >= outbuflen)
191 0 : return -1;
192 114412 : *outbuf++ = (unsigned char)table2[k][0];
193 114412 : outlen++;
194 : }
195 : }
196 : else
197 : {
198 2465290 : j = table1[j];
199 2465290 : if (outlen >= outbuflen)
200 0 : return -1;
201 2465290 : *outbuf++ = (unsigned char)table2[j][0];
202 2465290 : outlen++;
203 : }
204 :
205 2579700 : m += table2[j][1];
206 :
207 2579700 : if (m >= 19)
208 : {
209 616582 : if (m >= 8)
210 : {
211 1929530 : for (i = m >> 3; i; i--)
212 : {
213 1312940 : if (inlen)
214 : {
215 1312750 : reg = (reg << 8) | *inbuf++;
216 1312750 : inlen--;
217 : }
218 : else
219 192 : reg = reg << 8;
220 : }
221 : }
222 616582 : m = m & 7;
223 : }
224 2579700 : newdata = (reg >> (19 - m)) & 0x1fff;
225 : }
226 192 : return outlen;
227 : }
228 :
229 : /*
230 : Reconstruct a new detail level with double resolution in the horizontal
231 : direction from data from the previous detail level and plus new differential
232 : data.
233 : */
234 1600 : STATIC blxdata *reconstruct_horiz(blxdata *base, blxdata *diff, unsigned rows,
235 : unsigned cols, blxdata *out)
236 : {
237 : unsigned int i, j;
238 : blxdata tmp;
239 :
240 : /* Last column */
241 36672 : for (i = 0; i < rows; i++)
242 35072 : out[2 * (cols * i + cols - 1)] =
243 35072 : diff[cols * i + cols - 1] +
244 35072 : (((short)(base[cols * i + cols - 2] - base[cols * i + cols - 1] -
245 : 1)) >>
246 : 2);
247 :
248 : /* Intermediate columns */
249 36672 : for (i = 0; i < rows; i++)
250 1419010 : for (j = cols - 2; j > 0; j--)
251 1383940 : out[2 * (cols * i + j)] =
252 1383940 : diff[cols * i + j] +
253 1383940 : (((short)(base[cols * i + j] +
254 1383940 : 2 * (base[cols * i + j - 1] -
255 1383940 : out[2 * (cols * i + j + 1)]) -
256 1383940 : 3 * base[cols * i + j + 1] + 1)) >>
257 : 3);
258 :
259 : /* First column */
260 36672 : for (i = 0; i < rows; i++)
261 35072 : out[2 * cols * i] =
262 35072 : diff[cols * i] +
263 35072 : (((short)(base[cols * i] - base[cols * i + 1] + 1)) >> 2);
264 :
265 36672 : for (i = 0; i < rows; i++)
266 1489150 : for (j = 0; j < cols; j++)
267 : {
268 1454080 : tmp = base[cols * i + j] +
269 1454080 : (((short)(out[2 * (cols * i + j)] + 1)) >> 1);
270 1454080 : out[2 * cols * i + 2 * j + 1] = tmp - out[2 * (cols * i + j)];
271 1454080 : out[2 * cols * i + 2 * j] = tmp;
272 : }
273 :
274 1600 : return out;
275 : }
276 :
277 : /*
278 : Reconstruct a new detail level with double resolution in the vertical
279 : direction from data from the previous detail level and plus new differential
280 : data.
281 : */
282 800 : STATIC blxdata *reconstruct_vert(blxdata *base, blxdata *diff, unsigned rows,
283 : unsigned cols, blxdata *out)
284 : {
285 : unsigned int i, j;
286 : blxdata tmp;
287 :
288 : /* Last row */
289 35872 : for (i = 0; i < cols; i++)
290 35072 : out[2 * cols * (rows - 1) + i] =
291 35072 : diff[cols * (rows - 1) + i] +
292 35072 : (((short)(base[cols * (rows - 2) + i] -
293 35072 : base[cols * (rows - 1) + i] - 1)) >>
294 : 2);
295 :
296 : /* Intermediate rows */
297 35872 : for (i = 0; i < cols; i++)
298 1419010 : for (j = rows - 2; j > 0; j--)
299 1383940 : out[2 * cols * j + i] =
300 1383940 : diff[cols * j + i] +
301 1383940 : ((short)((base[cols * j + i] +
302 1383940 : 2 * (base[cols * (j - 1) + i] -
303 1383940 : out[2 * cols * (j + 1) + i]) -
304 1383940 : 3 * base[cols * (j + 1) + i] + 1)) >>
305 : 3);
306 :
307 : /* First row */
308 35872 : for (i = 0; i < cols; i++)
309 35072 : out[i] = diff[i] + (((short)(base[i] - base[i + cols] + 1)) >> 2);
310 :
311 35872 : for (i = 0; i < cols; i++)
312 1489150 : for (j = 0; j < rows; j++)
313 : {
314 1454080 : tmp = base[cols * j + i] +
315 1454080 : (((short)(out[2 * cols * j + i] + 1)) >> 1);
316 1454080 : out[cols * (2 * j + 1) + i] = tmp - out[2 * cols * j + i];
317 1454080 : out[cols * 2 * j + i] = tmp;
318 : }
319 800 : return out;
320 : }
321 :
322 : /*
323 : Inverse of reconstruct_horiz
324 : */
325 320 : STATIC void decimate_horiz(blxdata *in, unsigned int rows, unsigned int cols,
326 : blxdata *base, blxdata *diff)
327 : {
328 : unsigned int i, j;
329 : blxdata tmp;
330 :
331 8256 : for (i = 0; i < rows; i++)
332 : {
333 357120 : for (j = 0; j < cols; j += 2)
334 : {
335 349184 : tmp = in[i * cols + j] - in[i * cols + j + 1];
336 349184 : diff[i * cols / 2 + j / 2] = tmp;
337 349184 : base[i * cols / 2 + j / 2] =
338 349184 : in[i * cols + j] - (((short)(tmp + 1)) >> 1);
339 : }
340 : }
341 :
342 : /* First column */
343 8256 : for (i = 0; i < rows; i++)
344 : {
345 7936 : diff[cols / 2 * i] -=
346 7936 : ((short)(base[i * cols / 2] - base[i * cols / 2 + 1] + 1)) >> 2;
347 : }
348 :
349 : /* Intermediate columns */
350 8256 : for (i = 0; i < rows; i++)
351 341248 : for (j = 1; j < cols / 2 - 1; j++)
352 333312 : diff[cols / 2 * i + j] -=
353 333312 : ((short)(base[cols / 2 * i + j] +
354 333312 : 2 * (base[cols / 2 * i + j - 1] -
355 333312 : diff[cols / 2 * i + j + 1]) -
356 333312 : 3 * base[cols / 2 * i + j + 1] + 1)) >>
357 : 3;
358 :
359 : /* Last column */
360 8256 : for (i = 0; i < rows; i++)
361 7936 : diff[cols / 2 * i + cols / 2 - 1] -=
362 7936 : ((short)(base[i * cols / 2 + cols / 2 - 2] -
363 7936 : base[i * cols / 2 + cols / 2 - 1] - 1)) >>
364 : 2;
365 320 : }
366 :
367 : /*
368 : Inverse of reconstruct_vert
369 : */
370 160 : STATIC void decimate_vert(blxdata *in, unsigned int rows, unsigned int cols,
371 : blxdata *base, blxdata *diff)
372 : {
373 : unsigned int i, j;
374 : blxdata tmp;
375 :
376 4128 : for (i = 0; i < rows; i += 2)
377 353152 : for (j = 0; j < cols; j++)
378 : {
379 349184 : tmp = in[i * cols + j] - in[(i + 1) * cols + j];
380 349184 : diff[i / 2 * cols + j] = tmp;
381 349184 : base[i / 2 * cols + j] =
382 349184 : in[i * cols + j] - (((short)(tmp + 1)) >> 1);
383 : }
384 :
385 : /* First row */
386 8096 : for (j = 0; j < cols; j++)
387 7936 : diff[j] -= ((short)(base[j] - base[cols + j] + 1)) >> 2;
388 :
389 : /* Intermediate rows */
390 3808 : for (i = 1; i < rows / 2 - 1; i++)
391 336960 : for (j = 0; j < cols; j++)
392 333312 : diff[cols * i + j] -= ((short)(base[cols * i + j] +
393 333312 : 2 * (base[cols * (i - 1) + j] -
394 333312 : diff[cols * (i + 1) + j]) -
395 333312 : 3 * base[cols * (i + 1) + j] + 1)) >>
396 : 3;
397 :
398 : /* Last row */
399 8096 : for (j = 0; j < cols; j++)
400 7936 : diff[cols * (rows / 2 - 1) + j] -=
401 7936 : ((short)(base[cols * (rows / 2 - 2) + j] -
402 7936 : base[cols * (rows / 2 - 1) + j] - 1)) >>
403 : 2;
404 160 : }
405 :
406 : typedef union
407 : {
408 : short s;
409 : unsigned short u;
410 : } unionshort;
411 :
412 57615 : static int get_short_le(const unsigned char **data)
413 : {
414 : /* We assume two's complement representation for this to work */
415 57615 : unionshort result = {0};
416 57615 : result.u = (unsigned short)(*(*data) | (*(*data + 1) << 8));
417 57615 : *data += 2;
418 57615 : return result.s;
419 : }
420 :
421 9270 : static int get_short_be(const unsigned char **data)
422 : {
423 : /* We assume two's complement representation for this to work */
424 9270 : unionshort result = {0};
425 9270 : result.u = (unsigned short)(*(*data + 1) | (*(*data) << 8));
426 9270 : *data += 2;
427 9270 : return result.s;
428 : }
429 :
430 17644 : static void put_short_le(short data, unsigned char **bufptr)
431 : {
432 : /* We assume two's complement representation for this to work */
433 17644 : unionshort us = {0};
434 17644 : us.s = data;
435 17644 : *(*bufptr)++ = (unsigned char)(us.u & 0xff);
436 17644 : *(*bufptr)++ = (unsigned char)((us.u >> 8) & 0xff);
437 17644 : }
438 :
439 3602 : static void put_short_be(short data, unsigned char **bufptr)
440 : {
441 : /* We assume two's complement representation for this to work */
442 3602 : unionshort us = {0};
443 3602 : us.s = data;
444 3602 : *(*bufptr)++ = (unsigned char)((us.u >> 8) & 0xff);
445 3602 : *(*bufptr)++ = (unsigned char)(us.u & 0xff);
446 3602 : }
447 :
448 224 : static int get_unsigned_short_le(const unsigned char **data)
449 : {
450 : int result;
451 :
452 224 : result = *(*data) | (*(*data + 1) << 8);
453 224 : *data += 2;
454 224 : return result;
455 : }
456 :
457 192 : static int get_unsigned_short_be(const unsigned char **data)
458 : {
459 : int result;
460 :
461 192 : result = *(*data + 1) | (*(*data) << 8);
462 192 : *data += 2;
463 192 : return result;
464 : }
465 :
466 64 : static void put_unsigned_short_le(unsigned short data, unsigned char **bufptr)
467 : {
468 64 : *(*bufptr)++ = (unsigned char)(data & 0xff);
469 64 : *(*bufptr)++ = (unsigned char)((data >> 8) & 0xff);
470 64 : }
471 :
472 64 : static void put_unsigned_short_be(unsigned short data, unsigned char **bufptr)
473 : {
474 64 : *(*bufptr)++ = (unsigned char)((data >> 8) & 0xff);
475 64 : *(*bufptr)++ = (unsigned char)(data & 0xff);
476 64 : }
477 :
478 22619 : static int get_short(blxcontext_t *ctx, const unsigned char **data)
479 : {
480 :
481 22619 : if (ctx->endian == LITTLEENDIAN)
482 13361 : return get_short_le(data);
483 : else
484 9258 : return get_short_be(data);
485 : }
486 :
487 416 : static int get_unsigned_short(blxcontext_t *ctx, const unsigned char **data)
488 : {
489 :
490 416 : if (ctx->endian == LITTLEENDIAN)
491 224 : return get_unsigned_short_le(data);
492 : else
493 192 : return get_unsigned_short_be(data);
494 : }
495 :
496 7204 : static void put_short(blxcontext_t *ctx, short data, unsigned char **bufptr)
497 : {
498 7204 : if (ctx->endian == LITTLEENDIAN)
499 3602 : put_short_le(data, bufptr);
500 : else
501 3602 : put_short_be(data, bufptr);
502 7204 : }
503 :
504 128 : static void put_unsigned_short(blxcontext_t *ctx, unsigned short data,
505 : unsigned char **bufptr)
506 : {
507 128 : if (ctx->endian == LITTLEENDIAN)
508 64 : put_unsigned_short_le(data, bufptr);
509 : else
510 64 : put_unsigned_short_be(data, bufptr);
511 128 : }
512 :
513 : typedef union
514 : {
515 : int i;
516 : unsigned int u;
517 : } unionint;
518 :
519 39 : static int get_int32(blxcontext_t *ctx, const unsigned char **data)
520 : {
521 : /* We assume two's complement representation for this to work */
522 39 : unionint result = {0};
523 :
524 39 : if (ctx->endian == LITTLEENDIAN)
525 21 : result.u = *(*data) | (*(*data + 1) << 8) | (*(*data + 2) << 16) |
526 21 : ((unsigned)*(*data + 3) << 24);
527 : else
528 18 : result.u = *(*data + 3) | (*(*data + 2) << 8) | (*(*data + 1) << 16) |
529 18 : ((unsigned)*(*data) << 24);
530 39 : *data += 4;
531 39 : return result.i;
532 : }
533 :
534 76 : static void put_int32(blxcontext_t *ctx, int data, unsigned char **bufptr)
535 : {
536 : /* We assume two's complement representation for this to work */
537 76 : unionint ui = {0};
538 76 : ui.i = data;
539 76 : if (ctx->endian == LITTLEENDIAN)
540 : {
541 38 : *(*bufptr)++ = (unsigned char)(ui.u & 0xff);
542 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 8) & 0xff);
543 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 16) & 0xff);
544 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 24) & 0xff);
545 : }
546 : else
547 : {
548 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 24) & 0xff);
549 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 16) & 0xff);
550 38 : *(*bufptr)++ = (unsigned char)((ui.u >> 8) & 0xff);
551 38 : *(*bufptr)++ = (unsigned char)(ui.u & 0xff);
552 : }
553 76 : }
554 :
555 208 : static int get_unsigned32(blxcontext_t *ctx, const unsigned char **data)
556 : {
557 : int result;
558 :
559 208 : if (ctx->endian == LITTLEENDIAN)
560 112 : result = *(*data) | (*(*data + 1) << 8) | (*(*data + 2) << 16) |
561 112 : ((unsigned)*(*data + 3) << 24);
562 : else
563 96 : result = *(*data + 3) | (*(*data + 2) << 8) | (*(*data + 1) << 16) |
564 96 : ((unsigned)*(*data) << 24);
565 208 : *data += 4;
566 208 : return result;
567 : }
568 :
569 : /* Check native endian order */
570 136 : static int is_big_endian(void)
571 : {
572 136 : short int word = 0x0001;
573 136 : char *byte = (char *)&word;
574 136 : return (byte[0] ? 0 : 1);
575 : }
576 :
577 32 : static double doubleSWAP(double df)
578 : {
579 32 : CPL_SWAP64PTR(&df);
580 32 : return df;
581 : }
582 :
583 52 : static double get_double(blxcontext_t *ctx, const unsigned char **data)
584 : {
585 : double result;
586 52 : memcpy(&result, *data, sizeof(double));
587 104 : if ((is_big_endian() && ctx->endian == LITTLEENDIAN) ||
588 104 : (!is_big_endian() && ctx->endian == BIGENDIAN))
589 24 : result = doubleSWAP(result);
590 :
591 52 : *data += sizeof(double);
592 :
593 52 : return result;
594 : }
595 :
596 16 : static void put_double(blxcontext_t *ctx, double data, unsigned char **bufptr)
597 : {
598 32 : if ((is_big_endian() && ctx->endian == LITTLEENDIAN) ||
599 32 : (!is_big_endian() && ctx->endian == BIGENDIAN))
600 8 : data = doubleSWAP(data);
601 16 : memcpy(*bufptr, &data, sizeof(double));
602 16 : *bufptr += sizeof(double);
603 16 : }
604 :
605 64 : static void put_cellindex_entry(blxcontext_t *ctx, struct cellindex_s *ci,
606 : unsigned char **buffer)
607 : {
608 64 : put_int32(ctx, (int)ci->offset, buffer);
609 64 : put_unsigned_short(ctx, (unsigned short)ci->datasize, buffer);
610 64 : put_unsigned_short(ctx, (unsigned short)ci->compdatasize, buffer);
611 64 : }
612 :
613 : /* Transpose matrix in-place */
614 728 : static void transpose(blxdata *data, int rows, int cols)
615 : {
616 : int i, j;
617 : blxdata tmp;
618 :
619 23448 : for (i = 0; i < rows; i++)
620 532320 : for (j = i + 1; j < cols; j++)
621 : {
622 509600 : tmp = data[i * cols + j];
623 509600 : data[i * cols + j] = data[j * cols + i];
624 509600 : data[j * cols + i] = tmp;
625 : }
626 728 : }
627 :
628 : struct lutentry_s
629 : {
630 : blxdata value;
631 : int frequency;
632 : };
633 :
634 66234 : static int lutcmp(const void *aa, const void *bb)
635 : {
636 66234 : const struct lutentry_s *a = aa, *b = bb;
637 :
638 66234 : return b->frequency - a->frequency;
639 : }
640 :
641 32 : int blx_encode_celldata(blxcontext_t *ctx, blxdata *indata, int side,
642 : unsigned char *outbuf, CPL_UNUSED int outbufsize)
643 : {
644 32 : unsigned char *p = outbuf, *tmpdata, *coutstart, *cout = NULL;
645 : int level, cn, coutsize, zeros;
646 32 : blxdata *vdec = NULL, *vdiff = NULL, *c[4] = {NULL}, *tc1, *clut,
647 : *indata_scaled;
648 :
649 : struct lutentry_s lut[256];
650 32 : int lutsize = 0;
651 :
652 : int i, j;
653 :
654 32 : memset(&lut, 0, sizeof(lut));
655 32 : lut[0].value = 0;
656 :
657 32 : *p++ = (unsigned char)(side / 32 - 4); /* Resolution */
658 :
659 : /* Allocated memory for buffers */
660 32 : indata_scaled = BLXmalloc(sizeof(blxdata) * side * side);
661 32 : vdec = BLXmalloc(sizeof(blxdata) * side * side / 2);
662 32 : vdiff = BLXmalloc(sizeof(blxdata) * side * side / 2);
663 160 : for (cn = 0; cn < 4; cn++)
664 128 : c[cn] = BLXmalloc(sizeof(blxdata) * side * side / 4);
665 32 : tc1 = BLXmalloc(sizeof(blxdata) * side * side / 4);
666 32 : tmpdata = BLXmalloc(5 * 4 * side * side / 4);
667 :
668 : /* Scale indata and process undefined values*/
669 524320 : for (i = 0; i < side * side; i++)
670 : {
671 524288 : if ((indata[i] == BLX_UNDEF) && ctx->fillundef)
672 0 : indata[i] = (blxdata)ctx->fillundefval;
673 : /* cppcheck-suppress uninitdata */
674 524288 : indata_scaled[i] = (blxdata)(indata[i] / ctx->zscale);
675 : }
676 :
677 32 : indata = indata_scaled;
678 :
679 32 : cout = tmpdata;
680 :
681 192 : for (level = 0; level < 5; level++)
682 : {
683 160 : if (ctx->debug)
684 : {
685 0 : BLXdebug1("\nlevel=%d\n", level);
686 : }
687 160 : decimate_vert(indata, side, side, vdec, vdiff);
688 160 : decimate_horiz(vdec, side / 2, side, c[0], c[1]);
689 160 : decimate_horiz(vdiff, side / 2, side, c[2], c[3]);
690 :
691 : /* For some reason the matrix is transposed if the lut is used for
692 : * vdec_hdiff */
693 4128 : for (i = 0; i < side / 2; i++)
694 178560 : for (j = 0; j < side / 2; j++)
695 : {
696 174592 : tc1[j * side / 2 + i] = c[1][i * side / 2 + j];
697 174592 : tc1[i * side / 2 + j] = c[1][j * side / 2 + i];
698 : }
699 :
700 640 : for (cn = 1; cn < 4; cn++)
701 : {
702 : /* Use the possibly transposed version of c when building lut */
703 480 : if (cn == 1)
704 160 : clut = tc1;
705 : else
706 320 : clut = c[cn];
707 :
708 480 : lutsize = 0;
709 480 : coutstart = cout;
710 524256 : for (i = 0; i < side * side / 4; i++)
711 : {
712 : /* Find element in lookup table */
713 7448770 : for (j = 0; (j < lutsize) && (lut[j].value != clut[i]); j++)
714 : ;
715 :
716 523776 : if (clut[i] != 0)
717 : {
718 456638 : if (j == lutsize)
719 : {
720 18636 : lut[lutsize].value = clut[i];
721 18636 : lut[lutsize].frequency = 1;
722 18636 : lutsize++;
723 18636 : if (lutsize >= 255)
724 0 : break;
725 : }
726 : else
727 438002 : lut[j].frequency++;
728 : }
729 : }
730 480 : if (lutsize < 255)
731 : {
732 : /* Since the Huffman table is arranged to let smaller number
733 : occupy less bits after the compression, the lookup table is sorted on
734 : frequency */
735 480 : qsort(lut, lutsize, sizeof(struct lutentry_s), lutcmp);
736 :
737 480 : zeros = 0;
738 524256 : for (i = 0; i < side * side / 4; i++)
739 : {
740 523776 : if (clut[i] == 0)
741 67138 : zeros++;
742 523776 : if (((zeros > 0) && (clut[i] != 0)) ||
743 475588 : (zeros >= 0x100 - lutsize))
744 : {
745 48188 : *cout++ = (unsigned char)(0x100 - zeros);
746 48188 : zeros = 0;
747 : }
748 523776 : if (clut[i] != 0)
749 : {
750 3788590 : for (j = 0; (j < lutsize) && (lut[j].value != clut[i]);
751 3331950 : j++)
752 : ;
753 456638 : *cout++ = (unsigned char)j;
754 : }
755 : }
756 480 : if (zeros > 0)
757 24 : *cout++ = (unsigned char)(0x100 - zeros);
758 : }
759 : /* Use the lookuptable only when it pays off to do do.
760 : For some reason there cannot be lookup tables in level 4.
761 : Otherwise Mapsend crashes. */
762 480 : coutsize = (int)(cout - coutstart);
763 480 : if ((lutsize < 255) &&
764 480 : (coutsize + 2 * lutsize + 1 < 2 * side * side / 4) &&
765 : (level < 4))
766 : {
767 304 : *p++ = (unsigned char)(lutsize + 1);
768 14042 : for (j = 0; j < lutsize; j++)
769 13738 : put_short_le(lut[j].value, &p);
770 304 : put_short_le((short)coutsize, &p);
771 :
772 304 : if (ctx->debug)
773 : {
774 0 : BLXdebug2("n=%d dlen=%d\n", lutsize + 1, coutsize);
775 0 : BLXdebug0("lut={");
776 0 : for (i = 0; i < lutsize; i++)
777 0 : BLXdebug1("%d, ", lut[i].value);
778 0 : BLXdebug0("}\n");
779 : }
780 : }
781 : else
782 : {
783 176 : *p++ = 0;
784 176 : cout = coutstart;
785 6832 : for (i = 0; i < side * side / 4; i++)
786 6656 : put_short(ctx, c[cn][i], &cout);
787 : }
788 : }
789 :
790 160 : side >>= 1;
791 160 : indata = c[0];
792 : }
793 :
794 32 : memcpy(p, tmpdata, cout - tmpdata);
795 32 : p += cout - tmpdata;
796 :
797 544 : for (i = 0; i < side * side; i++)
798 512 : put_short(ctx, indata[i], &p);
799 :
800 32 : *p++ = 0;
801 :
802 32 : BLXfree(indata_scaled);
803 32 : BLXfree(vdec);
804 32 : BLXfree(vdiff);
805 160 : for (cn = 0; cn < 4; cn++)
806 128 : BLXfree(c[cn]);
807 32 : BLXfree(tc1);
808 32 : BLXfree(tmpdata);
809 :
810 32 : return (int)(p - outbuf);
811 : }
812 :
813 192 : STATIC blxdata *decode_celldata(blxcontext_t *ctx, const unsigned char *inbuf,
814 : int len, int *side, blxdata *outbuf,
815 : int outbufsize, int overviewlevel)
816 : {
817 192 : const unsigned char *inptr = inbuf;
818 : int resolution, l_div, level, c, n, i, j, dpos, tmp, a, value, l_index,
819 : step, cellsize;
820 192 : int baseside[12] = {0};
821 : blxdata *base, *diff;
822 : struct component_s linfo[MAXLEVELS][MAXCOMPONENTS];
823 :
824 192 : if (len < 1)
825 : {
826 0 : BLXerror0("Cell corrupt");
827 0 : return NULL;
828 : }
829 192 : resolution = *inptr++;
830 192 : len--;
831 :
832 192 : tmp = (resolution + 4) * 32;
833 2304 : for (l_div = 1; l_div < 12; l_div++)
834 2112 : baseside[l_div - 1] = tmp >> l_div;
835 :
836 192 : if (side != NULL)
837 0 : *side = tmp >> overviewlevel;
838 :
839 192 : cellsize = tmp * tmp;
840 192 : if (outbufsize < cellsize * (int)sizeof(blxdata))
841 : {
842 0 : BLXerror0("Cell will not fit in output buffer\n");
843 0 : return NULL;
844 : }
845 :
846 192 : if (outbuf == NULL)
847 : {
848 0 : BLXerror0("outbuf is NULL");
849 0 : return NULL;
850 : }
851 :
852 192 : if (ctx->debug)
853 : {
854 0 : BLXdebug0("==============================\n");
855 : }
856 :
857 : /* Clear level info structure */
858 192 : memset(linfo, 0, sizeof(linfo));
859 :
860 192 : base = BLXmalloc(sizeof(blxdata) * 2 * baseside[0] * baseside[0]);
861 192 : diff = BLXmalloc(sizeof(blxdata) * 2 * baseside[0] * baseside[0]);
862 192 : if (base == NULL || diff == NULL)
863 : {
864 0 : BLXerror0("Not enough memory\n");
865 0 : outbuf = NULL;
866 0 : goto error;
867 : }
868 :
869 1152 : for (level = 0; level < 5; level++)
870 : {
871 3840 : for (c = 1; c < 4; c++)
872 : {
873 2880 : if (len < 1)
874 : {
875 0 : BLXerror0("Cell corrupt");
876 0 : outbuf = NULL;
877 0 : goto error;
878 : }
879 2880 : n = *inptr++;
880 2880 : len--;
881 2880 : linfo[level][c].n = n;
882 2880 : if (n > 0)
883 : {
884 2144 : linfo[level][c].lut = BLXmalloc(sizeof(blxdata) * (n - 1));
885 2144 : if (len < (int)sizeof(short) * n)
886 : {
887 0 : BLXerror0("Cell corrupt");
888 0 : outbuf = NULL;
889 0 : goto error;
890 : }
891 44228 : for (i = 0; i < n - 1; i++)
892 42084 : linfo[level][c].lut[i] = (blxdata)get_short_le(&inptr);
893 2144 : linfo[level][c].dlen = get_short_le(&inptr);
894 2144 : if (linfo[level][c].dlen < 0)
895 : {
896 0 : BLXerror0("Cell corrupt");
897 0 : outbuf = NULL;
898 0 : goto error;
899 : }
900 2144 : len -= sizeof(short) * n;
901 : }
902 : else
903 : {
904 736 : linfo[level][c].dlen = 0;
905 : }
906 : }
907 : }
908 :
909 1152 : for (level = 0; level < 5; level++)
910 : {
911 960 : if (ctx->debug)
912 : {
913 0 : BLXdebug1("\nlevel=%d\n", level);
914 : }
915 :
916 960 : linfo[level][0].data =
917 960 : BLXmalloc(sizeof(blxdata) * baseside[level] * baseside[level]);
918 960 : if (linfo[level][0].data == NULL)
919 : {
920 0 : BLXerror0("Not enough memory\n");
921 0 : outbuf = NULL;
922 0 : goto error;
923 : }
924 :
925 3840 : for (c = 1; c < 4; c++)
926 : {
927 2880 : if (ctx->debug)
928 : {
929 0 : BLXdebug2("n=%d dlen=%d\n", linfo[level][c].n,
930 : linfo[level][c].dlen);
931 0 : BLXdebug0("lut={");
932 0 : for (i = 0; i < linfo[level][c].n - 1; i++)
933 0 : BLXdebug1("%d, ", linfo[level][c].lut[i]);
934 0 : BLXdebug0("}\n");
935 : }
936 :
937 2880 : linfo[level][c].data =
938 2880 : BLXmalloc(sizeof(blxdata) * baseside[level] * baseside[level]);
939 2880 : if (linfo[level][c].data == NULL)
940 : {
941 0 : BLXerror0("Not enough memory\n");
942 0 : outbuf = NULL;
943 0 : goto error;
944 : }
945 :
946 2880 : if (linfo[level][c].n == 0)
947 : {
948 736 : if (len <
949 736 : (int)sizeof(short) * baseside[level] * baseside[level])
950 : {
951 0 : BLXerror0("Cell corrupt");
952 0 : outbuf = NULL;
953 0 : goto error;
954 : }
955 20192 : for (i = 0; i < baseside[level] * baseside[level]; i++)
956 19456 : linfo[level][c].data[i] = (blxdata)get_short(ctx, &inptr);
957 736 : len -= sizeof(short) * baseside[level] * baseside[level];
958 : }
959 : else
960 : {
961 2144 : dpos = 0;
962 2144 : if (len < linfo[level][c].dlen)
963 : {
964 0 : BLXerror0("Cell corrupt");
965 0 : outbuf = NULL;
966 0 : goto error;
967 : }
968 2445070 : for (i = 0; i < linfo[level][c].dlen; i++)
969 : {
970 2442920 : unsigned char v = *inptr++;
971 2442920 : if (v >= linfo[level][c].n - 1)
972 : {
973 549452 : if (dpos + 256 - v > baseside[level] * baseside[level])
974 : {
975 0 : BLXerror0("Cell corrupt\n");
976 0 : outbuf = NULL;
977 0 : goto error;
978 : }
979 : /* coverity[tainted_data] */
980 1779180 : for (j = 0; j < 256 - v; j++)
981 1229730 : linfo[level][c].data[dpos++] = 0;
982 : }
983 : else
984 : {
985 1893470 : if (dpos + 1 > baseside[level] * baseside[level])
986 : {
987 0 : BLXerror0("Cell corrupt\n");
988 0 : outbuf = NULL;
989 0 : goto error;
990 : }
991 1893470 : linfo[level][c].data[dpos++] = linfo[level][c].lut[v];
992 : }
993 : }
994 2144 : len -= linfo[level][c].dlen;
995 2144 : if (c == 1)
996 728 : transpose(linfo[level][c].data, baseside[level],
997 : baseside[level]);
998 : }
999 : if (0 && ctx->debug)
1000 : {
1001 : BLXdebug1("baseside:%d\n", baseside[level]);
1002 : BLXdebug0("data={");
1003 : for (i = 0; i < baseside[level] * baseside[level]; i++)
1004 : BLXdebug1("%d, ", linfo[level][c].data[i]);
1005 : BLXdebug0("}\n");
1006 : }
1007 : }
1008 : }
1009 :
1010 192 : if (len < (int)sizeof(short) * baseside[4] * baseside[4])
1011 : {
1012 0 : BLXerror0("Cell corrupt");
1013 0 : outbuf = NULL;
1014 0 : goto error;
1015 : }
1016 3264 : for (i = 0; i < baseside[4] * baseside[4]; i++)
1017 3072 : linfo[4][0].data[i] = (blxdata)get_short(ctx, &inptr);
1018 192 : len -= sizeof(short) * baseside[4] * baseside[4];
1019 :
1020 992 : for (level = 4; level >= overviewlevel; level--)
1021 : {
1022 800 : if (ctx->debug)
1023 : {
1024 0 : BLXdebug1("baseside:%d\n", baseside[level]);
1025 0 : BLXdebug0("inbase={");
1026 0 : for (i = 0; i < baseside[level] * baseside[level]; i++)
1027 0 : BLXdebug1("%d, ", linfo[level][0].data[i]);
1028 0 : BLXdebug0("}\n");
1029 0 : BLXdebug0("indiff={");
1030 0 : for (i = 0; i < baseside[level] * baseside[level]; i++)
1031 0 : BLXdebug1("%d, ", linfo[level][1].data[i]);
1032 0 : BLXdebug0("}\n");
1033 : }
1034 :
1035 800 : reconstruct_horiz(linfo[level][0].data, linfo[level][1].data,
1036 800 : baseside[level], baseside[level], base);
1037 800 : if (ctx->debug)
1038 : {
1039 0 : BLXdebug0("base={");
1040 0 : for (i = 0; i < baseside[level] * baseside[level]; i++)
1041 0 : BLXdebug1("%d, ", base[i]);
1042 0 : BLXdebug0("}\n");
1043 : }
1044 :
1045 800 : reconstruct_horiz(linfo[level][2].data, linfo[level][3].data,
1046 800 : baseside[level], baseside[level], diff);
1047 800 : if (ctx->debug)
1048 : {
1049 0 : BLXdebug0("diff={");
1050 0 : for (i = 0; i < baseside[level] * baseside[level]; i++)
1051 0 : BLXdebug1("%d, ", diff[i]);
1052 0 : BLXdebug0("}\n");
1053 : }
1054 800 : if (level > overviewlevel)
1055 608 : reconstruct_vert(base, diff, baseside[level], 2 * baseside[level],
1056 608 : linfo[level - 1][0].data);
1057 : else
1058 192 : reconstruct_vert(base, diff, baseside[level], 2 * baseside[level],
1059 : outbuf);
1060 : }
1061 :
1062 192 : if (overviewlevel == 0)
1063 : {
1064 128 : if (len < 1)
1065 : {
1066 0 : BLXerror0("Cell corrupt");
1067 0 : outbuf = NULL;
1068 0 : goto error;
1069 : }
1070 128 : a = *((char *)inptr++);
1071 128 : len--;
1072 128 : l_index = 0;
1073 128 : while (len >= 3)
1074 : {
1075 0 : step = inptr[0] | (inptr[1] << 8);
1076 0 : inptr += 2;
1077 0 : value = *((char *)inptr++);
1078 0 : len -= 3;
1079 :
1080 0 : l_index += step;
1081 :
1082 0 : if (value & 1)
1083 0 : value = (value - 1) / 2 - a;
1084 : else
1085 0 : value = value / 2 + a;
1086 :
1087 0 : if (l_index >= cellsize)
1088 : {
1089 0 : BLXerror0("Cell data corrupt\n");
1090 0 : outbuf = NULL;
1091 0 : goto error;
1092 : }
1093 :
1094 0 : outbuf[l_index] = outbuf[l_index] + (blxdata)value;
1095 : }
1096 :
1097 128 : if (len != 0)
1098 0 : BLXdebug1("remaining len=%d", len);
1099 : }
1100 : else
1101 : {
1102 64 : if (len != 1)
1103 0 : BLXdebug1("remaining len=%d", len);
1104 : }
1105 :
1106 : /* Scale data */
1107 3145920 : for (i = 0; i < cellsize; i++)
1108 : {
1109 3145730 : int val = outbuf[i] * (blxdata)ctx->zscale;
1110 3145730 : if (val < SHRT_MIN)
1111 66429 : outbuf[i] = SHRT_MIN;
1112 3079300 : else if (val > SHRT_MAX)
1113 673282 : outbuf[i] = SHRT_MAX;
1114 : else
1115 2406020 : outbuf[i] = (blxdata)val;
1116 : }
1117 :
1118 192 : error:
1119 192 : if (base != NULL)
1120 192 : BLXfree(base);
1121 192 : if (diff != NULL)
1122 192 : BLXfree(diff);
1123 :
1124 : /* Free allocated memory */
1125 1152 : for (level = 4; level >= 0; level--)
1126 4800 : for (c = 0; c < 4; c++)
1127 : {
1128 3840 : if (linfo[level][c].lut)
1129 2144 : BLXfree(linfo[level][c].lut);
1130 3840 : if (linfo[level][c].data)
1131 3840 : BLXfree(linfo[level][c].data);
1132 : }
1133 :
1134 192 : return outbuf;
1135 : }
1136 :
1137 17 : blxcontext_t *blx_create_context()
1138 : {
1139 : blxcontext_t *c;
1140 :
1141 17 : c = BLXmalloc(sizeof(blxcontext_t));
1142 :
1143 17 : memset(c, 0, sizeof(blxcontext_t));
1144 :
1145 17 : c->cell_ysize = c->cell_xsize = 128;
1146 :
1147 17 : c->minval = 32767;
1148 17 : c->maxval = -32768;
1149 :
1150 17 : c->debug = 0;
1151 :
1152 17 : c->zscale = 1;
1153 :
1154 17 : c->fillundef = 1;
1155 17 : c->fillundefval = 0;
1156 :
1157 17 : return c;
1158 : }
1159 :
1160 17 : void blx_free_context(blxcontext_t *ctx)
1161 : {
1162 17 : if (ctx->cellindex)
1163 15 : BLXfree(ctx->cellindex);
1164 :
1165 17 : BLXfree(ctx);
1166 17 : }
1167 :
1168 0 : void blxprintinfo(blxcontext_t *ctx)
1169 : {
1170 0 : BLXnotice2("Lat: %f Lon: %f\n", ctx->lat, ctx->lon);
1171 0 : BLXnotice2("Pixelsize: Lat: %f Lon: %f\n", 3600 * ctx->pixelsize_lat,
1172 : 3600 * ctx->pixelsize_lon);
1173 0 : BLXnotice2("Size %dx%d\n", ctx->xsize, ctx->ysize);
1174 0 : BLXnotice2("Cell size %dx%d\n", ctx->cell_xsize, ctx->cell_ysize);
1175 0 : BLXnotice2("Cell grid %dx%d\n", ctx->cell_cols, ctx->cell_rows);
1176 0 : BLXnotice1("Ysize scale factor: %d\n", ctx->zscale);
1177 0 : BLXnotice1("Max Ysize: %d\n", ctx->zscale * ctx->maxval);
1178 0 : BLXnotice1("Min Ysize: %d\n", ctx->zscale * ctx->minval);
1179 0 : BLXnotice1("Max chunksize: %d\n", ctx->maxchunksize);
1180 0 : }
1181 :
1182 2410 : int blx_checkheader(const char *header)
1183 : {
1184 2410 : const short *signature = (const short *)header;
1185 :
1186 4813 : return ((signature[0] == 0x4) && (signature[1] == 0x66)) ||
1187 2403 : ((signature[0] == 0x400) && (signature[1] == 0x6600));
1188 : }
1189 :
1190 4 : static void blx_generate_header(blxcontext_t *ctx, unsigned char *header)
1191 : {
1192 4 : unsigned char *hptr = header;
1193 :
1194 4 : memset(header, 0, 102);
1195 :
1196 : /* Write signature */
1197 4 : put_short(ctx, 0x4, &hptr); // 0
1198 4 : put_short(ctx, 0x66, &hptr); // 2
1199 :
1200 4 : put_int32(ctx, ctx->cell_xsize * ctx->cell_cols, &hptr); // 4
1201 4 : put_int32(ctx, ctx->cell_ysize * ctx->cell_rows, &hptr); // 8
1202 :
1203 4 : put_short(ctx, (short)ctx->cell_xsize, &hptr); // 12
1204 4 : put_short(ctx, (short)ctx->cell_ysize, &hptr); // 14
1205 :
1206 4 : put_short(ctx, (short)ctx->cell_cols, &hptr); // 16
1207 4 : put_short(ctx, (short)ctx->cell_rows, &hptr); // 18
1208 :
1209 4 : put_double(ctx, ctx->lon, &hptr); // 20
1210 4 : put_double(ctx, -ctx->lat, &hptr); // 28
1211 :
1212 4 : put_double(ctx, ctx->pixelsize_lon, &hptr); // 36
1213 4 : put_double(ctx, -ctx->pixelsize_lat, &hptr); // 44
1214 :
1215 4 : put_short(ctx, (short)ctx->minval, &hptr); // 52
1216 4 : put_short(ctx, (short)ctx->maxval, &hptr); // 54
1217 4 : put_short(ctx, (short)ctx->zscale, &hptr); // 56
1218 4 : put_int32(ctx, ctx->maxchunksize, &hptr); // 58
1219 : // 62
1220 4 : }
1221 :
1222 32 : int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol)
1223 : {
1224 32 : unsigned char *uncompbuf = NULL, *outbuf = NULL;
1225 : int bufsize, uncompsize, compsize;
1226 32 : int status = 0;
1227 : int i, allundef;
1228 :
1229 : /* Calculate statistics and find out if all elements have undefined values
1230 : */
1231 32 : allundef = 1;
1232 524320 : for (i = 0; i < ctx->cell_xsize * ctx->cell_ysize; i++)
1233 : {
1234 524288 : if (cell[i] > ctx->maxval)
1235 224 : ctx->maxval = cell[i];
1236 524288 : if (cell[i] < ctx->minval)
1237 14 : ctx->minval = cell[i];
1238 524288 : if (cell[i] != BLX_UNDEF)
1239 524288 : allundef = 0;
1240 : }
1241 :
1242 32 : if (allundef)
1243 0 : return status;
1244 :
1245 32 : if (ctx->debug)
1246 0 : BLXdebug2("Writing cell (%d,%d)\n", cellrow, cellcol);
1247 :
1248 32 : if (!ctx->open)
1249 : {
1250 0 : status = -3;
1251 0 : goto error;
1252 : }
1253 :
1254 32 : if ((cellrow >= ctx->cell_rows) || (cellcol >= ctx->cell_cols))
1255 : {
1256 0 : status = -2;
1257 0 : goto error;
1258 : }
1259 :
1260 32 : bufsize = sizeof(blxdata) * ctx->cell_xsize * ctx->cell_ysize + 1024;
1261 32 : uncompbuf = BLXmalloc(bufsize);
1262 32 : outbuf = BLXmalloc(bufsize);
1263 :
1264 : uncompsize =
1265 32 : blx_encode_celldata(ctx, cell, ctx->cell_xsize, uncompbuf, bufsize);
1266 32 : compsize = compress_chunk(uncompbuf, uncompsize, outbuf, bufsize);
1267 32 : if (compsize < 0)
1268 : {
1269 0 : BLXerror0("Couldn't compress chunk");
1270 0 : status = -1;
1271 0 : goto error;
1272 : }
1273 :
1274 32 : if (uncompsize > ctx->maxchunksize)
1275 12 : ctx->maxchunksize = uncompsize;
1276 :
1277 32 : ctx->cellindex[cellrow * ctx->cell_cols + cellcol].offset =
1278 32 : (int)BLXftell(ctx->fh);
1279 32 : ctx->cellindex[cellrow * ctx->cell_cols + cellcol].datasize = uncompsize;
1280 32 : ctx->cellindex[cellrow * ctx->cell_cols + cellcol].compdatasize = compsize;
1281 :
1282 32 : if ((int)BLXfwrite(outbuf, 1, compsize, ctx->fh) != compsize)
1283 : {
1284 0 : status = -1;
1285 0 : goto error;
1286 : }
1287 :
1288 32 : error:
1289 32 : if (uncompbuf)
1290 32 : BLXfree(uncompbuf);
1291 32 : if (outbuf)
1292 32 : BLXfree(outbuf);
1293 32 : return status;
1294 : }
1295 :
1296 17 : int blxopen(blxcontext_t *ctx, const char *filename, const char *rw)
1297 : {
1298 : unsigned char header[102];
1299 17 : int signature[2] = {0};
1300 : int i, j;
1301 : struct cellindex_s *ci;
1302 :
1303 17 : if (!strcmp(rw, "r") || !strcmp(rw, "rb"))
1304 13 : ctx->write = 0;
1305 4 : else if (!strcmp(rw, "w") || !strcmp(rw, "wb"))
1306 4 : ctx->write = 1;
1307 : else
1308 0 : goto error;
1309 :
1310 17 : ctx->fh = BLXfopen(filename, rw);
1311 :
1312 17 : if (ctx->fh == NULL)
1313 2 : goto error;
1314 :
1315 15 : if (ctx->write)
1316 : {
1317 2 : unsigned char *hptr = header;
1318 2 : blx_generate_header(ctx, header);
1319 :
1320 2 : if (BLXfwrite(header, 1, 102, ctx->fh) != 102)
1321 0 : goto error;
1322 :
1323 4 : ctx->cellindex = BLXmalloc(sizeof(struct cellindex_s) * ctx->cell_rows *
1324 2 : ctx->cell_cols);
1325 2 : if (ctx->cellindex == NULL)
1326 : {
1327 0 : goto error;
1328 : }
1329 2 : memset(ctx->cellindex, 0,
1330 2 : sizeof(struct cellindex_s) * ctx->cell_rows * ctx->cell_cols);
1331 :
1332 : /* Write the empty cell index (this will be overwritten when we have
1333 : * actual data)*/
1334 10 : for (i = 0; i < ctx->cell_rows; i++)
1335 40 : for (j = 0; j < ctx->cell_cols; j++)
1336 : {
1337 32 : hptr = header;
1338 32 : put_cellindex_entry(
1339 32 : ctx, ctx->cellindex + i * ctx->cell_cols + j, &hptr);
1340 32 : if ((int)BLXfwrite(header, 1, hptr - header, ctx->fh) !=
1341 32 : (int)(hptr - header))
1342 0 : goto error;
1343 : }
1344 : }
1345 : else
1346 : {
1347 13 : const unsigned char *hptr = header;
1348 :
1349 : /* Read header */
1350 13 : if (BLXfread(header, 1, 102, ctx->fh) != 102)
1351 0 : goto error;
1352 :
1353 13 : signature[0] = get_short_le(&hptr);
1354 13 : signature[1] = get_short_le(&hptr);
1355 :
1356 : /* Determine if the endianness of the BLX file */
1357 13 : if ((signature[0] == 0x4) && (signature[1] == 0x66))
1358 7 : ctx->endian = LITTLEENDIAN;
1359 : else
1360 : {
1361 6 : hptr = header;
1362 6 : signature[0] = get_short_be(&hptr);
1363 6 : signature[1] = get_short_be(&hptr);
1364 6 : if ((signature[0] == 0x4) && (signature[1] == 0x66))
1365 6 : ctx->endian = BIGENDIAN;
1366 : else
1367 0 : goto error;
1368 : }
1369 :
1370 13 : ctx->xsize = get_int32(ctx, &hptr);
1371 13 : ctx->ysize = get_int32(ctx, &hptr);
1372 13 : if (ctx->xsize <= 0 || ctx->ysize <= 0)
1373 : {
1374 0 : BLXerror0("Invalid raster size");
1375 0 : goto error;
1376 : }
1377 :
1378 13 : ctx->cell_xsize = get_short(ctx, &hptr);
1379 13 : ctx->cell_ysize = get_short(ctx, &hptr);
1380 13 : if (ctx->cell_xsize <= 0 || ctx->cell_ysize <= 0)
1381 : {
1382 0 : BLXerror0("Invalid cell size");
1383 0 : goto error;
1384 : }
1385 :
1386 13 : ctx->cell_cols = get_short(ctx, &hptr);
1387 13 : ctx->cell_rows = get_short(ctx, &hptr);
1388 13 : if (ctx->cell_cols <= 0 || ctx->cell_cols > 10000 ||
1389 13 : ctx->cell_rows <= 0 || ctx->cell_rows > 10000)
1390 : {
1391 0 : BLXerror0("Invalid cell number");
1392 0 : goto error;
1393 : }
1394 :
1395 13 : ctx->lon = get_double(ctx, &hptr);
1396 13 : ctx->lat = -get_double(ctx, &hptr);
1397 :
1398 13 : ctx->pixelsize_lon = get_double(ctx, &hptr);
1399 13 : ctx->pixelsize_lat = -get_double(ctx, &hptr);
1400 :
1401 13 : ctx->minval = get_short(ctx, &hptr);
1402 13 : ctx->maxval = get_short(ctx, &hptr);
1403 13 : ctx->zscale = get_short(ctx, &hptr);
1404 13 : ctx->maxchunksize = get_int32(ctx, &hptr);
1405 :
1406 26 : ctx->cellindex = BLXmalloc(sizeof(struct cellindex_s) * ctx->cell_rows *
1407 13 : ctx->cell_cols);
1408 13 : if (ctx->cellindex == NULL)
1409 : {
1410 0 : goto error;
1411 : }
1412 :
1413 65 : for (i = 0; i < ctx->cell_rows; i++)
1414 260 : for (j = 0; j < ctx->cell_cols; j++)
1415 : {
1416 : /* Read cellindex entry */
1417 208 : if (BLXfread(header, 1, 8, ctx->fh) != 8)
1418 0 : goto error;
1419 208 : hptr = header;
1420 :
1421 208 : ci = &ctx->cellindex[i * ctx->cell_cols + j];
1422 208 : ci->offset = get_unsigned32(ctx, &hptr);
1423 208 : ci->datasize = get_unsigned_short(ctx, &hptr);
1424 208 : ci->compdatasize = get_unsigned_short(ctx, &hptr);
1425 : }
1426 : }
1427 15 : ctx->open = 1;
1428 :
1429 15 : return 0;
1430 :
1431 2 : error:
1432 2 : return -1;
1433 : }
1434 :
1435 15 : int blxclose(blxcontext_t *ctx)
1436 : {
1437 : unsigned char header[102], *hptr;
1438 15 : int i, j, status = 0;
1439 :
1440 15 : if (ctx->write)
1441 : {
1442 : /* Write updated header and cellindex */
1443 2 : if (BLXfseek(ctx->fh, 0, SEEK_SET) != 0)
1444 : {
1445 0 : status = -1;
1446 0 : goto error;
1447 : }
1448 :
1449 2 : blx_generate_header(ctx, header);
1450 :
1451 2 : if (BLXfwrite(header, 1, 102, ctx->fh) != 102)
1452 : {
1453 0 : status = -1;
1454 0 : goto error;
1455 : }
1456 10 : for (i = 0; i < ctx->cell_rows; i++)
1457 40 : for (j = 0; j < ctx->cell_cols; j++)
1458 : {
1459 32 : hptr = header;
1460 32 : put_cellindex_entry(
1461 32 : ctx, ctx->cellindex + i * ctx->cell_cols + j, &hptr);
1462 32 : if ((int)BLXfwrite(header, 1, hptr - header, ctx->fh) !=
1463 32 : (int)(hptr - header))
1464 : {
1465 0 : status = -1;
1466 0 : break;
1467 : }
1468 : }
1469 : }
1470 15 : ctx->open = 1;
1471 :
1472 15 : error:
1473 15 : if (ctx->fh)
1474 15 : BLXfclose(ctx->fh);
1475 :
1476 15 : return status;
1477 : }
1478 :
1479 192 : short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer,
1480 : int bufsize, int overviewlevel)
1481 : {
1482 : struct cellindex_s *ci;
1483 192 : unsigned char *chunk = NULL, *cchunk = NULL;
1484 192 : blxdata *tmpbuf = NULL;
1485 : int tmpbufsize, i;
1486 192 : short *result = NULL;
1487 : int npoints;
1488 :
1489 192 : if ((ctx == NULL) || (row >= ctx->cell_rows) || (col >= ctx->cell_cols))
1490 0 : return NULL;
1491 :
1492 192 : ci = &ctx->cellindex[row * ctx->cell_cols + col];
1493 :
1494 192 : npoints = (ctx->cell_xsize * ctx->cell_ysize) >> (2 * overviewlevel);
1495 192 : if (bufsize < npoints * (int)sizeof(short))
1496 0 : return NULL;
1497 :
1498 192 : if (ci->datasize == 0)
1499 : {
1500 0 : for (i = 0; i < npoints; i++)
1501 0 : buffer[i] = BLX_UNDEF;
1502 : }
1503 : else
1504 : {
1505 192 : if (BLXfseek(ctx->fh, ci->offset, SEEK_SET) != 0)
1506 0 : goto error;
1507 :
1508 192 : chunk = BLXmalloc(ci->datasize);
1509 192 : cchunk = BLXmalloc(ci->compdatasize);
1510 :
1511 192 : if ((chunk == NULL) || (cchunk == NULL))
1512 0 : goto error;
1513 :
1514 192 : if (BLXfread(cchunk, 1, ci->compdatasize, ctx->fh) != ci->compdatasize)
1515 0 : goto error;
1516 :
1517 384 : if ((unsigned int)uncompress_chunk(cchunk, ci->compdatasize, chunk,
1518 192 : ci->datasize) != ci->datasize)
1519 0 : goto error;
1520 :
1521 192 : tmpbufsize = sizeof(blxdata) * ctx->cell_xsize * ctx->cell_ysize;
1522 192 : tmpbuf = BLXmalloc(tmpbufsize);
1523 192 : if (tmpbuf == NULL)
1524 0 : goto error;
1525 :
1526 192 : if (decode_celldata(ctx, chunk, ci->datasize, NULL, tmpbuf, tmpbufsize,
1527 : overviewlevel) == NULL)
1528 0 : goto error;
1529 :
1530 2184380 : for (i = 0; i < npoints; i++)
1531 2184190 : buffer[i] = tmpbuf[i];
1532 : }
1533 :
1534 192 : result = buffer;
1535 :
1536 192 : error:
1537 192 : if (chunk)
1538 192 : BLXfree(chunk);
1539 192 : if (cchunk)
1540 192 : BLXfree(cchunk);
1541 192 : if (tmpbuf)
1542 192 : BLXfree(tmpbuf);
1543 :
1544 192 : return result;
1545 : }
|