Re: Image header - 256 bytes out
Posted by
Frederic V. Hessman on
Aug 06, 2010; 1:23pm
URL: http://imagej.273.s1.nabble.com/Image-header-256-bytes-out-tp3687288p3687294.html
The simplest thing might be to translate your files into FITS, which
has a very simple but rich keyword-value functionality (and which
ImageJ can process: our astronomical plugins even use present and
create new content).
Rick
On 6 Aug 2010, at 12:24, Neil Thomson wrote:
> Dear list
>
> I'm writing (or trying) a plugin to import a proprietary medical
> image format. There is no trouble importing the image proper, but
> I'm having problems reading some of the header information, which
> contains demographic and image information as "keys" and "values".
> The structure of the header is as follows:
>
> 1. 10 bytes of preamble, which includes number of keys
> 2. Keys and value-offsets (up to the number obtained above) in
> chunks of 6 bytes (2 for key number, 1 for data type, 1 unused and 2
> for the byte offset of the value).
> 3. Values of keys (The size is determined by type or, for strings,
> by a hand-typed look-up table referenced to the key number)
> 4. Image
>
> In my plugin I read to the number of keys. I can then loop to query
> the 6 bytes key/offset block to get the value offset, use a lookup
> table to get more information about the key. I then add the key and
> value to the image info (with the later intention of doing something
> useful, like set dimensions). Loop until reaching the last value.
>
> This works for some keys and not for others. Many values are
> strings, so I can read the whole header into IJ.log and inspect it
> for readable characters. I have found that when the offset reported
> (in the 6 byte block) is incorrect, it is always by 256 bytes. It
> seems very odd to me that when it's wrong it's by the same amount
> and can't be random.
>
> I must be doing something wrong and would be grateful for any help
> with this. Here are a couple of code snippets that demonstrated the
> offset reported by some keys being 256 bytes away from the values as
> read in as a string from the header:
>
> ------------------------------------------------
> private boolean littleEndian = false;
> private int location = 0, offset = 0;
> private static final int imageOffset = 2048;
>
> BufferedInputStream inputStream;
> ...
>
> inputstream.read(header, 0, imageOffset);
>
> String hdr = getString(6) + "\n";
> IJ.log(hdr); // says adac01
> short labels = getShort();
> IJ.log(Integer.toString(labels)); // Number of labels in header
> IJ.log(Integer.toString(getByte())); // Number of sub-headers
> IJ.log(Integer.toString(getByte())); // Unused byte
> // Should have read 10 bytes
>
> offset = location;
>
> // Test header output 20 chars at a time
> for (int i=0; i<1956; i++){
> location=i;
> IJ.log(""+i + ": " + getString(20));
> }
> location = offset;
>
> for (short i = 0; i < labels; i++) {
> getKeys();
> IJ.log("Key: " + keynum + " Type: " + datTyp + " offset: " +
> fieldOffset + "\n");
> }
> .......
> void getKeys() throws IOException {
> keynum = getShort();
> datTyp = getByte();
> unused = getByte();
> fieldOffset = getShort();
> }
>
> String getString(int length) throws IOException {
> byte[] buf = new byte[length];
> System.arraycopy(header, location, buf, 0, length);
> location += length;
> return new String(buf);
> }
>
> byte getByte() throws IOException {
> byte b = header[location];
> ++location;
> return b;
> }
>
> short getShort() throws IOException {
> byte b0 = getByte();
> byte b1 = getByte();
> if (littleEndian) {
> return (short) ((b1 << 8) + b0);
> } else {
> return (short)((b0 << 8) + b1);
> }
> }
>
> ------------------------------------
>
> Many thanks in advance, Neil