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
41 * compressed images. In regular images specific values (such as
42 * {@link Double#NaN} or a specific integer value) may be used to indicate
43 * missing data. However, because of e.g. quantization or lossy compression,
44 * these specific values may not be recovered exactly when compressing /
45 * decompressing images. Hence, there is a need to demark <code>null</code>
46 * values differently in copmressed images. This class provides support for that
47 * purpose.
48 */
49 public class AbstractNullPixelMask {
50
51 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
52
53 /** Byte value signifying invalid / null data */
54 protected static final byte NULL_INDICATOR = (byte) 1;
55
56 private final TileBuffer tileBuffer;
57
58 private final int tileIndex;
59
60 private final long nullValue;
61
62 private ByteBuffer mask;
63
64 private final ICompressorControl compressorControl;
65
66 /**
67 * Creates a new pixel mask got a given image tile and designated null
68 * value.
69 *
70 * @param tileBuffer
71 * the buffer containing the tile data
72 * @param tileIndex
73 * the tile index
74 * @param nullValue
75 * the integer value representing <code>null</code> or invalid
76 * data
77 * @param compressorControl
78 * The class managing the compression
79 * @throws IllegalStateException
80 * if the compressorControl argument is <code>null</code>
81 */
82 protected AbstractNullPixelMask(TileBuffer tileBuffer, int tileIndex, long nullValue, ICompressorControl compressorControl) throws IllegalStateException {
83 this.tileBuffer = tileBuffer;
84 this.tileIndex = tileIndex;
85 this.nullValue = nullValue;
86 this.compressorControl = compressorControl;
87 if (this.compressorControl == null) {
88 throw new IllegalStateException("Compression algorithm for the null pixel mask not available");
89 }
90 }
91
92 /**
93 * Returns a byte array containing the mask
94 *
95 * @return the byte array containing the pixel mask for the tile.
96 * @deprecated (<i>for internal use</i>) Visibility may be reduced to
97 * package level in the future.
98 */
99 public byte[] getMaskBytes() {
100 if (mask == null) {
101 return EMPTY_BYTE_ARRAY;
102 }
103 int size = mask.position();
104 byte[] result = new byte[size];
105 mask.rewind();
106 mask.get(result);
107 return result;
108 }
109
110 /**
111 * Sets data for a new mask as a flattened buffer of data.
112 *
113 * @param mask
114 * the buffer containing the mask data in flattened format.
115 */
116 public void setMask(ByteBuffer mask) {
117 this.mask = mask;
118 }
119
120 /**
121 * Returns the object that manages the compression, and which therefore
122 * handles the masking
123 *
124 * @return the object that manages the compression.
125 */
126 protected ICompressorControl getCompressorControl() {
127 return compressorControl;
128 }
129
130 /**
131 * Returns the mask data as a buffer in flattened format.
132 *
133 * @return the buffer containing the mask data in flattened format.
134 */
135 protected ByteBuffer getMask() {
136 return mask;
137 }
138
139 /**
140 * Returns the value that represents a <code>null</code> or an undefined
141 * data point.
142 *
143 * @return the value that demarks an undefined datum.
144 */
145 protected long getNullValue() {
146 return nullValue;
147 }
148
149 /**
150 * Returns the buffer that holds data for an image tile.
151 *
152 * @return the buffer that holds data for a single image tile.
153 */
154 protected TileBuffer getTileBuffer() {
155 return tileBuffer;
156 }
157
158 /**
159 * Return the tile index for the image tile that is processed.
160 *
161 * @return the image tile index
162 */
163 protected int getTileIndex() {
164 return tileIndex;
165 }
166
167 /**
168 * Creates an internal buffer for holding the mask data, for the specified
169 * number of points.
170 *
171 * @param remaining
172 * the number of points the mask should accomodate.
173 * @return the internal buffer that may store the mask data for the
174 * specified number of data points.
175 */
176 protected ByteBuffer initializedMask(int remaining) {
177 if (mask == null) {
178 mask = ByteBuffer.allocate(remaining);
179 }
180 return mask;
181 }
182 }