Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Raster Matrix Format
4 : * Purpose: Implementation of the ad-hoc compression algorithm used in
5 : * GIS "Panorama"/"Integratsia".
6 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 :
32 : #include "rmfdataset.h"
33 :
34 : #include <limits>
35 :
36 : /*
37 : * The encoded data stream is a series of records.
38 : *
39 : * Encoded record consist from the 1-byte record header followed by the
40 : * encoded data block. Header specifies the number of elements in the data
41 : * block and encoding type. Header format
42 : *
43 : * +---+---+---+---+---+---+---+---+
44 : * | type | count |
45 : * +---+---+---+---+---+---+---+---+
46 : * 7 6 5 4 3 2 1 0
47 : *
48 : * If count is zero then it means that there are more than 31 elements in this
49 : * record. Read the next byte in the stream and increase its value with 32 to
50 : * get the count. In this case maximum number of elements is 287.
51 : *
52 : * The "type" field specifies encoding type. It can be either difference
53 : * between the previous and the next data value (for the first element the
54 : * previous value is zero) or out-of-range codes.
55 : *
56 : * In case of "out of range" or "zero difference" values there are no more
57 : * elements in record after the header. Otherwise read as much encoded
58 : * elements as count specifies.
59 : */
60 :
61 : typedef GInt32 DEMWorkT;
62 : typedef GInt64 DEMDiffT;
63 :
64 : // Encoding types
65 : enum RmfTypes
66 : {
67 : TYPE_OUT = 0x00, // Value is out of range
68 : TYPE_ZERO = 0x20, // Zero difference
69 : TYPE_INT4 = 0x40, // Difference is 4-bit wide
70 : TYPE_INT8 = 0x60, // Difference is 8-bit wide
71 : TYPE_INT12 = 0x80, // Difference is 12-bit wide
72 : TYPE_INT16 = 0xA0, // Difference is 16-bit wide
73 : TYPE_INT24 = 0xC0, // Difference is 24-bit wide
74 : TYPE_INT32 = 0xE0 // Difference is 32-bit wide
75 : };
76 :
77 : // Encoding ranges
78 : GInt32 RANGE_INT4 = 0x00000007L; // 4-bit
79 : GInt32 RANGE_INT8 = 0x0000007FL; // 8-bit
80 : GInt32 RANGE_INT12 = 0x000007FFL; // 12-bit
81 : GInt32 RANGE_INT16 = 0x00007FFFL; // 16-bit
82 : GInt32 RANGE_INT24 = 0x007FFFFFL; // 24-bit
83 :
84 : // Out of range codes
85 : GInt32 OUT_INT4 = 0xFFFFFFF8;
86 : GInt32 OUT_INT8 = 0xFFFFFF80;
87 : GInt32 OUT_INT12 = 0xFFFFF800;
88 : GInt32 OUT_INT16 = 0xFFFF8000;
89 : GInt32 OUT_INT24 = 0xFF800000;
90 : GInt32 OUT_INT32 = 0x80000000;
91 :
92 : constexpr DEMDiffT DIFF_OUI_OF_RANGE = std::numeric_limits<DEMDiffT>::max();
93 :
94 : // Inversion masks
95 : GInt32 INV_INT4 = 0xFFFFFFF0L;
96 : GInt32 INV_INT12 = 0xFFFFF000L;
97 : GInt32 INV_INT24 = 0xFF000000L;
98 :
99 : // Not sure which behavior we wish for int32 overflow, so just do the
100 : // addition as uint32 to workaround -ftrapv
101 : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
102 542772 : static GInt32 AddInt32(GInt32 &nTarget, GInt32 nVal)
103 : {
104 542772 : GUInt32 nTargetU = static_cast<GUInt32>(nTarget);
105 542772 : GUInt32 nValU = static_cast<GUInt32>(nVal);
106 542772 : nTargetU += nValU;
107 542772 : memcpy(&nTarget, &nTargetU, 4);
108 542772 : return nTarget;
109 : }
110 :
111 : /************************************************************************/
112 : /* DEMDecompress() */
113 : /************************************************************************/
114 :
115 18 : size_t RMFDataset::DEMDecompress(const GByte *pabyIn, GUInt32 nSizeIn,
116 : GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
117 : GUInt32)
118 : {
119 18 : if (pabyIn == nullptr || pabyOut == nullptr || nSizeOut < nSizeIn ||
120 : nSizeIn < 2)
121 0 : return 0;
122 :
123 18 : GInt32 iPrev = 0; // The last data value decoded.
124 :
125 18 : const signed char *pabyTempIn =
126 : reinterpret_cast<const signed char *>(pabyIn);
127 18 : GInt32 *paiOut = reinterpret_cast<GInt32 *>(pabyOut);
128 18 : nSizeOut /= sizeof(GInt32);
129 :
130 61662 : while (nSizeIn > 0)
131 : {
132 : // Read number of codes in the record and encoding type.
133 61644 : GUInt32 nCount = *pabyTempIn & 0x1F;
134 61644 : const GUInt32 nType = *pabyTempIn++ & 0xE0; // The encoding type.
135 61644 : nSizeIn--;
136 61644 : if (nCount == 0)
137 : {
138 1668 : if (nSizeIn == 0)
139 0 : break;
140 1668 : nCount = 32 + *((GByte *)pabyTempIn++);
141 1668 : nSizeIn--;
142 : }
143 :
144 61644 : switch (nType)
145 : {
146 17994 : case TYPE_ZERO:
147 17994 : if (nSizeOut < nCount)
148 0 : break;
149 17994 : nSizeOut -= nCount;
150 98978 : while (nCount > 0)
151 : {
152 80984 : nCount--;
153 80984 : *paiOut++ = iPrev;
154 : }
155 17994 : break;
156 :
157 1564 : case TYPE_OUT:
158 1564 : if (nSizeOut < nCount)
159 0 : break;
160 1564 : nSizeOut -= nCount;
161 26086 : while (nCount > 0)
162 : {
163 24522 : nCount--;
164 24522 : *paiOut++ = OUT_INT32;
165 : }
166 1564 : break;
167 :
168 1874 : case TYPE_INT4:
169 1874 : if (nSizeIn < (nCount + 1) / 2)
170 0 : break;
171 1874 : if (nSizeOut < nCount)
172 0 : break;
173 1874 : nSizeIn -= nCount / 2;
174 1874 : nSizeOut -= nCount;
175 4902 : while (nCount > 0)
176 : {
177 4014 : nCount--;
178 : GInt32 nCode;
179 4014 : nCode = (*pabyTempIn) & 0x0F;
180 4014 : if (nCode > RANGE_INT4)
181 1752 : nCode |= INV_INT4;
182 4014 : *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
183 3994 : : AddInt32(iPrev, nCode);
184 :
185 4014 : if (nCount == 0)
186 : {
187 986 : if (nSizeIn)
188 : {
189 986 : pabyTempIn++;
190 986 : nSizeIn--;
191 : }
192 986 : break;
193 : }
194 3028 : nCount--;
195 :
196 3028 : nCode = ((*pabyTempIn++) >> 4) & 0x0F;
197 3028 : if (nCode > RANGE_INT4)
198 1222 : nCode |= INV_INT4;
199 6036 : *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
200 3008 : : AddInt32(iPrev, nCode);
201 : }
202 1874 : break;
203 :
204 5924 : case TYPE_INT8:
205 5924 : if (nSizeIn < nCount)
206 0 : break;
207 5924 : if (nSizeOut < nCount)
208 0 : break;
209 5924 : nSizeIn -= nCount;
210 5924 : nSizeOut -= nCount;
211 50708 : while (nCount > 0)
212 : {
213 44784 : nCount--;
214 : GInt32 nCode;
215 44784 : *paiOut++ = ((nCode = *pabyTempIn++) == OUT_INT8)
216 44784 : ? OUT_INT32
217 44766 : : AddInt32(iPrev, nCode);
218 : }
219 5924 : break;
220 :
221 15482 : case TYPE_INT12:
222 15482 : if (nSizeIn < (3 * nCount + 1) / 2)
223 0 : break;
224 15482 : if (nSizeOut < nCount)
225 0 : break;
226 15482 : nSizeIn -= 3 * nCount / 2;
227 15482 : nSizeOut -= nCount;
228 :
229 78758 : while (nCount > 0)
230 : {
231 71274 : nCount--;
232 71274 : GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn) & 0x0FFF;
233 71274 : pabyTempIn += 1;
234 71274 : if (nCode > RANGE_INT12)
235 39394 : nCode |= INV_INT12;
236 71274 : *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
237 70578 : : AddInt32(iPrev, nCode);
238 :
239 71274 : if (nCount == 0)
240 : {
241 7998 : if (nSizeIn)
242 : {
243 7998 : pabyTempIn++;
244 7998 : nSizeIn--;
245 : }
246 7998 : break;
247 : }
248 63276 : nCount--;
249 :
250 63276 : nCode = (CPL_LSBSINT16PTR(pabyTempIn) >> 4) & 0x0FFF;
251 63276 : pabyTempIn += 2;
252 63276 : if (nCode > RANGE_INT12)
253 35672 : nCode |= INV_INT12;
254 125870 : *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
255 62594 : : AddInt32(iPrev, nCode);
256 : }
257 15482 : break;
258 :
259 17958 : case TYPE_INT16:
260 17958 : if (nSizeIn < 2 * nCount)
261 0 : break;
262 17958 : if (nSizeOut < nCount)
263 0 : break;
264 17958 : nSizeIn -= 2 * nCount;
265 17958 : nSizeOut -= nCount;
266 :
267 263522 : while (nCount > 0)
268 : {
269 245564 : nCount--;
270 245564 : const GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn);
271 245564 : pabyTempIn += 2;
272 485978 : *paiOut++ = (nCode == OUT_INT16) ? OUT_INT32
273 240414 : : AddInt32(iPrev, nCode);
274 : }
275 17958 : break;
276 :
277 676 : case TYPE_INT24:
278 676 : if (nSizeIn < 3 * nCount)
279 0 : break;
280 676 : if (nSizeOut < nCount)
281 0 : break;
282 676 : nSizeIn -= 3 * nCount;
283 676 : nSizeOut -= nCount;
284 :
285 70290 : while (nCount > 0)
286 : {
287 69614 : nCount--;
288 69614 : GInt32 nCode = (*(GByte *)pabyTempIn) |
289 69614 : ((*(GByte *)(pabyTempIn + 1)) << 8) |
290 69614 : ((*(GByte *)(pabyTempIn + 2)) << 16);
291 69614 : pabyTempIn += 3;
292 69614 : if (nCode > RANGE_INT24)
293 31998 : nCode |= INV_INT24;
294 137972 : *paiOut++ = (nCode == OUT_INT24) ? OUT_INT32
295 68358 : : AddInt32(iPrev, nCode);
296 : }
297 676 : break;
298 :
299 172 : case TYPE_INT32:
300 172 : if (nSizeIn < 4 * nCount)
301 0 : break;
302 172 : if (nSizeOut < nCount)
303 0 : break;
304 172 : nSizeIn -= 4 * nCount;
305 172 : nSizeOut -= nCount;
306 :
307 49232 : while (nCount > 0)
308 : {
309 49060 : nCount--;
310 49060 : GInt32 nCode = CPL_LSBSINT32PTR(pabyTempIn);
311 49060 : pabyTempIn += 4;
312 98120 : *paiOut++ = (nCode == OUT_INT32) ? OUT_INT32
313 49060 : : AddInt32(iPrev, nCode);
314 : }
315 172 : break;
316 : }
317 : }
318 :
319 18 : return (GByte *)paiOut - pabyOut;
320 : }
321 :
322 : /************************************************************************/
323 : /* DEMWriteCode() */
324 : /************************************************************************/
325 :
326 1212 : static CPLErr DEMWriteRecord(const DEMDiffT *paiRecord, RmfTypes eRecordType,
327 : GUInt32 nRecordSize, GInt32 nSizeOut,
328 : GByte *&pabyCurrent)
329 : {
330 1212 : const GUInt32 nMaxCountInHeader = 31;
331 : GInt32 iCode;
332 : GInt32 iPrevCode;
333 :
334 1212 : if (nRecordSize <= nMaxCountInHeader)
335 : {
336 481 : nSizeOut -= 1;
337 481 : if (nSizeOut <= 0)
338 : {
339 0 : return CE_Failure;
340 : }
341 :
342 481 : *pabyCurrent++ = static_cast<GByte>(eRecordType | nRecordSize);
343 : }
344 : else
345 : {
346 731 : nSizeOut -= 2;
347 731 : if (nSizeOut <= 0)
348 : {
349 0 : return CE_Failure;
350 : }
351 :
352 731 : *pabyCurrent++ = static_cast<GByte>(eRecordType);
353 731 : *pabyCurrent++ = static_cast<GByte>(nRecordSize - 32);
354 : }
355 :
356 1212 : switch (eRecordType)
357 : {
358 46 : case TYPE_INT4:
359 46 : nSizeOut -= ((nRecordSize + 1) / 2);
360 46 : if (nSizeOut <= 0)
361 : {
362 0 : return CE_Failure;
363 : }
364 :
365 84 : for (GUInt32 n = 0; n != nRecordSize; ++n)
366 : {
367 68 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
368 : {
369 0 : iCode = OUT_INT4;
370 : }
371 : else
372 : {
373 68 : iCode = static_cast<GInt32>(paiRecord[n]);
374 : }
375 68 : *pabyCurrent = static_cast<GByte>(iCode & 0x0F);
376 :
377 68 : ++n;
378 68 : if (n == nRecordSize)
379 : {
380 30 : pabyCurrent++;
381 30 : break;
382 : }
383 :
384 38 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
385 : {
386 0 : iCode = OUT_INT4;
387 : }
388 : else
389 : {
390 38 : iCode = static_cast<GInt32>(paiRecord[n]);
391 : }
392 38 : *pabyCurrent++ |= static_cast<GByte>((iCode & 0x0F) << 4);
393 : }
394 46 : break;
395 :
396 100 : case TYPE_INT8:
397 100 : nSizeOut -= nRecordSize;
398 100 : if (nSizeOut <= 0)
399 : {
400 0 : return CE_Failure;
401 : }
402 :
403 8708 : for (GUInt32 n = 0; n != nRecordSize; ++n)
404 : {
405 8608 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
406 : {
407 9 : *pabyCurrent++ = static_cast<GByte>(OUT_INT8);
408 : }
409 : else
410 : {
411 8599 : *pabyCurrent++ = static_cast<GByte>(paiRecord[n]);
412 : }
413 : }
414 100 : break;
415 :
416 278 : case TYPE_INT12:
417 278 : nSizeOut -= ((nRecordSize * 3 + 1) / 2);
418 278 : if (nSizeOut <= 0)
419 : {
420 0 : return CE_Failure;
421 : }
422 :
423 6851 : for (GUInt32 n = 0; n != nRecordSize; ++n)
424 : {
425 6744 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
426 : {
427 348 : iCode = OUT_INT12;
428 : }
429 : else
430 : {
431 6396 : iCode = static_cast<GInt32>(paiRecord[n]);
432 : }
433 :
434 6744 : iPrevCode = iCode;
435 6744 : *pabyCurrent++ = static_cast<GByte>(iCode & 0x00FF);
436 :
437 6744 : ++n;
438 6744 : if (n == nRecordSize)
439 : {
440 171 : *pabyCurrent++ =
441 171 : static_cast<GByte>((iPrevCode & 0x0F00) >> 8);
442 171 : break;
443 : }
444 :
445 6573 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
446 : {
447 341 : iCode = OUT_INT12;
448 : }
449 : else
450 : {
451 6232 : iCode = static_cast<GInt32>(paiRecord[n]);
452 : }
453 6573 : iCode = (((iPrevCode & 0x0F00) >> 8) | ((iCode & 0x0FFF) << 4));
454 :
455 6573 : CPL_LSBPTR32(&iCode);
456 6573 : memcpy(pabyCurrent, &iCode, 2);
457 6573 : pabyCurrent += 2;
458 : }
459 278 : break;
460 :
461 395 : case TYPE_INT16:
462 395 : nSizeOut -= (nRecordSize * 2);
463 395 : if (nSizeOut <= 0)
464 : {
465 0 : return CE_Failure;
466 : }
467 :
468 103286 : for (GUInt32 n = 0; n != nRecordSize; ++n)
469 : {
470 102891 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
471 : {
472 2575 : iCode = OUT_INT16;
473 : }
474 : else
475 : {
476 100316 : iCode = static_cast<GInt32>(paiRecord[n]);
477 : }
478 102891 : CPL_LSBPTR32(&iCode);
479 102891 : memcpy(pabyCurrent, &iCode, 2);
480 102891 : pabyCurrent += 2;
481 : }
482 395 : break;
483 :
484 137 : case TYPE_INT24:
485 137 : nSizeOut -= (nRecordSize * 3);
486 137 : if (nSizeOut <= 0)
487 : {
488 0 : return CE_Failure;
489 : }
490 :
491 34743 : for (GUInt32 n = 0; n != nRecordSize; ++n)
492 : {
493 34606 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
494 : {
495 628 : iCode = OUT_INT24;
496 : }
497 : else
498 : {
499 33978 : iCode = static_cast<GInt32>(paiRecord[n]);
500 : }
501 34606 : CPL_LSBPTR32(&iCode);
502 34606 : memcpy(pabyCurrent, &iCode, 3);
503 34606 : pabyCurrent += 3;
504 : }
505 137 : break;
506 :
507 86 : case TYPE_INT32:
508 86 : nSizeOut -= (nRecordSize * 4);
509 86 : if (nSizeOut <= 0)
510 : {
511 0 : return CE_Failure;
512 : }
513 :
514 24616 : for (GUInt32 n = 0; n != nRecordSize; ++n)
515 : {
516 24530 : if (paiRecord[n] == DIFF_OUI_OF_RANGE)
517 : {
518 0 : iCode = OUT_INT32;
519 : }
520 : else
521 : {
522 24530 : iCode = static_cast<GInt32>(paiRecord[n]);
523 : }
524 24530 : CPL_LSBPTR32(&iCode);
525 24530 : memcpy(pabyCurrent, &iCode, 4);
526 24530 : pabyCurrent += 4;
527 : }
528 86 : break;
529 :
530 170 : case TYPE_ZERO:
531 : case TYPE_OUT:
532 170 : break;
533 :
534 0 : default:
535 0 : return CE_Failure;
536 : }
537 :
538 1212 : return CE_None;
539 : }
540 :
541 : /************************************************************************/
542 : /* DEMDeltaType() */
543 : /************************************************************************/
544 :
545 189311 : static RmfTypes DEMDeltaType(DEMDiffT delta)
546 : {
547 189311 : if (delta <= RANGE_INT12)
548 : {
549 141083 : if (delta <= RANGE_INT4)
550 : {
551 61786 : if (delta == 0)
552 : {
553 49823 : return TYPE_ZERO;
554 : }
555 : else
556 : {
557 11963 : return TYPE_INT4;
558 : }
559 : }
560 : else
561 : {
562 79297 : if (delta <= RANGE_INT8)
563 : {
564 23225 : return TYPE_INT8;
565 : }
566 : else
567 : {
568 56072 : return TYPE_INT12;
569 : }
570 : }
571 : }
572 : else
573 : {
574 48228 : if (delta <= RANGE_INT24)
575 : {
576 33338 : if (delta <= RANGE_INT16)
577 : {
578 24341 : return TYPE_INT16;
579 : }
580 : else
581 : {
582 8997 : return TYPE_INT24;
583 : }
584 : }
585 : else
586 : {
587 14890 : return TYPE_INT32;
588 : }
589 : }
590 : }
591 :
592 : /************************************************************************/
593 : /* DEMCompress() */
594 : /************************************************************************/
595 :
596 5 : size_t RMFDataset::DEMCompress(const GByte *pabyIn, GUInt32 nSizeIn,
597 : GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
598 : GUInt32, const RMFDataset *poDS)
599 : {
600 5 : if (pabyIn == nullptr || pabyOut == nullptr || nSizeIn < sizeof(DEMWorkT))
601 0 : return 0;
602 :
603 5 : const GUInt32 anDeltaTypeSize[8] = {0, 0, 4, 8, 12, 16, 24, 32};
604 5 : const GUInt32 nMaxRecordSize = 255 + 32;
605 :
606 5 : DEMWorkT iMin(std::numeric_limits<DEMWorkT>::min() + 1);
607 5 : if (poDS != nullptr &&
608 5 : poDS->sHeader.adfElevMinMax[0] < poDS->sHeader.adfElevMinMax[1])
609 : {
610 0 : iMin = static_cast<DEMWorkT>(poDS->sHeader.adfElevMinMax[0]);
611 : }
612 5 : GUInt32 nLessCount = 0;
613 5 : GUInt32 nRecordSize = 0;
614 5 : RmfTypes eRecordType = TYPE_OUT;
615 5 : DEMDiffT aiRecord[nMaxRecordSize] = {0};
616 5 : DEMWorkT aiPrev[nMaxRecordSize] = {0};
617 :
618 5 : GByte *pabyCurrent = pabyOut;
619 5 : DEMWorkT iPrev = 0;
620 :
621 5 : nSizeIn = nSizeIn / sizeof(DEMWorkT);
622 :
623 5 : const DEMWorkT *paiIn = reinterpret_cast<const DEMWorkT *>(pabyIn);
624 5 : const DEMWorkT *paiInEnd = paiIn + nSizeIn;
625 :
626 : while (true)
627 : {
628 197413 : GUInt32 nRecordElementSize = 0;
629 :
630 197413 : if (paiIn >= paiInEnd)
631 : {
632 10 : if (nRecordSize == 0)
633 : {
634 5 : return pabyCurrent - pabyOut;
635 : }
636 :
637 5 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
638 : nSizeOut, pabyCurrent))
639 : {
640 0 : return 0;
641 : }
642 5 : nRecordSize = 0;
643 5 : continue;
644 : }
645 :
646 197403 : DEMWorkT iCurr = *(paiIn++);
647 : RmfTypes eCurrType;
648 :
649 197403 : if (iCurr < iMin)
650 : {
651 8092 : eCurrType = TYPE_OUT;
652 8092 : aiRecord[nRecordSize] = DIFF_OUI_OF_RANGE;
653 8092 : aiPrev[nRecordSize] = iPrev;
654 : }
655 : else
656 : {
657 189311 : DEMDiffT delta =
658 189311 : static_cast<DEMDiffT>(iCurr) - static_cast<DEMDiffT>(iPrev);
659 :
660 189311 : aiRecord[nRecordSize] = delta;
661 189311 : aiPrev[nRecordSize] = iCurr;
662 :
663 189311 : if (delta < 0)
664 79880 : delta = -delta;
665 :
666 189311 : eCurrType = DEMDeltaType(delta);
667 189311 : iPrev = iCurr;
668 : }
669 197403 : nRecordSize++;
670 :
671 197403 : if (nRecordSize == 1)
672 : {
673 1212 : eRecordType = eCurrType;
674 : // nRecordElementSize = anDeltaTypeSize[eCurrType >> 5];
675 1212 : continue;
676 : }
677 :
678 196191 : if (nRecordSize == nMaxRecordSize)
679 : {
680 602 : nLessCount = 0;
681 602 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
682 : nSizeOut, pabyCurrent))
683 : {
684 0 : return 0;
685 : }
686 602 : iPrev = aiPrev[nRecordSize - 1];
687 602 : nRecordSize = 0;
688 602 : continue;
689 : }
690 :
691 195589 : if (eCurrType == eRecordType)
692 : {
693 59166 : nLessCount = 0;
694 59166 : continue;
695 : }
696 :
697 136423 : if ((eCurrType > eRecordType) || (eCurrType | eRecordType) == TYPE_ZERO)
698 : {
699 605 : --paiIn;
700 605 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
701 : nRecordSize - 1, nSizeOut,
702 : pabyCurrent))
703 : {
704 0 : return 0;
705 : }
706 605 : iPrev = aiPrev[nRecordSize - 2];
707 605 : nRecordSize = 0;
708 605 : nLessCount = 0;
709 605 : continue;
710 : }
711 :
712 135818 : nLessCount++;
713 :
714 135818 : GUInt32 nDeltaSize(anDeltaTypeSize[eCurrType >> 5]);
715 135818 : if (nRecordElementSize < nDeltaSize ||
716 45035 : (nRecordElementSize - nDeltaSize) * nLessCount < 16)
717 : {
718 135818 : continue;
719 : }
720 :
721 0 : paiIn -= nLessCount;
722 0 : if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
723 : nRecordSize - nLessCount, nSizeOut,
724 : pabyCurrent))
725 : {
726 0 : return 0;
727 : }
728 0 : iPrev = aiPrev[nRecordSize - nLessCount - 1];
729 0 : nRecordSize = 0;
730 0 : nLessCount = 0;
731 197408 : }
732 :
733 : return 0;
734 : }
|