1 package nom.tam.image.compression.tile.mask;
2
3 /*
4 * #%L
5 * nom.tam FITS library
6 * %%
7 * Copyright (C) 1996 - 2024 nom-tam-fits
8 * %%
9 * This is free and unencumbered software released into the public domain.
10 *
11 * Anyone is free to copy, modify, publish, use, compile, sell, or
12 * distribute this software, either in source code form or as a compiled
13 * binary, for any purpose, commercial or non-commercial, and by any
14 * means.
15 *
16 * In jurisdictions that recognize copyright laws, the author or authors
17 * of this software dedicate any and all copyright interest in the
18 * software to the public domain. We make this dedication for the benefit
19 * of the public at large and to the detriment of our heirs and
20 * successors. We intend this dedication to be an overt act of
21 * relinquishment in perpetuity of all present and future rights to this
22 * software under copyright law.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE.
31 * #L%
32 */
33
34 import java.nio.ByteBuffer;
35
36 import nom.tam.fits.compression.algorithm.api.ICompressorControl;
37 import nom.tam.image.tile.operation.buffer.TileBuffer;
38
39 /**
40 * (<i>for internal use</i>) Base support for blank (<code>null</code>) in compressed images. In regular images specific
41 * values (such as {@link Double#NaN} or a specific integer value) may be used to indicate missing data. However,
42 * because of e.g. quantization or lossy compression, these specific values may not be recovered exactly when
43 * compressing / decompressing images. Hence, there is a need to demark <code>null</code> values differently in
44 * copmressed images. This class provides support for that purpose.
45 */
46 public class AbstractNullPixelMask {
47
48 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
49
50 /** Byte value signifying invalid / null data */
51 protected static final byte NULL_INDICATOR = (byte) 1;
52
53 private final TileBuffer tileBuffer;
54
55 private final int tileIndex;
56
57 private final long nullValue;
58
59 private ByteBuffer mask;
60
61 private final ICompressorControl compressorControl;
62
63 /**
64 * Creates a new pixel mask got a given image tile and designated null value.
65 *
66 * @param tileBuffer the buffer containing the tile data
67 * @param tileIndex the tile index
68 * @param nullValue the integer value representing <code>null</code> or invalid data
69 * @param compressorControl The class managing the compression
70 *
71 * @throws IllegalStateException if the compressorControl argument is <code>null</code>
72 */
73 protected AbstractNullPixelMask(TileBuffer tileBuffer, int tileIndex, long nullValue,
74 ICompressorControl compressorControl) throws IllegalStateException {
75 this.tileBuffer = tileBuffer;
76 this.tileIndex = tileIndex;
77 this.nullValue = nullValue;
78 this.compressorControl = compressorControl;
79 if (this.compressorControl == null) {
80 throw new IllegalStateException("Compression algorithm for the null pixel mask not available");
81 }
82 }
83
84 /**
85 * Returns a byte array containing the mask
86 *
87 * @return the byte array containing the pixel mask for the tile.
88 *
89 * @deprecated (<i>for internal use</i>) Visibility may be reduced to package level in the future.
90 */
91 @Deprecated
92 public byte[] getMaskBytes() {
93 if (mask == null) {
94 return EMPTY_BYTE_ARRAY;
95 }
96 int size = mask.position();
97 byte[] result = new byte[size];
98 mask.rewind();
99 mask.get(result);
100 return result;
101 }
102
103 /**
104 * Sets data for a new mask as a flattened buffer of data.
105 *
106 * @param mask the buffer containing the mask data in flattened format.
107 */
108 public void setMask(ByteBuffer mask) {
109 this.mask = mask;
110 }
111
112 /**
113 * Returns the object that manages the compression, and which therefore handles the masking
114 *
115 * @return the object that manages the compression.
116 */
117 protected ICompressorControl getCompressorControl() {
118 return compressorControl;
119 }
120
121 /**
122 * Returns the mask data as a buffer in flattened format.
123 *
124 * @return the buffer containing the mask data in flattened format.
125 */
126 protected ByteBuffer getMask() {
127 return mask;
128 }
129
130 /**
131 * Returns the value that represents a <code>null</code> or an undefined data point.
132 *
133 * @return the value that demarks an undefined datum.
134 */
135 protected long getNullValue() {
136 return nullValue;
137 }
138
139 /**
140 * Returns the buffer that holds data for an image tile.
141 *
142 * @return the buffer that holds data for a single image tile.
143 */
144 protected TileBuffer getTileBuffer() {
145 return tileBuffer;
146 }
147
148 /**
149 * Return the tile index for the image tile that is processed.
150 *
151 * @return the image tile index
152 */
153 protected int getTileIndex() {
154 return tileIndex;
155 }
156
157 /**
158 * Creates an internal buffer for holding the mask data, for the specified number of points.
159 *
160 * @param remaining the number of points the mask should accomodate.
161 *
162 * @return the internal buffer that may store the mask data for the specified number of data points.
163 */
164 protected ByteBuffer initializedMask(int remaining) {
165 if (mask == null) {
166 mask = ByteBuffer.allocate(remaining);
167 }
168 return mask;
169 }
170 }