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 }