Login  Register

Re: creating an ImagePlus from an InputStream or a byte[]

Posted by ctrueden on Dec 12, 2007; 7:05pm
URL: http://imagej.273.s1.nabble.com/creating-an-ImagePlus-from-an-InputStream-or-a-byte-tp3697788p3697793.html

Hi Johannes,

If your byte[] is a raw pixels block of 8-bit grayscale data, you can
use the ByteProcessor constructor:

public ByteProcessor(int width, int height, byte[] pixels,
java.awt.image.ColorModel cm)

However, if as you say your byte[] is a direct buffer from a GIF, PNG,
JPEG, BMP, or some other format, it is a bit more complicated. Three
possible ways are: 1) javax.imageio.ImageIO; 2) the ImageJ API; or 3)
Bio-Formats.

1) Using ImageIO is probably your easiest bet, assuming the formats
you need to support are limited to the common
(non-discipline-specific) single-plane image formats: JPEG, PNG, GIF,
BMP and TIFF.

BufferedImage img = ImageIO.read(new ByteArrayInputStream(myBytes));
ImagePlus imp = new ImagePlus(title, img);

But I don't think this approach will work for TIFF stacks, and more
exotic life sciences formats are right out.

2) ImageJ has separate logic for each format, which you could invoke
directly on a format-by-format basis.

For example, for TIFF, you could try the following:

TiffDecoder td = new TiffDecoder(new ByteArrayInputStream(myBytes), name);
FileInfo[] info = td.getTiffInfo();
ImagePlus imp = null;
if (info.length>1) { // try to open as stack
  imp = openTiffStack(info);
  if (imp!=null) return imp;
}
FileOpener fo = new FileOpener(info[0]);
imp = fo.open(false);
return imp;

I stole that code from ij.io.Opener, but adapted the TiffDecoder to
use the InputStream constructor instead. I haven't tested it, so do
not know for certain whether it will work.

With this approach, you would need to similarly adapt each individual
format you want to support.

There may also be a simpler "pure ImageJ" way of which I am ignorant.

3) Another option would be to use Bio-Formats, since it handles a
large number of multi-plane file formats and has a unified API to
avoid the need for format-specific logic.

In the process of whipping up some sample code, though, I realized the
latest Bio-Formats release does not actually have an API for feeding
in a byte array or InputStream directly to a reader, though 99% of the
logic to do it was there internally. So we have cooked up a
pre-release capable of doing so and placed it at:

http://skyking.microscopy.wisc.edu/curtis/jar/loci_tools.jar

And here is a code fragment:

import loci.formats.*;
import loci.plugins.Util;
...
IRandomAccess ira = new RABytes(myBytes);
// map the file to an id
String id = "myBytes"; // use whatever name you like here
Location.mapFile(id, ira);
// read the image planes
ImageReader r = new ImageReader();
r.setId(id);
int w = r.getSizeX();
int h = r.getSizeY();
int num = r.getImageCount();
ImageStack stack = new ImageStack(w, h);
for (int i=0; i<num; i++) {
  ImageProcessor ip = Util.openProcessor(r, i);
  stack.addSlice(id + ":" + i, ip);
}
ImagePlus imp = new ImagePlus(id, stack);

HTH,
Curtis

On Dec 12, 2007 8:35 AM, Johannes Hermen <[hidden email]> wrote:

> ImageJ Interest Group <[hidden email]> wrote on 12.12.2007 12:44:55:
>
> > > Does anybody knows a solution on how to create an ImagePlus
> > > directly from
> > > a byte[] or an Inputstream.
> > > The thing is that we want to show Images stored in a database blob
> > > without
> > > creating a tempfile before.
> > >
> > > It would be really nice to have something like this new ImagePlus
> > > (byte[])
> > > or new ImagePlus(InputStream)
> > Hello Johannes
> >
> > Try this:
> >
> > InputStream myStream = ...;
> > ObjectInputStream ois = new ObjectInputStream(myStream);
> > ImagePlus ip = (ImagePlus) ois.readObject();
>
> That would only work if the byte[] is a serialized ImagePlus, but our
> byte[] is an gif/png/jpg/bmp etc...
>
>
> -----------------------------------------------------------------
> Johannes Hermen  -  Ingenieur de Recherche
> [hidden email]
> -----------------------------------------------------------------
> CRP Henri Tudor  http://www.santec.tudor.lu
> 29, Avenue John F. Kennedy
> L-1855 Luxembourg
> -----------------------------------------------------------------
>