1 pixel size image reading one of the channels from czi file

Your place to discuss general handling of images and the CZI file format
Post Reply
user-6352
Posts: 1
Joined: Thu Jan 01, 1970 1:00 am

1 pixel size image reading one of the channels from czi file

Post by user-6352 »

Hi,

My code reads CZI file and extracts image from it. CZI file has multiple time points and three channels (blue, red and grayscale). Reading blue channel always produces 1px bmp for certain files with a single scene (I have other files with multiple scenes, and blue channel in those files is read correctly).

I create instance of ImageAccessor which reports non-zero byte size. But when I read it using method ImageAccessor.GetBitmapSource() I get back 1 pixel size image. This happens for blue channel only, other channels produce correct images when read using the same method.

If I open the same file with ZEN(blue) I see three channels. I'm out of ideas what I could be doing wrong.

Here is a code snippet:

Code: Select all

ImageDocument imageDocument = new ImageDocument();
imageDocument.Open("c:\file.czi");

string pixelType = imageDocument.PixelType.ToString();
int sizeS = imageDocument.Bounds.SizeS;
int sizeC = imageDocument.Bounds.SizeC;
int sizeT = imageDocument.Bounds.SizeT;
int sizeB = imageDocument.Bounds.SizeB;
int sizeZ = imageDocument.Bounds.SizeZ;
int width = imageDocument.Bounds.SizeX;
int height = imageDocument.Bounds.SizeY;

// split by channel - array count depends on number of time points and scenes and is a multiplication of these counts
ImageAccessorCollection c = imageDocument.CreateAccessor().Split3d(ImageDimension.C);
for (int i = 0; i < c.Count; i++)
{
      // split by time - array count is equal to channel count
      ImageAccessorCollection t = c[i].Split3d(ImageDimension.T);
      for (int j = 0; j < t.Count; j++)
      {
             // frame position on the image surface
             int channel = t[j].Bounds.StartC;
             int time = t[j].Bounds.StartT;
             int slice = t[j].Bounds.StartZ;
             int scene = t[j].Bounds.StartS;
             int block = t[j].Bounds.StartB;
             int ntime = t[j].Bounds.SizeT;
             int nscene = t[j].Bounds.SizeS;
             int nblock = t[j].Bounds.SizeB;
             // pixel type
             string pixel = t[j].PixelType.ToString();
             // frame dimensions
             int x = t[j].FirstPixelSubBlock.Bounds.StartX;
             int y = t[j].FirstPixelSubBlock.Bounds.StartY;
             int z = t[j].FirstPixelSubBlock.Bounds.StartZ;
             int w = t[j].FirstPixelSubBlock.Bounds.SizeX;
             int h = t[j].FirstPixelSubBlock.Bounds.SizeY;
             int d = t[j].FirstPixelSubBlock.Bounds.SizeZ;

             string dir = "c:\output";
             if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
             string filePath = Path.Combine(dir, string.Format("t{:D 6}_c{1 :D 2}_s{2 :D 2}_z{3 :D 2}.bmp", time, channel, scene, slice));
             using (var fileStream = new FileStream(filePath, FileMode.Create))
             {
                    ImageAccessor imageAccessor = t[j].CreateAccessor(new SubsetBounds { SizeX = w, SizeY = h, SizeZ = d, StartX = x, StartY = y, 
                            StartZ = z, SizeS = nscene, StartS = scene, SizeT = ntime, StartT = time });

                    var image = imageAccessor.GetBitmapSource();
                    BitmapEncoder encoder = new BmpBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(image));
                    encoder.Save(fileStream);
               }
      }
}
ZeissImageLib.dll version:
The attachment zeisslib.JPG is no longer available
Attachments
zeisslib.JPG
zeisslib.JPG (39.2 KiB) Viewed 5509 times
user-4
Posts: 398
Joined: Thu Jan 01, 1970 1:00 am

Post by user-4 »

Hello VictorB,

I am not so sure what your goal is but maybe these comments help.

As an example, we think of a 3-channel image with 10 time points.

tArray = imageDocument.CreateAccessor().Split3d(ImageDimension.T)
returns an array with size 3. So each of the 3 elements represent a channel. Each element has an array with its time points.
tPlaneArray = tArray[0].Split2d()
returns an array with size 10
bms = tPlaneArray[0].GetBitmapSource()
returns the bitmap of the first channel with the first timepoint.

cArray = imageDocument.CreateAccessor().Split3d(ImageDimension.C)
returns an array with size 10. So each of the 10 elements represent a time point. Each element has an array with its 3 channels.
cPlaneArray = cArray[0].Split2d()
returns an array with size 3
bms = planeArray[0].GetBitmapSource()
returns the bitmap of the first timepoint with the first channel.


iPlaneArray = imageDocument.CreateAccessor().Split2d()
returns an array with size 30
bms = iPlaneArray[0].GetBitmapSource()
returns the bitmap of the first timepoint with the first channel.

I hope this helps!
Melovianna Vivielei
Posts: 1
Joined: Tue Oct 31, 2023 10:27 am

Re: 1 pixel size image reading one of the channels from czi file

Post by Melovianna Vivielei »

You can open the CZI in Python using the aicsimageio tool, get the array data for the channel you want, find a single pixel value, and save it to a small image filegeometry dash lite.
You can open the CZI file in Fiji or ImageJ, split the channels, pick the channel you want to work with, make the area 1 pixel wide, and save the picture as a thumbnail.
To get the thumbnail in MATLAB, use bfopen() to read the CZI data, then index into the array to get a pixel from the channel matrix, resize it to a 1x1 size, and pass it to imwrite().
Post Reply