1 package nom.tam.image.compression.hdu; 2 3 import java.nio.Buffer; 4 5 import nom.tam.fits.BinaryTable; 6 import nom.tam.fits.FitsException; 7 import nom.tam.fits.Header; 8 import nom.tam.fits.HeaderCard; 9 import nom.tam.fits.compression.algorithm.api.ICompressOption; 10 import nom.tam.fits.header.Compression; 11 import nom.tam.image.compression.tile.TiledImageCompressionOperation; 12 import nom.tam.util.ArrayFuncs; 13 14 /* 15 * #%L 16 * nom.tam FITS library 17 * %% 18 * Copyright (C) 1996 - 2024 nom-tam-fits 19 * %% 20 * This is free and unencumbered software released into the public domain. 21 * 22 * Anyone is free to copy, modify, publish, use, compile, sell, or 23 * distribute this software, either in source code form or as a compiled 24 * binary, for any purpose, commercial or non-commercial, and by any 25 * means. 26 * 27 * In jurisdictions that recognize copyright laws, the author or authors 28 * of this software dedicate any and all copyright interest in the 29 * software to the public domain. We make this dedication for the benefit 30 * of the public at large and to the detriment of our heirs and 31 * successors. We intend this dedication to be an overt act of 32 * relinquishment in perpetuity of all present and future rights to this 33 * software under copyright law. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 38 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 39 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 40 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 41 * OTHER DEALINGS IN THE SOFTWARE. 42 * #L% 43 */ 44 45 /** 46 * FITS representation of a compressed image. Compressed images are essentially stored as FITS binary tables. They are 47 * distinguished only by a set of mandatory header keywords and specific column data structure. The image-specific 48 * header keywords of the original image are re-mapped to keywords starting with 'Z' prefixed so as to not interfere 49 * with the binary table description. (e.g. NAXIS1 of the original image is stored as ZNAXIS1 in the compressed table). 50 * 51 * @see CompressedImageHDU 52 */ 53 @SuppressWarnings("deprecation") 54 public class CompressedImageData extends BinaryTable { 55 56 /** 57 * tile information, only available during compressing or decompressing. 58 */ 59 private TiledImageCompressionOperation tiledImageOperation; 60 61 /** 62 * Creates a new empty compressed image data to be initialized at a later point 63 */ 64 protected CompressedImageData() { 65 super(); 66 } 67 68 /** 69 * Creates a new compressed image data based on the prescription of the supplied header. 70 * 71 * @param hdr The header that describes the compressed image 72 * 73 * @throws FitsException If the header is invalid or could not be accessed. 74 */ 75 protected CompressedImageData(Header hdr) throws FitsException { 76 super(hdr); 77 } 78 79 @Override 80 public void fillHeader(Header h) throws FitsException { 81 super.fillHeader(h); 82 h.addValue(Compression.ZIMAGE, true); 83 h.deleteKey(Compression.ZTABLE); 84 } 85 86 /** 87 * Returns the class that handles the (de)compression of the image tiles. 88 * 89 * @return the class handling the (de)compression of the image tiles. 90 */ 91 private TiledImageCompressionOperation tiledImageOperation() { 92 if (tiledImageOperation == null) { 93 tiledImageOperation = new TiledImageCompressionOperation(this); 94 } 95 return tiledImageOperation; 96 } 97 98 /** 99 * This should only be called by {@link CompressedImageHDU}. 100 */ 101 @SuppressWarnings("javadoc") 102 protected void compress(CompressedImageHDU hdu) throws FitsException { 103 discardVLAs(); 104 tiledImageOperation().compress(hdu); 105 } 106 107 /** 108 * This should only be called buy{@link CompressedImageHDU}. 109 */ 110 @SuppressWarnings("javadoc") 111 protected void forceNoLoss(int x, int y, int width, int heigth) { 112 tiledImageOperation.forceNoLoss(x, y, width, heigth); 113 } 114 115 /** 116 * Returns the compression (or quantization) options for a selected compression option class. It is presumed that 117 * the requested options are appropriate for the compression and/or quantization algorithm that was selected. E.g., 118 * if you called <code>setCompressionAlgorithm({@link Compression#ZCMPTYPE_RICE_1})</code>, then you can retrieve 119 * options for it with this method as 120 * <code>getCompressOption({@link nom.tam.fits.compression.algorithm.rice.RiceCompressOption}.class)</code>. 121 * 122 * @param <T> The generic type of the compression class 123 * @param clazz the compression class 124 * 125 * @return The current set of options for the requested type, or <code>null</code> if there are no options or 126 * if the requested type does not match the algorithm(s) selected. 127 * 128 * @see nom.tam.fits.compression.algorithm.hcompress.HCompressorOption 129 * @see nom.tam.fits.compression.algorithm.rice.RiceCompressOption 130 * @see nom.tam.fits.compression.algorithm.quant.QuantizeOption 131 */ 132 protected <T extends ICompressOption> T getCompressOption(Class<T> clazz) { 133 return tiledImageOperation().compressOptions().unwrap(clazz); 134 } 135 136 /** 137 * This should only be called by {@link CompressedImageHDU}. 138 */ 139 @SuppressWarnings("javadoc") 140 protected Buffer getUncompressedData(Header hdr) throws FitsException { 141 try { 142 tiledImageOperation = new TiledImageCompressionOperation(this).read(hdr); 143 return tiledImageOperation.decompress(); 144 } finally { 145 tiledImageOperation = null; 146 } 147 } 148 149 /** 150 * This should only be called by {@link CompressedImageHDU}. 151 */ 152 @SuppressWarnings("javadoc") 153 protected void prepareUncompressedData(Object data, Header header) throws FitsException { 154 tiledImageOperation().readPrimaryHeaders(header); 155 Buffer source = tiledImageOperation().getBaseType().newBuffer(tiledImageOperation.getBufferSize()); 156 ArrayFuncs.copyInto(data, source.array()); 157 tiledImageOperation().prepareUncompressedData(source); 158 } 159 160 /** 161 * preserve the null values in the image even if the compression algorithm is lossy. 162 * 163 * @param nullValue the value representing null for byte/short and integer pixel values 164 * @param compressionAlgorithm compression algorithm to use for the null pixel mask 165 */ 166 protected void preserveNulls(long nullValue, String compressionAlgorithm) { 167 tiledImageOperation().preserveNulls(nullValue, compressionAlgorithm); 168 } 169 170 /** 171 * Sets the size of the image to be compressed. 172 * 173 * @param axes the image size 174 * 175 * @return itself This should only be called by {@link CompressedImageHDU}. 176 */ 177 protected CompressedImageData setAxis(int[] axes) { 178 tiledImageOperation().setAxes(axes); 179 return this; 180 } 181 182 /** 183 * Sets the compression algorithm that was used to generate the HDU. 184 * 185 * @param compressAlgorithmCard the FITS header card that specifies the compression algorithm that was used. 186 * 187 * @see #setQuantAlgorithm(HeaderCard) 188 */ 189 protected void setCompressAlgorithm(HeaderCard compressAlgorithmCard) { 190 tiledImageOperation().setCompressAlgorithm(compressAlgorithmCard); 191 } 192 193 /** 194 * Sets the quantization algorithm that was used to generate the HDU. 195 * 196 * @param quantAlgorithmCard the FITS header card that specifies the quantization algorithm that was used. 197 * 198 * @throws FitsException if no algorithm is available by the specified name 199 * 200 * @see #setCompressAlgorithm(HeaderCard) 201 */ 202 protected void setQuantAlgorithm(HeaderCard quantAlgorithmCard) throws FitsException { 203 tiledImageOperation().setQuantAlgorithm(quantAlgorithmCard); 204 } 205 206 /** 207 * Sets the tile size to use for sompressing. 208 * 209 * @param axes the tile size along all dimensions. Only the last 2 dimensions may differ from 1. 210 * 211 * @return itself 212 * 213 * @throws FitsException if the tile size is invalid. This should only be called by {@link CompressedImageHDU}. 214 */ 215 protected CompressedImageData setTileSize(int... axes) throws FitsException { 216 tiledImageOperation().setTileAxes(axes); 217 return this; 218 } 219 }