View Javadoc
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 }