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