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