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.fits.compression.algorithm.plio;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import nom.tam.fits.compression.algorithm.api.ICompressor;
/*
* #%L
* nom.tam FITS library
* %%
* 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%
*/
/**
* (for internal use) The PLIO compression algorithm. The original decompression code was written by Doug Tody,
* NRAO and included (ported to c and adapted) in cfitsio by William Pence, NASA/GSFC. That code was then ported to Java
* by R. van Nieuwenhoven. Later it was massively refactored to harmonize the different compression algorithms and
* reduce the duplicate code pieces without obscuring the algorithm itself as good as possible.
*
* @author Doug Tody
* @author William Pence
* @author Richard van Nieuwenhoven
*/
@SuppressWarnings("javadoc")
public abstract class PLIOCompress {
public static class BytePLIOCompressor extends PLIOCompress implements ICompressor {
private ByteBuffer pixelData;
@Override
public boolean compress(ByteBuffer buffer, ByteBuffer compressed) {
pixelData = buffer;
compress(compressed.asShortBuffer(), pixelData.limit());
return true;
}
@Override
public void decompress(ByteBuffer compressed, ByteBuffer buffer) {
pixelData = buffer;
decompress(compressed.asShortBuffer(), pixelData.limit());
}
@Override
protected int nextPixel() {
return pixelData.get();
}
@Override
protected void put(int index, int pixel) {
pixelData.put(index, (byte) pixel);
}
}
public static class ShortPLIOCompressor extends PLIOCompress implements ICompressor {
private ShortBuffer pixelData;
@Override
public boolean compress(ShortBuffer buffer, ByteBuffer compressed) {
pixelData = buffer;
super.compress(compressed.asShortBuffer(), pixelData.limit());
return true;
}
@Override
public void decompress(ByteBuffer compressed, ShortBuffer buffer) {
pixelData = buffer;
decompress(compressed.asShortBuffer(), pixelData.limit());
}
@Override
protected int nextPixel() {
return pixelData.get();
}
@Override
protected void put(int index, int pixel) {
pixelData.put(index, (short) pixel);
}
}
/**
* Attention int values are limited to 24 bits!
*/
public static class IntPLIOCompressor extends PLIOCompress implements ICompressor {
private IntBuffer pixelData;
@Override
public boolean compress(IntBuffer buffer, ByteBuffer compressed) {
pixelData = buffer;
super.compress(compressed.asShortBuffer(), pixelData.limit());
return true;
}
@Override
public void decompress(ByteBuffer compressed, IntBuffer buffer) {
pixelData = buffer;
decompress(compressed.asShortBuffer(), pixelData.limit());
}
@Override
protected int nextPixel() {
return pixelData.get();
}
@Override
protected void put(int index, int pixel) {
pixelData.put(index, (short) pixel);
}
}
private static final int FIRST_VALUE_WITH_13_BIT = 4096;
private static final int FIRST_VALUE_WITH_14_BIT = 8192;
private static final int FIRST_VALUE_WITH_15_BIT = 16384;
private static final int FIRST_VALUE_WITH_16_BIT = 32768;
private static final int HEADER_SIZE_FIELD1 = 3;
private static final int HEADER_SIZE_FIELD2 = 4;
private static final int LAST_VALUE_FITTING_IN_12_BIT = FIRST_VALUE_WITH_13_BIT - 1;
private static final int MINI_HEADER_SIZE = 3;
private static final int MINI_HEADER_SIZE_FIELD = 2;
/**
* The exact meaning of this var is not clear at the moment of porting the algorithm to Java.
*/
private static final int N20481 = 20481;
private static final int OPCODE_1 = 1;
private static final int OPCODE_2 = 2;
private static final int OPCODE_3 = 3;
private static final int OPCODE_4 = 4;
private static final int OPCODE_5 = 5;
private static final int OPCODE_6 = 6;
private static final int OPCODE_7 = 7;
private static final int OPCODE_8 = 8;
private static final short[] PLIO_HEADER = {(short) 0, (short) 7, (short) -100, (short) 0, (short) 0, (short) 0,
(short) 0};
private static final int SHIFT_12_BITS = 12;
private static final int SHIFT_15_BITS = 15;
private static final int VALUE_OF_BIT_13_AND14_ON = 12288;
/**
* PL_P2L -- Convert a pixel tiledImageOperation to a line list. The length of the list is returned as the function
* value.
*
* @param compressedData encoded line list
* @param npix number of pixels to convert
*/
protected void compress(ShortBuffer compressedData, int npix) {
compressedData.put(PLIO_HEADER);
final int xe = npix - 1;
int op = PLIO_HEADER.length;
/* Computing MAX */
int pv = Math.max(0, nextPixel());
int x1 = 0;
int iz = 0;
int hi = 1;
int nv = 0;
for (int ip = 0; ip <= xe; ++ip) {
if (ip < xe) {
/* Computing MAX */
nv = Math.max(0, nextPixel());
if (nv == pv) {
continue;
}
if (pv == 0) {
pv = nv;
x1 = ip + 1;
continue;
}
} else if (pv == 0) {
x1 = xe + 1;
}
int np = ip - x1 + 1;
int nz = x1 - iz;
boolean skip = false;
if (pv > 0) {
int dv = pv - hi;
if (dv != 0) {
hi = pv;
if (Math.abs(dv) > LAST_VALUE_FITTING_IN_12_BIT) {
compressedData.put(op, (short) ((pv & LAST_VALUE_FITTING_IN_12_BIT) + FIRST_VALUE_WITH_13_BIT));
++op;
compressedData.put(op, (short) (pv / FIRST_VALUE_WITH_13_BIT));
++op;
} else {
if (dv < 0) {
compressedData.put(op, (short) (-dv + VALUE_OF_BIT_13_AND14_ON));
} else {
compressedData.put(op, (short) (dv + FIRST_VALUE_WITH_14_BIT));
}
++op;
if (np == 1 && nz == 0) {
int v = compressedData.get(op - 1);
compressedData.put(op - 1, (short) (v | FIRST_VALUE_WITH_15_BIT));
skip = true;
}
}
}
}
if (!skip) {
if (nz > 0) {
while (nz > 0) {
compressedData.put(op, (short) Math.min(LAST_VALUE_FITTING_IN_12_BIT, nz));
++op;
nz += -LAST_VALUE_FITTING_IN_12_BIT;
}
if (np == 1 && pv > 0) {
compressedData.put(op - 1, (short) (compressedData.get(op - 1) + N20481));
skip = true;
}
}
}
if (!skip) {
while (np > 0) {
compressedData.put(op, (short) (Math.min(LAST_VALUE_FITTING_IN_12_BIT, np) + FIRST_VALUE_WITH_15_BIT));
++op;
np += -LAST_VALUE_FITTING_IN_12_BIT;
}
}
x1 = ip + 1;
iz = x1;
pv = nv;
}
compressedData.put(HEADER_SIZE_FIELD1, (short) (op % FIRST_VALUE_WITH_16_BIT));
compressedData.put(HEADER_SIZE_FIELD2, (short) (op / FIRST_VALUE_WITH_16_BIT));
compressedData.position(op);
}
/**
* PL_L2PI -- Translate a PLIO line list into an integer pixel tiledImageOperation. The number of pixels output
* (always npix) is returned as the function value.
*
* @param compressedData encoded line list
* @param npix number of pixels to convert
*
* @return number of pixels converted
*/
protected int decompress(ShortBuffer compressedData, int npix) {
int llfirt;
int lllen;
if (!(compressedData.get(2) > 0)) {
lllen = (compressedData.get(HEADER_SIZE_FIELD2) << SHIFT_15_BITS) + compressedData.get(HEADER_SIZE_FIELD1);
llfirt = compressedData.get(1);
} else {
lllen = compressedData.get(MINI_HEADER_SIZE_FIELD);
llfirt = MINI_HEADER_SIZE;
}
final int xe = npix;
int op = 0;
int x1 = 1;
int pv = 1;
for (int ip = llfirt; ip <= lllen; ++ip) {
final int opcode = compressedData.get(ip) / FIRST_VALUE_WITH_13_BIT;
final int data = compressedData.get(ip) & LAST_VALUE_FITTING_IN_12_BIT;
final int sw0001 = opcode + 1;
if (sw0001 == OPCODE_1 || sw0001 == OPCODE_5 || sw0001 == OPCODE_6) {
final int x2 = x1 + data - 1;
final int i2 = Math.min(x2, xe);
final int np = i2 - Math.max(x1, 0) + 1;
if (np > 0) {
final int otop = op + np - 1;
if (!(opcode == OPCODE_4)) {
for (int index = op; index <= otop; ++index) {
put(index, 0);
}
if (opcode == OPCODE_5 && i2 == x2) {
put(otop, pv);
}
} else {
for (int index = op; index <= otop; ++index) {
put(index, pv);
}
}
op = otop + 1;
}
x1 = x2 + 1;
} else if (sw0001 == OPCODE_2) {
pv = (compressedData.get(ip + 1) << SHIFT_12_BITS) + data;
++ip;
} else if (sw0001 == OPCODE_3) {
pv += data;
} else if (sw0001 == OPCODE_4) {
pv -= data;
} else if (sw0001 == OPCODE_7) {
pv += data;
if (x1 >= 0 && x1 <= xe) {
put(op, pv);
++op;
}
++x1;
} else if (sw0001 == OPCODE_8) {
pv -= data;
if (x1 >= 0 && x1 <= xe) {
put(op, pv);
++op;
}
++x1;
}
if (x1 > xe) {
break;
}
}
for (int index = op; index < npix; ++index) {
put(index, 0);
}
return npix;
}
protected abstract int nextPixel();
protected abstract void put(int index, int pixel);
}