1
2
3
4
5
6
7 package org.astrogrid.fits;
8
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.util.Hashtable;
12 import org.astrogrid.common.myspace.SourceResolver;
13 import org.astrogrid.log.Log;
14
15 /***
16 * A set of routines for handling a fits image
17 *
18 * FITS images are binary representations of tables or pixel images, and are
19 * well known in the astronomical community (in 2003!). They consist of
20 * a number of 'lines' of 80 characters of ASCII keyword/value pairs, then
21 * the binary data itself.
22 *
23 * (Should say more or give reference)
24 *
25 * NB the image might be remote, eg
26 * http or ftp, so we can't deal with instances of File
27 */
28 public class FitsImage
29 {
30 String fileLocation;
31 int dataOffset = -1;
32 Hashtable header = null;
33
34 public FitsImage(String givenLocation) throws IOException
35 {
36 this.fileLocation = givenLocation;
37 getInputStream();
38 }
39
40 /***
41 * resolves access to the fits image.
42 */
43 public InputStream getInputStream() throws IOException
44 {
45
46 Log.trace("Resolving access to image '"+fileLocation+"'..");
47 return SourceResolver.resolveInputStream(fileLocation);
48
49 }
50
51 /***
52 * Loads the header into a set of key/value pairs, and notes the
53 * point at the beginning of the data.
54 */
55 public void loadHeader() throws IOException
56 {
57 Log.trace("Loading image header...");
58 InputStream in = getInputStream();
59 header = new Hashtable();
60
61
62 byte[] block = new byte[80];
63
64 String line = "";
65 int lineNum = 0;
66 int totBytesRead = 0;
67
68 while (!line.toUpperCase().startsWith("END") && !line.toUpperCase().startsWith("HISTORY AIP"))
69 {
70 lineNum++;
71
72 int bytesRead = in.read(block);
73 int lineBytesRead = bytesRead;
74
75
76
77 while ((lineBytesRead <80) && (bytesRead != -1))
78 {
79 bytesRead = in.read(block, lineBytesRead, 80-lineBytesRead);
80 lineBytesRead = lineBytesRead + bytesRead;
81 }
82 totBytesRead = totBytesRead + lineBytesRead;
83
84
85
86
87
88
89
90
91
92 for (int i=0;i<block.length;i++)
93 {
94 if ( ((block[i] >128) || (block[i] <32)) && (block[i] != 0) )
95 {
96 String msg="Binary data encountered before header END in image "+fileLocation+"\n";
97 msg=msg+new String(block)+"\n";
98 for (int j=0;j<block.length;j++) msg=msg+"["+block[j]+"] ";
99
100 throw new IOException(msg);
101 }
102 }
103
104 line = new String(block);
105 Log.trace(line);
106
107 int equalsPos = line.indexOf('=');
108 if (equalsPos > -1)
109 {
110 String key = line.substring(0,equalsPos).trim().toUpperCase();
111 String value = line.substring(equalsPos+1).trim();
112
113
114 if (value.startsWith("'"))
115 {
116 if ((value.indexOf("'",1) > -1) && (value.indexOf("'") > 1))
117 {
118 value = value.substring(1,value.indexOf("'",1)-1);
119 }
120 }
121 else
122 {
123
124
125 int commentPos = value.indexOf('/');
126 if (commentPos>-1)
127 {
128 value = value.substring(0,commentPos).trim();
129 }
130 }
131
132
133 header.put(key, value);
134 }
135
136 }
137
138 if (!line.toUpperCase().startsWith("HISTORY AIP"))
139 {
140
141 dataOffset = totBytesRead;
142 }
143 }
144
145 /***
146 * Returns the value in the header corresponding to the given key
147 */
148 public String getHeaderValue(String keyword)
149 {
150 return (String) header.get(keyword);
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165