View Javadoc
1   package nom.tam.fits;
2   
3   /*-
4    * #%L
5    * nom.tam.fits
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.io.IOException;
35  
36  import nom.tam.fits.header.Bitpix;
37  import nom.tam.fits.header.Standard;
38  import nom.tam.util.ArrayDataInput;
39  import nom.tam.util.ArrayDataOutput;
40  import nom.tam.util.ArrayFuncs;
41  import nom.tam.util.Cursor;
42  import nom.tam.util.FitsEncoder;
43  
44  /**
45   * A container for unknown binary data types. We can still retrieve the data as a <code>byte[]</code> array, we just
46   * don't know how to interpret it ourselves. This class makes sure we don't break when we encouter HDUs that we don't
47   * (yet) support, such as HDU types defined by future FITS standards.
48   * 
49   * @see UndefinedHDU
50   */
51  public class UndefinedData extends Data {
52  
53      private static final String XTENSION_UNKNOWN = "UNKNOWN";
54      // private static final Logger LOG = getLogger(UndefinedData.class);
55  
56      private Bitpix bitpix = Bitpix.BYTE;
57      private int[] dims;
58      private int byteSize = 0;
59      private byte[] data;
60      private int pCount = 0;
61      private int gCount = 1;
62  
63      private String extensionType = XTENSION_UNKNOWN;
64  
65      /**
66       * Creates a new empty container for data of unknown type based on the provided FITS header information.
67       *
68       * @param      h             The FITS header corresponding to the data segment in the HDU
69       * 
70       * @throws     FitsException if there wan an error accessing or interpreting the provided header information.
71       * 
72       * @deprecated               (<i>for internal use</i>). Visibility will be reduced to the package level in the
73       *                               future.
74       */
75      @Deprecated
76      public UndefinedData(Header h) throws FitsException {
77          extensionType = h.getStringValue(Standard.XTENSION, XTENSION_UNKNOWN);
78  
79          int naxis = h.getIntValue(Standard.NAXIS);
80  
81          dims = new int[naxis];
82  
83          int size = naxis > 0 ? 1 : 0;
84          for (int i = 1; i <= naxis; i++) {
85              dims[naxis - i] = h.getIntValue(Standard.NAXISn.n(i));
86              size *= dims[naxis - i];
87          }
88  
89          pCount = h.getIntValue(Standard.PCOUNT);
90          size += pCount;
91  
92          gCount = h.getIntValue(Standard.GCOUNT);
93          if (gCount > 1) {
94              size *= h.getIntValue(Standard.GCOUNT);
95          }
96  
97          bitpix = Bitpix.fromHeader(h);
98          size *= bitpix.byteSize();
99  
100         byteSize = size;
101     }
102 
103     /**
104      * @deprecated                          (<i>for internal use</i>). Users should always construct known data types.
105      *                                          Reduce visibility to the package level.
106      * 
107      * @param      x                        object to create the hdu from
108      * 
109      * @throws     IllegalArgumentException If the object is not an array or contains elements that do not have a known
110      *                                          binary size.
111      */
112     @Deprecated
113     public UndefinedData(Object x) throws IllegalArgumentException {
114         byteSize = (int) FitsEncoder.computeSize(x);
115         dims = ArrayFuncs.getDimensions(x);
116         data = new byte[byteSize];
117         ArrayFuncs.copyInto(x, data);
118     }
119 
120     @SuppressWarnings("deprecation")
121     @Override
122     protected void fillHeader(Header head) {
123         // We'll assume it's a primary image, until we know better...
124         // Just in case, we don't want an XTENSION key lingering around...
125         head.deleteKey(Standard.SIMPLE);
126         head.deleteKey(Standard.EXTEND);
127 
128         Standard.context(UndefinedData.class);
129 
130         Cursor<String, HeaderCard> c = head.iterator();
131         c.add(HeaderCard.create(Standard.XTENSION, extensionType));
132         c.add(HeaderCard.create(Standard.BITPIX, bitpix.getHeaderValue()));
133 
134         c.add(HeaderCard.create(Standard.NAXIS, dims.length));
135 
136         for (int i = 1; i <= dims.length; i++) {
137             c.add(HeaderCard.create(Standard.NAXISn.n(i), dims[dims.length - i]));
138         }
139 
140         c.add(HeaderCard.create(Standard.PCOUNT, pCount));
141         c.add(HeaderCard.create(Standard.GCOUNT, gCount));
142 
143         Standard.context(null);
144     }
145 
146     @Override
147     protected byte[] getCurrentData() {
148         return data;
149     }
150 
151     @Override
152     protected long getTrueSize() {
153         return byteSize;
154     }
155 
156     /**
157      * Returns the FITS extension type as stored by the XTENSION keyword in the FITS header.
158      * 
159      * @return The value used for the XTENSION keyword in the FITS header
160      * 
161      * @since  1.19
162      */
163     public final String getXtension() {
164         return extensionType;
165     }
166 
167     /**
168      * Returns the FITS element type as a Bitpux value.
169      * 
170      * @return The FITS Bitpix value for the type of primitive data element used by this data
171      * 
172      * @since  1.19
173      */
174     public final Bitpix getBitpix() {
175         return bitpix;
176     }
177 
178     /**
179      * Returns the size of the optional parameter space as stored by the PCOUNT keyword in the FITS header.
180      * 
181      * @return The element count of the optional parameter space accompanying the main data, as stored by the PCOUNT
182      *             header value.
183      * 
184      * @since  1.19
185      */
186     public final int getParameterCount() {
187         return pCount;
188     }
189 
190     /**
191      * Returns the number of repeated (data + parameter) groups in this data object
192      * 
193      * @return The number of repeated data + parameter blocks, as stored by the GCOUNT header value.
194      * 
195      * @since  1.19
196      */
197     public final int getGroupCount() {
198         return gCount;
199     }
200 
201     /**
202      * Returns the dimensionality of the data (if any), in Java array index order. That is, The value for NAXIS1 is the
203      * last value in the returned array
204      * 
205      * @return the regular dimensions of the data in Java index order (that is NAXIS1 is the last entry in the array),
206      *             or possibly <code>null</code> if no dimensions have been defined.
207      */
208     public final int[] getDimensions() {
209         return dims;
210     }
211 
212     @Override
213     public byte[] getData() throws FitsException {
214         byte[] bytes = (byte[]) super.getData();
215         if (bytes != null) {
216             return bytes;
217         }
218 
219         data = new byte[byteSize];
220         return data;
221     }
222 
223     @Override
224     protected void loadData(ArrayDataInput in) throws IOException {
225         data = new byte[byteSize];
226         in.readFully(data);
227     }
228 
229     @SuppressWarnings({"resource", "deprecation"})
230     @Override
231     public void write(ArrayDataOutput o) throws FitsException {
232         if (o != getRandomAccessInput()) {
233             ensureData();
234         }
235         try {
236             o.write(data);
237         } catch (IOException e) {
238             throw new FitsException("IO Error on unknown data write", e);
239         }
240         FitsUtil.pad(o, getTrueSize());
241     }
242 
243     @Override
244     @SuppressWarnings("deprecation")
245     public UndefinedHDU toHDU() {
246         Header h = new Header();
247         fillHeader(h);
248         return new UndefinedHDU(h, this);
249     }
250 }