Page 1 of 2

Rendering images per channel

PostPosted: Tue Jun 30, 2015 2:27 pm
by Charavay
Hi,

I'm developing a java application : it will display images from omero by using the BufferedImage class. The format of images can be jpeg, tiff, png, ome.tiff ... If a file contains several channels, I want to display one image per channel and an image with all channels.

I have developed the following code based on an example given on the Omero web site :
Code: Select all
                             // Read image
                            // See documentation at https://www.openmicroscopy.org/site/support/omero5.1/developers/Java.html
                            // https://www.openmicroscopy.org/community/viewtopic.php?f=6&t=7839
                           // Beans containing the bufferedImages to display
                            List<ImageBean> imageBeans = new ArrayList<>();
                            BufferedImage bufferedImage;
                            List<Image> images = containerPrx.getImages(Image.class.getName(), Arrays.asList(imageId), new ParametersI());

                            if (images.size() == 0) {
                                // Can not find image
                                bufferedImage = null;
                                ImageBean imageBean = new ImageBean(imageId, bufferedImage);
                                imageBeans.add(imageBean);
                            } else {

                                Image image = images.get(0);
                                ImageData imageData = new ImageData(image);
                                PixelsData pixelsData = imageData.getDefaultPixels();
                                // Number of z sections
                                int sizeZ = pixelsData.getSizeZ();
                                // Number of timepoints
                                int sizeT = pixelsData.getSizeT();
                                // Number of channels
                                int sizeC = pixelsData.getSizeC();

                                // Retrieve pixels
                                long pixelsId = pixelsData.getId();

                                RenderingEnginePrx proxy = serviceFactoryPrx.createRenderingEngine();
                                proxy.lookupPixels(pixelsId);
                                if (!(proxy.lookupRenderingDef(pixelsId))) {
                                    proxy.resetDefaultSettings(true);
                                    proxy.lookupRenderingDef(pixelsId);
                                }
                                proxy.load();

                                // Now can interact with the rendering engine.
                                // Render the image
                                PlaneDef pDef = new PlaneDef();
                                pDef.z = 0;
                                pDef.t = 0;
                                pDef.slice = omero.romio.XY.value;

                                // if the image contains several channels : create one bufferedimage for each channel
                                if (sizeC > 1) {
                                    for (int channelToActivate = 0; channelToActivate < sizeC; channelToActivate++) {
                                        for (int channel = 0; channel < sizeC; channel++) {
                                            if (channel == channelToActivate) {
                                                // Activate the channel
                                                proxy.setActive(channel, Boolean.valueOf(true));
                                            } else {
                                                // Desactivate the channel
                                                proxy.setActive(channel, Boolean.valueOf(false));
                                            }
                                        }
                                        // render the data compressed
                                        byte[] compressed = proxy.renderCompressed(pDef);
                                        //Create a buffered image
                                        ByteArrayInputStream stream = new ByteArrayInputStream(compressed);
                                        try {
                                            bufferedImage = ImageIO.read(stream);
                                            ImageBean imageBean = new ImageBean(imageId, bufferedImage);
                                            imageBeans.add(imageBean);

                                        } catch (IOException ex) {
                                            // Can not read the image (image not found or not supported format)
                                            bufferedImage = null;
                                            ImageBean imageBean = new ImageBean(omeroImageId, bufferedImage);
                                            imageBeans.add(imageBean);
                                        }
                                    }
                                }

                                // create a bufferedimage for all channels
                                for (int channel = 0; channel < sizeC; channel++) {
                                    // Activate the channel
                                    proxy.setActive(channel, Boolean.valueOf(true));
                                }
                                //render the data uncompressed.
                                //int[] uncompressed = proxy.renderAsPackedInt(pDef);
                                //render the data compressed
                                byte[] compressed = proxy.renderCompressed(pDef);

                                //Create a buffered image
                                ByteArrayInputStream stream = new ByteArrayInputStream(compressed);
                                try {
                                    bufferedImage = ImageIO.read(stream);
                                    ImageBean imageBean = new ImageBean(imageId, bufferedImage);
                                    imageBeans.add(imageBean);

                                } catch (IOException ex) {
                                    // Can not read the image (image not found or not supported format)
                                    bufferedImage = null;
                                    ImageBean imageBean = new ImageBean(imageId, bufferedImage);
                                    imageBeans.add(imageBean);
                                }

                                // Close
                                proxy.close();


With an ome.tiff file containg several channels, it works very well. But for a RGB tiff, the sizeC is equal to 3 and my application displays one image for the red channel, one for the green, one for the blue and one image with the three channels : in this case, I would like to display only one image with the three channels. How can I make it ?

Thank you in advance for your help

Céline

Re: Rendering images per channel

PostPosted: Tue Jun 30, 2015 10:20 pm
by rleigh
Can you special-case this with, for example:

Code: Select all
if (pixelsData.isRGB()) {
  // The image is RGB data; render a single image
  int nSubChannels = pixelsData.getRGBChannelCount();
} else {
  // The image is separate planes; render separately.
}

Re: Rendering images per channel

PostPosted: Wed Jul 01, 2015 6:57 am
by Charavay
Thank you for your answer.
But the PixelsData class that I use (pojos.PixelsData ; http://downloads.openmicroscopy.org/omero/5.1.2/api/pojos/PixelsData.html) don't have these methods. Is there another way to test this ?

Céline

PS : the classes I use are :
import omero.model.Image;
import omero.romio.PlaneDef;
import omero.sys.ParametersI;
import pojos.ImageData;
import pojos.PixelsData;

Re: Rendering images per channel

PostPosted: Wed Jul 01, 2015 8:18 pm
by jburel
Dear Celine
There is the getFormat() method on pojos.ImageData that could help you determining if the image is a graphics image or not
e.g. a jpg image will return JPEG

We could certainly add a isGraphics method to the imageData class.

Cheers

Jmarie

Re: Rendering images per channel

PostPosted: Thu Jul 02, 2015 7:14 am
by Charavay
Dear Jmarie

Thank you for your answer.
I have tried your solution but when I call the getFormat() on pojos.ImageData, the following exception is thrown :
omero.UnloadedEntityException: Object unloaded:omero.model.FormatI@5170bcf4

Do you have any idea ?

Thank you in advance for your help

Céline

Re: Rendering images per channel

PostPosted: Thu Jul 02, 2015 8:10 am
by jburel
This means that the call used to retrieve the information did not load that part of the graph.
Which method do you use to load the images?
If you access the image from the pixelsData object, the information about the image will most likely not be loaded.

Cheers
Jmarie

Re: Rendering images per channel

PostPosted: Thu Jul 02, 2015 8:32 am
by Charavay
I load the image like that :
Code: Select all
List<Image> images = containerPrx.getImages(Image.class.getName(), Arrays.asList(imageId), new ParametersI());
Image image = images.get(0);
ImageData imageData = new ImageData(image);
String format = imageData.getFormat();
PixelsData pixelsData = imageData.getDefaultPixels();


> If you access the image from the pixelsData object, the information about the image will most likely not be loaded

I'm not sure to understand your explanation : in my code, I retrieve the imageData from the image object. Do you think it could be another way to load my image in order to have the format ?

Best regards

Céline

Re: Rendering images per channel

PostPosted: Thu Jul 02, 2015 3:11 pm
by jburel
I had a look at the method you are using to retrieve the image.
The format is not loaded. I will open a PR to fix that.

How you get the imageID? by first browsing the data tree? i.e.
* load the dataset using the loadContainerHierarchy method and access the images in the dataset
the image returned using that method has the format object loaded.

Cheers
jmarie

Re: Rendering images per channel

PostPosted: Fri Jul 03, 2015 6:29 am
by Charavay
Hi Jmarie

> How you get the imageID? by first browsing the data tree?

The user of my java application gives the imageID thanks to a CSV file. So I don't browse the data tree.

> * load the dataset using the loadContainerHierarchy method and access the images in the dataset
> the image returned using that method has the format object loaded.

As I don't know the dataset id it is not possible for me to load it.

> I had a look at the method you are using to retrieve the image.
> The format is not loaded. I will open a PR to fix that.

Ok. Thank you.

Céline

Re: Rendering images per channel

PostPosted: Fri Jul 03, 2015 9:35 am
by jburel
Hi Celine

In that case, you can, for the time being, retrieve the value of the format via another call
Code: Select all
List<Image> images = containerPrx.getImages(Image.class.getName(), Arrays.asList(imageId), new ParametersI());
Image image = images.get(0);
//extra call
Format f = (Format) queryServicePrx.get(Format.class.getName(), img.getFormat().getId().getValue());
if (f.getValue() != null) {
  String v = f.getValue().getValue();
}
ImageData imageData = new ImageData(image);
PixelsData pixelsData = imageData.getDefaultPixels();


This should give you the format as a string and you can check if it is jpeg etc.

Cheers
jmarie