Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package nom.tam.image.compression.bintable;
/*-
* #%L
* nom.tam.fits
* %%
* Copyright (C) 1996 - 2024 nom-tam-fits
* %%
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
* #L%
*/
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import nom.tam.fits.BinaryTable;
import nom.tam.fits.FitsException;
import nom.tam.fits.compression.algorithm.api.ICompressorControl;
import nom.tam.image.compression.hdu.CompressedTableData;
import nom.tam.image.compression.hdu.CompressedTableHDU;
import nom.tam.util.ByteBufferInputStream;
import nom.tam.util.ColumnTable;
import nom.tam.util.FitsInputStream;
import nom.tam.util.type.ElementType;
/**
* (for internal use) Handles the decompression of binary table 'tiles'.
*/
@SuppressWarnings("javadoc")
public class BinaryTableTileDecompressor extends BinaryTableTile {
private BinaryTable orig;
private final CompressedTableData compressed;
private int targetColumn = column;
/**
* @deprecated (for internal use) The visibility will be reduced in the future, not to mention that it should
* take a binary table as its argument, with heap and all. It cannot be used for decompressing
* binary tables with variable-length columns.
*/
public BinaryTableTileDecompressor(CompressedTableData compressedTable, ColumnTable> columnTable,
BinaryTableTileDescription description) throws FitsException {
super(columnTable, description);
compressed = compressedTable;
}
public BinaryTableTileDecompressor(CompressedTableData compressedTable, BinaryTable table,
BinaryTableTileDescription description) throws FitsException {
this(compressedTable, table.getData(), description);
orig = table;
}
private void decompressVariable() throws IOException {
int nRows = rowEnd - rowStart;
boolean longPointers = orig.getDescriptor(targetColumn).hasLongPointers();
// Uncompress the adjoint heap pointer data stored in the compressed table using GZIP_1
ByteBuffer pdata = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
ByteBuffer pointers = ByteBuffer
.allocateDirect((2 * nRows) * (Long.BYTES + (longPointers ? Long.BYTES : Integer.BYTES)));
getGZipCompressorControl().decompress(pdata, pointers, null);
pointers.flip();
long[][] cdesc = new long[nRows][2];
Object p = longPointers ? new long[nRows][2] : new int[nRows][2];
try (FitsInputStream ips = new FitsInputStream(new ByteBufferInputStream(pointers))) {
if (CompressedTableHDU.hasOldStandardVLAIndexing()) {
// --- The FITS standard way ---
// Restore the heap pointers to the compressed data in the compressed heap
ips.readLArray(cdesc);
// Restore the heap pointers for the original uncompressed data locations
ips.readLArray(p);
} else {
// --- The fpack / funpack way ---
// Restore the heap pointers for the original uncompressed data locations
ips.readLArray(p);
// Restore the heap pointers to the compressed data in the compressed heap
ips.readLArray(cdesc);
}
}
ElementType> dataType = ElementType.forClass(orig.getDescriptor(column).getElementClass());
ICompressorControl compressor = getCompressorControl(dataType.primitiveClass());
// Save the original pointers for the compressed tile
final Object bak = compressed.getData().getElement(getTileIndex(), column);
try {
for (int r = 0; r < nRows; r++) {
long csize = cdesc[r][0];
long coffset = cdesc[r][1];
if (csize < 0 || csize > Integer.MAX_VALUE || coffset < 0 || coffset > Integer.MAX_VALUE) {
throw new FitsException(
"Illegal or unsupported compressed heap pointer (offset=" + coffset + ", size=" + csize);
}
long dcount = longPointers ? ((long[][]) p)[r][0] : ((int[][]) p)[r][0];
long doffset = longPointers ? ((long[][]) p)[r][1] : ((int[][]) p)[r][1];
if (dcount < 0 || dcount > Integer.MAX_VALUE || doffset < 0 || doffset > Integer.MAX_VALUE) {
throw new FitsException(
"Illegal or unsupported uncompressed heap pointer (offset=" + doffset + ", size=" + dcount);
}
// Temporarily replace the heap pointers in the compressed table with the pointers to the compressed row
// entry
Object temp = bak instanceof long[] ? new long[] {csize, coffset} : new int[] {(int) csize, (int) coffset};
compressed.getData().setElement(getTileIndex(), column, temp);
// Decompress the row entry, and write it to its original location on the heap
ByteBuffer zip = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
Buffer buf = dataType.newBuffer(dcount);
compressor.decompress(zip, buf, null);
buf.flip();
// Restore the heap pointer in the uncompressed table
data.setElement(rowStart + r, targetColumn, longPointers ? ((long[][]) p)[r] : ((int[][]) p)[r]);
// Restore the uncompressed entry in the original heap location
orig.setElement(rowStart + r, targetColumn, buf.array());
}
} finally {
// Restore the original pointers for the compressed tile.
compressed.getData().setElement(getTileIndex(), column, bak);
}
}
private void decompressTableTile() throws IOException {
ByteBuffer zip = ByteBuffer.wrap((byte[]) compressed.getElement(getTileIndex(), column));
ByteBuffer buf = ByteBuffer.allocateDirect(getUncompressedSizeInBytes());
getCompressorControl().decompress(zip, type.asTypedBuffer(buf), null);
buf.rewind();
try (FitsInputStream is = new FitsInputStream(new ByteBufferInputStream(buf))) {
data.read(is, rowStart, rowEnd, targetColumn);
}
}
@Override
public void run() {
try {
if (orig != null && orig.getDescriptor(targetColumn).isVariableSize()) {
// binary table with variable sized column
decompressVariable();
} else {
// regular column table (fixed width columns)
decompressTableTile();
}
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
/**
* Changes the comlumn index of into which the tile gets decompressed in the uncompressed table. By default the
* decompressed column index will match the compressed data column index, which is great if we decompress the all
* columns. However, we might decompress only selected table columns into a different table in which the column
* indices are different.
*
* @param col the decompressed column index for the tile
*
* @return itself.
*
* @since 1.18
*/
public BinaryTableTileDecompressor decompressToColumn(int col) {
targetColumn = col;
return this;
}
}