1 package nom.tam.fits.compression.algorithm.hcompress;
2
3 import java.nio.ByteBuffer;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import static nom.tam.fits.compression.algorithm.hcompress.HCompress.BITS_OF_1_BYTE;
37 import static nom.tam.fits.compression.algorithm.hcompress.HCompress.BITS_OF_1_NYBBLE;
38 import static nom.tam.fits.compression.algorithm.hcompress.HCompress.BYTE_MASK;
39 import static nom.tam.fits.compression.algorithm.hcompress.HCompress.NYBBLE_MASK;
40 import static nom.tam.fits.compression.algorithm.hcompress.HCompress.ROUNDING_HALF;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class HDecompress {
60
61 private static class LongArrayPointer {
62
63 private final long[] a;
64
65 private int offset;
66
67 LongArrayPointer(long[] tmp) {
68 a = tmp;
69 offset = 0;
70 }
71
72 public void bitOr(int i, long planeVal) {
73 a[offset + i] |= planeVal;
74
75 }
76
77 public LongArrayPointer copy(int extraOffset) {
78 LongArrayPointer intAP = new LongArrayPointer(a);
79 intAP.offset = offset + extraOffset;
80 return intAP;
81 }
82
83 public long get() {
84 return a[offset];
85 }
86
87 public long get(int i) {
88 return a[offset + i];
89 }
90
91 public void set(int i, long value) {
92 a[offset + i] = value;
93
94 }
95
96 public void set(long value) {
97 a[offset] = value;
98 }
99
100 }
101
102 private static final byte[] CODE_MAGIC = {(byte) 0xDD, (byte) 0x99};
103
104 private static final int[] MASKS = {0, 1, 3, 7, 15, 31, 63, 127, 255};
105
106 private static final byte ZERO = 0;
107
108 private static final byte BIT_ONE = 1;
109
110 private static final byte BIT_TWO = 2;
111
112 private static final byte BIT_THREE = 4;
113
114 private static final byte BIT_FOUR = 8;
115
116
117
118
119
120 private static final int N03 = 3;
121
122 private static final int N04 = 4;
123
124 private static final int N05 = 5;
125
126 private static final int N06 = 6;
127
128 private static final int N07 = 7;
129
130 private static final int N08 = 8;
131
132 private static final int N09 = 9;
133
134 private static final int N10 = 10;
135
136 private static final int N11 = 11;
137
138 private static final int N12 = 12;
139
140 private static final int N13 = 13;
141
142 private static final int N14 = 14;
143
144 private static final int N15 = 15;
145
146 private static final int N26 = 26;
147
148 private static final int N27 = 27;
149
150 private static final int N28 = 28;
151
152 private static final int N29 = 29;
153
154 private static final int N30 = 30;
155
156 private static final int N31 = 31;
157
158 private static final int N62 = 62;
159
160 private static final int N63 = 63;
161
162
163
164
165 private int bitsToGo;
166
167
168 private int buffer2;
169
170 private int nx;
171
172 private int ny;
173
174 private int scale;
175
176
177
178
179 private int calculateLog2N(int nmax) {
180 int log2n;
181 log2n = (int) (Math.log(nmax) / Math.log(2.0) + ROUNDING_HALF);
182 if (nmax > 1 << log2n) {
183 log2n++;
184 }
185 return log2n;
186 }
187
188
189
190
191
192
193
194
195 private void decode64(ByteBuffer infile, LongArrayPointer a) {
196 byte[] nbitplanes = new byte[N03];
197 byte[] tmagic = new byte[2];
198
199
200
201
202 infile.get(tmagic);
203
204
205
206 if (tmagic[0] != CODE_MAGIC[0] || tmagic[1] != CODE_MAGIC[1]) {
207 throw new RuntimeException("Compression error");
208 }
209 nx = infile.getInt();
210 ny = infile.getInt();
211 scale = infile.getInt();
212
213
214 long sumall = infile.getLong();
215
216
217 infile.get(nbitplanes);
218
219 dodecode64(infile, a, nbitplanes);
220
221
222
223 a.set(0, sumall);
224 }
225
226
227
228
229
230
231
232
233
234
235
236 public void decompress(ByteBuffer input, boolean smooth, long[] aa) {
237
238 LongArrayPointer a = new LongArrayPointer(aa);
239
240
241
242 decode64(input, a);
243
244
245
246
247 undigitize64(a);
248
249
250
251
252 hinv64(a, smooth);
253
254 }
255
256
257
258
259 private int dodecode64(ByteBuffer infile, LongArrayPointer a, byte[] nbitplanes) {
260 int nel = nx * ny;
261 int nx2 = (nx + 1) / 2;
262 int ny2 = (ny + 1) / 2;
263
264
265
266 for (int i = 0; i < nel; i++) {
267 a.set(i, 0);
268 }
269
270
271
272 startInputingBits();
273
274
275
276 qtreeDecode64(infile, a.copy(0), ny, nx2, ny2, nbitplanes[0]);
277
278 qtreeDecode64(infile, a.copy(ny2), ny, nx2, ny / 2, nbitplanes[1]);
279
280 qtreeDecode64(infile, a.copy(ny * nx2), ny, nx / 2, ny2, nbitplanes[1]);
281
282 qtreeDecode64(infile, a.copy(ny * nx2 + ny2), ny, nx / 2, ny / 2, nbitplanes[2]);
283
284
285
286
287 if (inputNybble(infile) != 0) {
288 throw new RuntimeException("Compression error");
289 }
290
291
292
293 startInputingBits();
294 for (int i = 0; i < nel; i++) {
295 if (a.get(i) != 0) {
296 if (inputBit(infile) != 0) {
297 a.set(i, -a.get(i));
298 }
299 }
300 }
301 return 0;
302 }
303
304
305
306
307 private int hinv64(LongArrayPointer a, boolean smooth) {
308 int nmax = nx > ny ? nx : ny;
309 int log2n = calculateLog2N(nmax);
310
311 long[] tmp = new long[(nmax + 1) / 2];
312
313 int shift = 1;
314 long bit0 = (long) 1 << log2n - 1;
315 long bit1 = bit0 << 1;
316 long bit2 = bit0 << 2;
317 long mask0 = -bit0;
318 long mask1 = mask0 << 1;
319 long mask2 = mask0 << 2;
320 long prnd0 = bit0 >> 1;
321 long prnd1 = bit1 >> 1;
322 long prnd2 = bit2 >> 1;
323 long nrnd0 = prnd0 - 1;
324 long nrnd1 = prnd1 - 1;
325 long nrnd2 = prnd2 - 1;
326
327 a.set(0, a.get(0) + (a.get(0) >= 0 ? prnd2 : nrnd2) & mask2);
328
329
330
331 int nxtop = 1;
332 int nytop = 1;
333 int nxf = nx;
334 int nyf = ny;
335 int c = 1 << log2n;
336 int i;
337 for (int k = log2n - 1; k >= 0; k--) {
338
339
340 c = c >> 1;
341 nxtop = nxtop << 1;
342 nytop = nytop << 1;
343 if (nxf <= c) {
344 nxtop--;
345 } else {
346 nxf -= c;
347 }
348 if (nyf <= c) {
349 nytop--;
350 } else {
351 nyf -= c;
352 }
353
354 if (k == 0) {
355 nrnd0 = 0;
356 shift = 2;
357 }
358
359 for (i = 0; i < nxtop; i++) {
360 unshuffle64(a.copy(ny * i), nytop, 1, tmp);
361 }
362 for (int j = 0; j < nytop; j++) {
363 unshuffle64(a.copy(j), nxtop, ny, tmp);
364 }
365
366 if (smooth) {
367 hsmooth64(a, nxtop, nytop);
368 }
369 int oddx = nxtop % 2;
370 int oddy = nytop % 2;
371 for (i = 0; i < nxtop - oddx; i += 2) {
372 int s00 = ny * i;
373 int s10 = s00 + ny;
374 for (int j = 0; j < nytop - oddy; j += 2) {
375 long h0 = a.get(s00);
376 long hx = a.get(s10);
377 long hy = a.get(s00 + 1);
378 long hc = a.get(s10 + 1);
379
380
381 hx = hx + (hx >= 0 ? prnd1 : nrnd1) & mask1;
382 hy = hy + (hy >= 0 ? prnd1 : nrnd1) & mask1;
383 hc = hc + (hc >= 0 ? prnd0 : nrnd0) & mask0;
384
385 long lowbit0 = hc & bit0;
386 hx = hx >= 0 ? hx - lowbit0 : hx + lowbit0;
387 hy = hy >= 0 ? hy - lowbit0 : hy + lowbit0;
388
389
390
391 long lowbit1 = (hc ^ hx ^ hy) & bit1;
392 h0 = h0 >= 0 ? h0 + lowbit0 - lowbit1 : h0 + (lowbit0 == 0 ? lowbit1 : lowbit0 - lowbit1);
393
394 a.set(s10 + 1, h0 + hx + hy + hc >> shift);
395 a.set(s10, h0 + hx - hy - hc >> shift);
396 a.set(s00 + 1, h0 - hx + hy - hc >> shift);
397 a.set(s00, h0 - hx - hy + hc >> shift);
398 s00 += 2;
399 s10 += 2;
400 }
401 if (oddy != 0) {
402
403
404 long h0 = a.get(s00);
405 long hx = a.get(s10);
406 hx = (hx >= 0 ? hx + prnd1 : hx + nrnd1) & mask1;
407 long lowbit1 = hx & bit1;
408 h0 = h0 >= 0 ? h0 - lowbit1 : h0 + lowbit1;
409 a.set(s10, h0 + hx >> shift);
410 a.set(s00, h0 - hx >> shift);
411 }
412 }
413 if (oddx != 0) {
414
415 int s00 = ny * i;
416 for (int j = 0; j < nytop - oddy; j += 2) {
417 long h0 = a.get(s00);
418 long hy = a.get(s00 + 1);
419 hy = (hy >= 0 ? hy + prnd1 : hy + nrnd1) & mask1;
420 long lowbit1 = hy & bit1;
421 h0 = h0 >= 0 ? h0 - lowbit1 : h0 + lowbit1;
422 a.set(s00 + 1, h0 + hy >> shift);
423 a.set(s00, h0 - hy >> shift);
424 s00 += 2;
425 }
426 if (oddy != 0) {
427
428
429 long h0 = a.get(s00);
430 a.set(s00, h0 >> shift);
431 }
432 }
433
434 bit1 = bit0;
435 bit0 = bit0 >> 1;
436 mask1 = mask0;
437 mask0 = mask0 >> 1;
438 prnd1 = prnd0;
439 prnd0 = prnd0 >> 1;
440 nrnd1 = nrnd0;
441 nrnd0 = prnd0 - 1;
442 }
443 return 0;
444 }
445
446
447
448
449
450 private void hsmooth64(LongArrayPointer a, int nxtop, int nytop) {
451 int i, j;
452 int ny2, s10, s00;
453 long hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2, diff, dmax, dmin, s, smax, m1, m2;
454
455
456
457
458
459 smax = scale >> 1;
460 if (smax <= 0) {
461 return;
462 }
463 ny2 = ny << 1;
464
465
466
467
468
469
470
471
472 for (i = 2; i < nxtop - 2; i += 2) {
473 s00 = ny * i;
474 s10 = s00 + ny;
475 for (j = 0; j < nytop; j += 2) {
476
477
478
479 hm = a.get(s00 - ny2);
480 h0 = a.get(s00);
481 hp = a.get(s00 + ny2);
482
483
484
485 diff = hp - hm;
486
487
488
489 dmax = Math.max(Math.min(hp - h0, h0 - hm), 0) << 2;
490 dmin = Math.min(Math.max(hp - h0, h0 - hm), 0) << 2;
491
492
493
494 if (dmin < dmax) {
495 diff = Math.max(Math.min(diff, dmax), dmin);
496
497
498
499
500 s = diff - (a.get(s10) << N03);
501 s = s >= 0 ? s >> N03 : s + N07 >> N03;
502 s = Math.max(Math.min(s, smax), -smax);
503 a.set(s10, a.get(s10) + s);
504 }
505 s00 += 2;
506 s10 += 2;
507 }
508 }
509
510
511
512 for (i = 0; i < nxtop; i += 2) {
513 s00 = ny * i + 2;
514 s10 = s00 + ny;
515 for (j = 2; j < nytop - 2; j += 2) {
516 hm = a.get(s00 - 2);
517 h0 = a.get(s00);
518 hp = a.get(s00 + 2);
519 diff = hp - hm;
520 dmax = Math.max(Math.min(hp - h0, h0 - hm), 0) << 2;
521 dmin = Math.min(Math.max(hp - h0, h0 - hm), 0) << 2;
522 if (dmin < dmax) {
523 diff = Math.max(Math.min(diff, dmax), dmin);
524 s = diff - (a.get(s00 + 1) << N03);
525 s = s >= 0 ? s >> N03 : s + N07 >> N03;
526 s = Math.max(Math.min(s, smax), -smax);
527 a.set(s00 + 1, a.get(s00 + 1) + s);
528 }
529 s00 += 2;
530 s10 += 2;
531 }
532 }
533
534
535
536 for (i = 2; i < nxtop - 2; i += 2) {
537 s00 = ny * i + 2;
538 s10 = s00 + ny;
539 for (j = 2; j < nytop - 2; j += 2) {
540
541
542
543
544 hmm = a.get(s00 - ny2 - 2);
545 hpm = a.get(s00 + ny2 - 2);
546 hmp = a.get(s00 - ny2 + 2);
547 hpp = a.get(s00 + ny2 + 2);
548 h0 = a.get(s00);
549
550
551
552 diff = hpp + hmm - hmp - hpm;
553
554
555
556 hx2 = a.get(s10) << 1;
557 hy2 = a.get(s00 + 1) << 1;
558
559
560
561 m1 = Math.min(Math.max(hpp - h0, 0) - hx2 - hy2, Math.max(h0 - hpm, 0) + hx2 - hy2);
562 m2 = Math.min(Math.max(h0 - hmp, 0) - hx2 + hy2, Math.max(hmm - h0, 0) + hx2 + hy2);
563 dmax = Math.min(m1, m2) << BITS_OF_1_NYBBLE;
564 m1 = Math.max(Math.min(hpp - h0, 0) - hx2 - hy2, Math.min(h0 - hpm, 0) + hx2 - hy2);
565 m2 = Math.max(Math.min(h0 - hmp, 0) - hx2 + hy2, Math.min(hmm - h0, 0) + hx2 + hy2);
566 dmin = Math.max(m1, m2) << BITS_OF_1_NYBBLE;
567
568
569
570 if (dmin < dmax) {
571 diff = Math.max(Math.min(diff, dmax), dmin);
572
573
574
575
576 s = diff - (a.get(s10 + 1) << N06);
577 s = s >= 0 ? s >> N06 : s + N63 >> N06;
578 s = Math.max(Math.min(s, smax), -smax);
579 a.set(s10 + 1, a.get(s10 + 1) + s);
580 }
581 s00 += 2;
582 s10 += 2;
583 }
584 }
585 }
586
587 private int inputBit(ByteBuffer infile) {
588 if (bitsToGo == 0) {
589
590 buffer2 = infile.get() & BYTE_MASK;
591
592 bitsToGo = BITS_OF_1_BYTE;
593 }
594
595
596
597 bitsToGo--;
598 return buffer2 >> bitsToGo & 1;
599 }
600
601
602
603
604
605
606 private int inputHuffman(ByteBuffer infile) {
607 int c;
608
609
610
611
612 c = inputNbits(infile, N03);
613 if (c < N04) {
614
615
616
617 return 1 << c;
618 }
619
620
621
622 c = inputBit(infile) | c << 1;
623 if (c < N13) {
624
625
626
627 switch (c) {
628 case N08:
629 return N03;
630 case N09:
631 return N05;
632 case N10:
633 return N10;
634 case N11:
635 return N12;
636 case N12:
637 return N15;
638 default:
639 }
640 }
641
642
643
644 c = inputBit(infile) | c << 1;
645 if (c < N31) {
646
647
648
649 switch (c) {
650 case N26:
651 return N06;
652 case N27:
653 return N07;
654 case N28:
655 return N09;
656 case N29:
657 return N11;
658 case N30:
659 return N13;
660 default:
661 }
662 }
663
664
665
666 c = inputBit(infile) | c << 1;
667 if (c == N62) {
668 return 0;
669 }
670 return N14;
671 }
672
673 private int inputNbits(ByteBuffer infile, int n) {
674 if (bitsToGo < n) {
675
676
677
678
679 buffer2 = buffer2 << BITS_OF_1_BYTE | infile.get() & BYTE_MASK;
680 bitsToGo += BITS_OF_1_BYTE;
681 }
682
683
684
685 bitsToGo -= n;
686
687
688
689 return buffer2 >> bitsToGo & MASKS[n];
690 }
691
692
693
694 private int inputNnybble(ByteBuffer infile, int n, byte[] array) {
695
696
697
698
699 int ii, kk, shift1, shift2;
700
701
702
703
704
705 if (n == 1) {
706 array[0] = (byte) inputNybble(infile);
707 return 0;
708 }
709
710 if (bitsToGo == BITS_OF_1_BYTE) {
711
712
713
714 infile.position(infile.position() - 1);
715 bitsToGo = 0;
716 }
717
718
719
720
721 shift1 = bitsToGo + BITS_OF_1_NYBBLE;
722
723
724 shift2 = bitsToGo;
725 kk = 0;
726
727
728 if (bitsToGo == 0) {
729 for (ii = 0; ii < n / 2; ii++) {
730
731
732
733 buffer2 = buffer2 << BITS_OF_1_BYTE | infile.get() & BYTE_MASK;
734 array[kk] = (byte) (buffer2 >> BITS_OF_1_NYBBLE & NYBBLE_MASK);
735 array[kk + 1] = (byte) (buffer2 & NYBBLE_MASK);
736
737
738 kk += 2;
739 }
740 } else {
741 for (ii = 0; ii < n / 2; ii++) {
742
743
744
745 buffer2 = buffer2 << BITS_OF_1_BYTE | infile.get() & BYTE_MASK;
746 array[kk] = (byte) (buffer2 >> shift1 & NYBBLE_MASK);
747 array[kk + 1] = (byte) (buffer2 >> shift2 & NYBBLE_MASK);
748 kk += 2;
749 }
750 }
751
752 if (ii * 2 != n) {
753 array[n - 1] = (byte) inputNybble(infile);
754 }
755
756 return buffer2 >> bitsToGo & NYBBLE_MASK;
757 }
758
759 private int inputNybble(ByteBuffer infile) {
760 if (bitsToGo < BITS_OF_1_NYBBLE) {
761
762
763
764
765 buffer2 = buffer2 << BITS_OF_1_BYTE | infile.get() & BYTE_MASK;
766 bitsToGo += BITS_OF_1_BYTE;
767 }
768
769
770
771 bitsToGo -= BITS_OF_1_NYBBLE;
772
773 return buffer2 >> bitsToGo & NYBBLE_MASK;
774 }
775
776
777
778
779
780
781 private void qtreeBitins64(byte[] a, int lnx, int lny, LongArrayPointer b, int n, int bit) {
782 int i, j, s00;
783 long planeVal = 1L << bit;
784
785 ByteBuffer k = ByteBuffer.wrap(a);
786 for (i = 0; i < lnx - 1; i += 2) {
787 s00 = n * i;
788
789
790
791
792 for (j = 0; j < lny - 1; j += 2) {
793 byte value = k.get();
794 if ((value & BIT_ONE) != ZERO) {
795 b.bitOr(s00 + n + 1, planeVal);
796 }
797 if ((value & BIT_TWO) != ZERO) {
798 b.bitOr(s00 + n, planeVal);
799 }
800 if ((value & BIT_THREE) != ZERO) {
801 b.bitOr(s00 + 1, planeVal);
802 }
803 if ((value & BIT_FOUR) != ZERO) {
804 b.bitOr(s00, planeVal);
805 }
806
807
808
809
810 s00 += 2;
811
812 }
813 if (j < lny) {
814
815
816 byte value = k.get();
817 if ((value & BIT_TWO) != ZERO) {
818 b.bitOr(s00 + n, planeVal);
819 }
820 if ((value & BIT_FOUR) != ZERO) {
821 b.bitOr(s00, planeVal);
822 }
823
824
825 }
826 }
827 if (i < lnx) {
828
829 s00 = n * i;
830 for (j = 0; j < lny - 1; j += 2) {
831 byte value = k.get();
832 if ((value & BIT_THREE) != ZERO) {
833 b.bitOr(s00 + 1, planeVal);
834 }
835 if ((value & BIT_FOUR) != ZERO) {
836 b.bitOr(s00, planeVal);
837 }
838
839 s00 += 2;
840 }
841 if (j < lny) {
842
843
844 if ((k.get() & BIT_FOUR) != ZERO) {
845 b.bitOr(s00, planeVal);
846 }
847
848 }
849 }
850 }
851
852
853
854
855
856 private void qtreeCopy(byte[] a, int lnx, int lny, byte[] b, int n) {
857 int i, j, k, nx2, ny2;
858 int s00, s10;
859
860
861 nx2 = (lnx + 1) / 2;
862 ny2 = (lny + 1) / 2;
863 k = ny2 * (nx2 - 1) + ny2 - 1;
864 for (i = nx2 - 1; i >= 0; i--) {
865 s00 = 2 * (n * i + ny2 - 1);
866 for (j = ny2 - 1; j >= 0; j--) {
867 b[s00] = a[k];
868 k--;
869 s00 -= 2;
870 }
871 }
872 for (i = 0; i < lnx - 1; i += 2) {
873
874
875
876 s00 = n * i;
877 s10 = s00 + n;
878 for (j = 0; j < lny - 1; j += 2) {
879 b[s10 + 1] = (b[s00] & BIT_ONE) == ZERO ? ZERO : BIT_ONE;
880 b[s10] = (b[s00] & BIT_TWO) == ZERO ? ZERO : BIT_ONE;
881 b[s00 + 1] = (b[s00] & BIT_THREE) == ZERO ? ZERO : BIT_ONE;
882 b[s00] = (b[s00] & BIT_FOUR) == ZERO ? ZERO : BIT_ONE;
883 s00 += 2;
884 s10 += 2;
885 }
886 if (j < lny) {
887
888
889 b[s10] = (byte) (b[s00] >> 1 & 1);
890 b[s00] = (byte) (b[s00] >> N03 & 1);
891 }
892 }
893 if (i < lnx) {
894
895 s00 = n * i;
896 for (j = 0; j < lny - 1; j += 2) {
897
898 b[s00 + 1] = (byte) (b[s00] >> 2 & 1);
899 b[s00] = (byte) (b[s00] >> N03 & 1);
900 s00 += 2;
901 }
902 if (j < lny) {
903
904
905
906 b[s00] = (byte) (b[s00] >> N03 & 1);
907 }
908 }
909 }
910
911
912
913
914
915
916 private int qtreeDecode64(ByteBuffer infile, LongArrayPointer a, int n, int nqx, int nqy, int nbitplanes) {
917 int k, bit, b;
918 int nx2, ny2, nfx, nfy, c;
919 byte[] scratch;
920
921
922
923
924 int nqmax = nqx > nqy ? nqx : nqy;
925 int log2n = calculateLog2N(nqmax);
926
927
928
929 int nqx2 = (nqx + 1) / 2;
930 int nqy2 = (nqy + 1) / 2;
931 scratch = new byte[nqx2 * nqy2];
932
933
934
935
936 for (bit = nbitplanes - 1; bit >= 0; bit--) {
937
938
939
940 b = inputNybble(infile);
941
942 if (b == 0) {
943
944
945
946 readBdirect64(infile, a, n, nqx, nqy, scratch, bit);
947 } else if (b != NYBBLE_MASK) {
948 throw new RuntimeException("Compression error");
949 } else {
950
951
952
953 scratch[0] = (byte) inputHuffman(infile);
954
955
956
957 nx2 = 1;
958 ny2 = 1;
959 nfx = nqx;
960 nfy = nqy;
961 c = 1 << log2n;
962 for (k = 1; k < log2n; k++) {
963
964
965
966 c = c >> 1;
967 nx2 = nx2 << 1;
968 ny2 = ny2 << 1;
969 if (nfx <= c) {
970 nx2--;
971 } else {
972 nfx -= c;
973 }
974 if (nfy <= c) {
975 ny2--;
976 } else {
977 nfy -= c;
978 }
979 qtreeExpand(infile, scratch, nx2, ny2, scratch);
980 }
981
982
983
984 qtreeBitins64(scratch, nqx, nqy, a, n, bit);
985 }
986 }
987 return 0;
988 }
989
990
991
992
993
994 private void qtreeExpand(ByteBuffer infile, byte[] a, int nx2, int ny2, byte[] b) {
995 int i;
996
997
998
999
1000 qtreeCopy(a, nx2, ny2, b, ny2);
1001
1002
1003
1004 for (i = nx2 * ny2 - 1; i >= 0; i--) {
1005 if (b[i] != 0) {
1006 b[i] = (byte) inputHuffman(infile);
1007 }
1008 }
1009 }
1010
1011 private void readBdirect64(ByteBuffer infile, LongArrayPointer a, int n, int nqx, int nqy, byte[] scratch, int bit) {
1012
1013
1014
1015
1016
1017
1018 inputNnybble(infile, (nqx + 1) / 2 * ((nqy + 1) / 2), scratch);
1019
1020
1021
1022
1023 qtreeBitins64(scratch, nqx, nqy, a, n, bit);
1024 }
1025
1026
1027
1028
1029 private void startInputingBits() {
1030
1031
1032
1033 bitsToGo = 0;
1034 }
1035
1036 private void undigitize64(LongArrayPointer a) {
1037 long scale64;
1038
1039
1040
1041
1042 if (scale <= 1) {
1043 return;
1044 }
1045 scale64 = scale;
1046
1047
1048
1049 for (int index = 0; index < a.a.length; index++) {
1050 a.a[index] = a.a[index] * scale64;
1051 }
1052 }
1053
1054
1055
1056
1057
1058 private void unshuffle64(LongArrayPointer a, int n, int n2, long[] tmp) {
1059 int i;
1060 int nhalf;
1061 LongArrayPointer p1, p2, pt;
1062
1063
1064
1065
1066 nhalf = n + 1 >> 1;
1067 pt = new LongArrayPointer(tmp);
1068 p1 = a.copy(n2 * nhalf);
1069 for (i = nhalf; i < n; i++) {
1070 pt.set(p1.get());
1071 p1.offset += n2;
1072 pt.offset++;
1073 }
1074
1075
1076
1077 p2 = a.copy(n2 * (nhalf - 1));
1078 p1 = a.copy(n2 * (nhalf - 1) << 1);
1079 for (i = nhalf - 1; i >= 0; i--) {
1080 p1.set(p2.get());
1081 p2.offset -= n2;
1082 p1.offset -= n2 + n2;
1083 }
1084
1085
1086
1087 pt = new LongArrayPointer(tmp);
1088 p1 = a.copy(n2);
1089 for (i = 1; i < n; i += 2) {
1090 p1.set(pt.get());
1091 p1.offset += n2 + n2;
1092 pt.offset++;
1093 }
1094 }
1095 }