Login  Register

Re: Image header - 256 bytes out

Posted by Michael Schmid on Aug 06, 2010; 6:54pm
URL: http://imagej.273.s1.nabble.com/Image-header-256-bytes-out-tp3687288p3687292.html

Hi Neil,

it is not a matter of typecast, it is cast to int anyhow: in Java, there
are no byte or short operations like '+' or '<<'.
It rather is a problem of Java having only signed data types. E.g., byte
0xff is interpreted as -1, and converted to int -1 = 0xffffffff.

Thus, at least the lower byte needs an '&' operation to mask out the lower
8 bits:
   (b1 << 8) + (b0 & 0xff);
You don't need to mask out the upper byte because the typecast to short
will discard the higher bytes.

Michael
_________________________________________________________________

On Fri, August 6, 2010 19:13, Andreas Maier wrote:

> Hi Neil,
>
> I think writing a Plugin to read your fileformat is definitely the right
> way to go. If your plugin is extends ImagePlus you can even add it to
> the HandleExtraFileTypes.java in your plugin directory. Then your ImageJ
> will become fully compatible with your format and you can even use the
> drag and drop functionality in ImageJ.
>
> I completely agree with Joachim Wesner's comment. You should cast to
> short before you shift your bits:
>
>     short getShort() throws IOException {
>       byte b0 = getByte();
>       byte b1 = getByte();
>       if (littleEndian) {
>         return  ((((short)b1)<<  8) + b0);
>       } else {
>         return ((((short)b0)<<  8) + b1);
>       }
>     }
>
> Another thing which may be wrong, is that your current index in your
> header points to the wrong position for some reason. Without example
> files and the complete code, it's difficult to find the issue.
>
> Best,
>
> Andreas
>
> Am 8/6/2010 7:01 AM, schrieb Boris Epstein:
>>
>>
>> On 08/06/2010 06:24 AM, 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
>>
>> Neil,
>>
>> I don't know about your particular format but have you considered
>> converting this data into NRRD:
>>
>> http://teem.sourceforge.net/nrrd/
>>
>> Seems like a nice popular open source graphics format that from what
>> you are saying should handle all you are trying to handle leaving room
>> for further enhancement is necessary.
>>
>> Boris.
>>
>>
>> The information in this e-mail is intended only for the person to whom
>> it is
>> addressed. If you believe this e-mail was sent to you in error and the
>> e-mail
>> contains patient information, please contact the Partners Compliance
>> HelpLine at
>> http://www.partners.org/complianceline . If the e-mail was sent to you
>> in error
>> but does not contain patient information, please contact the sender
>> and properly
>> dispose of the e-mail.
>
>
> --
> Dr.-Ing. Andreas Maier
> Stanford University
> Department of Radiology
> The Lucas Center for Imaging
> Mail Code 5488, Route 8
> Stanford, CA  94305
> http://med.stanford.edu/profiles/Andreas_Maier/
>