1 package nom.tam.image.compression.bintable;
2
3
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 import java.io.IOException;
35 import java.nio.Buffer;
36 import java.nio.ByteBuffer;
37
38 import nom.tam.fits.BinaryTable;
39 import nom.tam.fits.FitsException;
40 import nom.tam.fits.compression.algorithm.api.ICompressorControl;
41 import nom.tam.image.compression.hdu.CompressedTableData;
42 import nom.tam.image.compression.hdu.CompressedTableHDU;
43 import nom.tam.util.ByteBufferInputStream;
44 import nom.tam.util.ColumnTable;
45 import nom.tam.util.FitsInputStream;
46 import nom.tam.util.type.ElementType;
47
48
49
50
51 @SuppressWarnings("javadoc")
52 public class BinaryTableTileDecompressor extends BinaryTableTile {
53
54 private BinaryTable orig;
55
56 private final CompressedTableData compressed;
57
58 private int targetColumn = column;
59
60
61
62
63
64
65 @Deprecated
66 public BinaryTableTileDecompressor(CompressedTableData compressedTable, ColumnTable<?> columnTable,
67 BinaryTableTileDescription description) throws FitsException {
68 super(columnTable, description);
69 compressed = compressedTable;
70 }
71
72 public BinaryTableTileDecompressor(CompressedTableData compressedTable, BinaryTable table,
73 BinaryTableTileDescription description) throws FitsException {
74 this(compressedTable, table.getData(), description);
75 orig = table;
76 }
77
78 private synchronized void decompressVariable() throws IOException {
79 int nRows = rowEnd - rowStart;
80 boolean longPointers = orig.getDescriptor(targetColumn).hasLongPointers();
81
82
83 ByteBuffer pdata = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
84 ByteBuffer pointers = ByteBuffer
85 .allocateDirect((2 * nRows) * (Long.BYTES + (longPointers ? Long.BYTES : Integer.BYTES)));
86
87 getGZipCompressorControl().decompress(pdata, pointers, null);
88 pointers.flip();
89
90 long[][] cdesc = new long[nRows][2];
91 Object p = longPointers ? new long[nRows][2] : new int[nRows][2];
92
93 try (FitsInputStream ips = new FitsInputStream(new ByteBufferInputStream(pointers))) {
94 if (CompressedTableHDU.hasOldStandardVLAIndexing()) {
95
96
97 ips.readLArray(cdesc);
98
99 ips.readLArray(p);
100 } else {
101
102
103 ips.readLArray(p);
104
105 ips.readLArray(cdesc);
106 }
107 }
108
109 ElementType<?> dataType = ElementType.forClass(orig.getDescriptor(column).getElementClass());
110
111 ICompressorControl compressor = getCompressorControl(dataType.primitiveClass());
112
113
114 final Object bak = compressed.getData().getElement(getTileIndex(), column);
115
116 try {
117 for (int r = 0; r < nRows; r++) {
118 long csize = cdesc[r][0];
119 long coffset = cdesc[r][1];
120
121 if (csize < 0 || csize > Integer.MAX_VALUE || coffset < 0 || coffset > Integer.MAX_VALUE) {
122 throw new FitsException(
123 "Illegal or unsupported compressed heap pointer (offset=" + coffset + ", size=" + csize);
124 }
125
126 long dcount = longPointers ? ((long[][]) p)[r][0] : ((int[][]) p)[r][0];
127 long doffset = longPointers ? ((long[][]) p)[r][1] : ((int[][]) p)[r][1];
128
129 if (dcount < 0 || dcount > Integer.MAX_VALUE || doffset < 0 || doffset > Integer.MAX_VALUE) {
130 throw new FitsException(
131 "Illegal or unsupported uncompressed heap pointer (offset=" + doffset + ", size=" + dcount);
132 }
133
134
135
136 Object temp = bak instanceof long[] ? new long[] {csize, coffset} : new int[] {(int) csize, (int) coffset};
137 compressed.getData().setElement(getTileIndex(), column, temp);
138
139
140 ByteBuffer zip = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
141 Buffer buf = dataType.newBuffer(dcount);
142 compressor.decompress(zip, buf, null);
143 buf.flip();
144
145
146 data.setElement(rowStart + r, targetColumn, longPointers ? ((long[][]) p)[r] : ((int[][]) p)[r]);
147
148
149 orig.setElement(rowStart + r, targetColumn, buf.array());
150 }
151 } finally {
152
153 compressed.getData().setElement(getTileIndex(), column, bak);
154 }
155 }
156
157 private synchronized void decompressTableTile() throws IOException {
158 ByteBuffer zip = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
159 ByteBuffer buf = ByteBuffer.allocateDirect(getUncompressedSizeInBytes());
160
161 getCompressorControl().decompress(zip, type.asTypedBuffer(buf), null);
162 buf.rewind();
163
164 try (FitsInputStream is = new FitsInputStream(new ByteBufferInputStream(buf))) {
165 data.read(is, rowStart, rowEnd, targetColumn);
166 }
167 }
168
169 @Override
170 public void run() {
171 try {
172 synchronized (this) {
173 if (orig != null && orig.getDescriptor(targetColumn).isVariableSize()) {
174
175 decompressVariable();
176 } else {
177
178 decompressTableTile();
179 }
180 }
181 } catch (IOException e) {
182 throw new IllegalStateException(e.getMessage(), e);
183 }
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198 public synchronized BinaryTableTileDecompressor decompressToColumn(int col) {
199 targetColumn = col;
200 return this;
201 }
202
203 }