Reading a binary file

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Reading a binary file

Kb Pru
Hello All,
  I am new to writing plugins and am trying to read a raw file in through a
plugin. I have several questions:

1. Each file I am reading is 105906380 bytes long. It takes a while to read
the file. How can I speed it up? I am currently reading the file slice by
slice via these commands:

for (int s=0;s<slices;s++){
   img.setSlice(s+1);
   IJ.showProgress( (double) s / slices);
   pixels = (short[]) img.getProcessor().getPixels();
   for(int row=0;row<height;row++){
        offset = (row*width);
        for (int col=0;col<width;col++){
           pixels[offset+col]=swapshort(input.readShort());
        }
   }
}

2. I would like to scale the pixel value linearly. However when I change one
line line from the above snipped to :
pixels[offset+col]=swapshort(input.readShort()-16383);
I get an error message "Incompatible type for method. Explicit cast needed
to convert int to short.". How do I operate on pixel element values.

Many thanks.

KB
Reply | Threaded
Open this post in threaded view
|

Re: Reading a binary file

Albert Cardona
Kb Pru wrote:
>   pixels[offset+col]=swapshort(input.readShort());
>  


Reading pixel-by-pixel may take forever unless you use a buffered input
stream.


> 2. I would like to scale the pixel value linearly. However when I change one
> line line from the above snipped to :
> pixels[offset+col]=swapshort(input.readShort()-16383);
> I get an error message "Incompatible type for method. Explicit cast needed
> to convert int to short.". How do I operate on pixel element values.
>  


In java, arithmetic operations go up to int or to double. In your case
to int.
So cast the result back to short:

pixels[offset+col]= swapshort(  (short) (input.readShort()-16383) );


Overall, you may be better off using LOCI Bioformats, which you may extend
for your particular file format and which have virtual stack (read:
dynamic loading)
capabilities.

Albert

--
Albert Cardona
http://albert.rierol.net
Reply | Threaded
Open this post in threaded view
|

Re: Reading a binary file

Kb Pru
Thanks. With
pixels[offset+col]= swapshort(  (short) (input.readShort()-16383) );
there is no error, but I still do not see a subtraction in the displayed
image values.

Can you please point me to some documentation about buffered input stream
you talk about? I did mention I am new to javascript! :)

My entire code is as follows:

import java.io.*;
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;
import ij.io.*;
import ij.measure.*;
import java.lang.*;

public class Open_V3d implements PlugIn {
    public void run(String arg) {
        String name;String directory = "";

        // Open dialog to pick a v3d file
        OpenDialog od = new OpenDialog("Load V3d file...",arg);
        name = od.getFileName();
        directory = od.getDirectory();

        if (name == null) return;
        IJ.showStatus(directory+name);

        // Open v3d file
        try {
            FileInputStream fs    = new FileInputStream(directory+name);
            DataInputStream input = new DataInputStream( new
BufferedInputStream(fs) ) ;

            int width,height,slices,element,offset;
            short pixels[];
            long filesize=0,StartReadPos=0;
            short pixelscaling = 16383;

            //Skip first 40 bytes to read the dimensions
            input.skipBytes(40);
            width  = swap(input.readInt());
            height = swap(input.readInt());
            slices = swap(input.readInt());

            //Calculate where we have to start reading the file for data
            filesize = fs.getChannel().size();
            StartReadPos = filesize - (width*height*slices*2)-(40+(3*4));
            input.skipBytes((int)StartReadPos);

            //IJ.showMessage("OpenV3d",""+StartReadPos);
            ImagePlus img =
IJ.createImage("v3dFile","16-bit",width,height,slices);

            // Reading pixel by pixel. Probably not very efficient. Change
later.
            for (int s=0;s<slices;s++){
                img.setSlice(s+1);
                IJ.showProgress( (double) s / slices);
                pixels = (short[]) img.getProcessor().getPixels();
                for(int row=0;row<height;row++){
                    offset = (row*width);
                    for (int col=0;col<width;col++){

//pixels[offset+col]=swapshort(input.readShort()-pixelscaling);
                        pixels[offset+col]=swapshort((short)
(input.readShort()-pixelscaling) );
                    }
                }
            }
            img.show();
            input.close();
        }
        catch (IOException e) { IJ.write("FileLoader: " + e.getMessage()); }
    }

    public static int swap (int value){
        int b1 = (value >> 0 ) & 0xff;
        int b2 = (value >> 8 ) & 0xff;
        int b3 = (value >> 16) & 0xff;
        int b4 = (value >> 24) & 0xff;

        return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
    }

    public static short swapshort (short value){
        int b1 = value & 0xff;
        int b2 = (value >> 8) & 0xff;
        return (short) (b1 << 8 | b2<<0);
    }
}


On Tue, Jun 2, 2009 at 9:46 AM, Albert Cardona <[hidden email]>wrote:

> Kb Pru wrote:
>
>>           pixels[offset+col]=swapshort(input.readShort());
>>
>>
>
>
> Reading pixel-by-pixel may take forever unless you use a buffered input
> stream.
>
>
>  2. I would like to scale the pixel value linearly. However when I change
>> one
>> line line from the above snipped to :
>> pixels[offset+col]=swapshort(input.readShort()-16383);
>> I get an error message "Incompatible type for method. Explicit cast needed
>> to convert int to short.". How do I operate on pixel element values.
>>
>>
>
>
> In java, arithmetic operations go up to int or to double. In your case to
> int.
> So cast the result back to short:
>
> pixels[offset+col]= swapshort(  (short) (input.readShort()-16383) );
>
>
> Overall, you may be better off using LOCI Bioformats, which you may extend
> for your particular file format and which have virtual stack (read: dynamic
> loading)
> capabilities.
>
> Albert
>
> --
> Albert Cardona
> http://albert.rierol.net
>
Reply | Threaded
Open this post in threaded view
|

Re: Reading a binary file

Michael Schmid
On 2 Jun 2009, at 16:20, KB wrote:
> Can you please point me to some documentation about buffered input  
> stream
> you talk about? I did mention I am new to javascript! :)
>


Hava a look at java.sun.com; there you find all java documentation,  
e.g.,

http://java.sun.com/j2se/1.4.2/docs/api/java/io/InputStream.html

DataInputStream has the advantage that it reads signed as well as  
unsigned short, but the disadvantage that the overhead of a method  
call for each short makes it significantly slower than methods that  
return arrays.

Your current code extracts bytes from the short data to swap the bytes.
It would be faster to read the bytes for a row of pixels or the whole  
image into an array (InputStream can fill a byte buffer) and then  
compose the shorts from the bytes array.

Michael
Reply | Threaded
Open this post in threaded view
|

Re: Reading a binary file

Fernando Sales
In reply to this post by Kb Pru
Kb,

the easiest way in my option is to use the Import > Raw available into IJ.
If you are intended to use it inside of a plugin, you can directly
instanciate the Import class and call its execution from your code.
Another optiion is to use the "Record Macro" resource and open one image
using the File > Import > Raw command and after this, get the plugin or
macro code from this operation.
I hope this helps you.
Best regards,
Fernando

On Tue, Jun 2, 2009 at 10:26 AM, Kb Pru <[hidden email]> wrote:

> Hello All,
>  I am new to writing plugins and am trying to read a raw file in through a
> plugin. I have several questions:
>
> 1. Each file I am reading is 105906380 bytes long. It takes a while to read
> the file. How can I speed it up? I am currently reading the file slice by
> slice via these commands:
>
> for (int s=0;s<slices;s++){
>   img.setSlice(s+1);
>   IJ.showProgress( (double) s / slices);
>   pixels = (short[]) img.getProcessor().getPixels();
>   for(int row=0;row<height;row++){
>        offset = (row*width);
>        for (int col=0;col<width;col++){
>           pixels[offset+col]=swapshort(input.readShort());
>        }
>   }
> }
>
> 2. I would like to scale the pixel value linearly. However when I change
> one
> line line from the above snipped to :
> pixels[offset+col]=swapshort(input.readShort()-16383);
> I get an error message "Incompatible type for method. Explicit cast needed
> to convert int to short.". How do I operate on pixel element values.
>
> Many thanks.
>
> KB
>