Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: pixel spacing? #106

Closed
mdhe1248 opened this issue Sep 5, 2023 · 10 comments
Closed

Question: pixel spacing? #106

mdhe1248 opened this issue Sep 5, 2023 · 10 comments
Labels
question Further information is requested waiting on author

Comments

@mdhe1248
Copy link
Contributor

mdhe1248 commented Sep 5, 2023

Hi,
I would like to know how to update pixel spacing information (x, y, and z).
It seems that tifftag has XRESOLUTION and YRESOLUTION. I played with it, but the information is not being updated (when I check that in fiji).

Thanks,

@tlnagy
Copy link
Owner

tlnagy commented Sep 6, 2023

Hi @mdhe1248, how are you saving a new file after updating the XRESOLUTION and YRESOLUTION?

@mdhe1248
Copy link
Contributor Author

mdhe1248 commented Sep 8, 2023

Hi @tlnagy,
I simply used TiffImages.save("test1.tif", img)
My test script is this:

using Images, TiffImages
img0 = Gray.(zeros(10,10, 3))
img = TiffImages.DenseTaggedImage(img0)
ifds = img.ifds
[ifds[i][TiffImages.XRESOLUTION] = 100 for i in axes(ifds,1)]
[ifds[i][TiffImages.YRESOLUTION] = 100 for i in axes(ifds,1)]
#[ifds[i][TiffImages.RESOLUTIONUNIT] = 3 for i in axes(ifds,1)]
TiffImages.save("test1.tif", img)

Opening test1.tif file in Fiji throws error messages.

@tlnagy
Copy link
Owner

tlnagy commented Sep 18, 2023

Sorry for the delay, but it looks like the problem is that the XRESOLUTION and YRESOLUTION tags require a rational type:

The number of pixels per ResolutionUnit in the ImageWidth direction.

So if you want to have a final pixel width of 0.653 microns, then you can set the XRESOLUTION and YRESOLUTION to Rational{UInt32}(1e4/0.653) with ResolutionUnit = UInt8(3)1

img0 = Gray.(zeros(10,10, 3))
img = TiffImages.DenseTaggedImage(img0)
ifds = img.ifds

res = Rational{UInt32}(round(1e4/0.653, digits = 3))

[ifds[i][TiffImages.XRESOLUTION] = res for i in axes(ifds,1)]
[ifds[i][TiffImages.YRESOLUTION] = res for i in axes(ifds,1)]
[ifds[i][TiffImages.RESOLUTIONUNIT] = UInt8(3) for i in axes(ifds,1)]
tmpf = mktemp()
TiffImages.save(tmpf[2], img)

Opening it in FIJI using the bioformats plugin:

image

There could be a good argument that we should consider adding type checking for the core tags.

Footnotes

  1. TiffImages currently doesn't do any type checking of the tags so you need to make sure you're providing the correct types so it knows how to write it to disk.

@tlnagy tlnagy added question Further information is requested waiting on author labels Sep 18, 2023
@mdhe1248
Copy link
Contributor Author

Thank you, @tlnagy
This works nicely!

I have additional questions:
When I load the newly updated tiff file in Julia, resolution information in ifds seems to be lost. Would this be normal behavior?

using Images, TiffImages
 
img1 = Gray.(zeros(Float32, 10,10,10))
img1_tagged = TiffImages.DenseTaggedImage(img1) 
ifds1 = img1_tagged.ifds
 
res = Rational{UInt32}(round(1e4/0.653)) #resolution 
 
[ifd[TiffImages.XRESOLUTION] = res for ifd in ifds1]
[ifd[TiffImages.YRESOLUTION] = res for ifd in ifds1]
[ifd[TiffImages.RESOLUTIONUNIT] = UInt8(3) for ifd in ifds1]
TiffImages.save("test1.tif", img1_tagged)

## Load image and save it again 
img2 = TiffImages.load("test1.tif")
img2_tagged = TiffImages.DenseTaggedImage(img2) # Information loss.
TiffImages.save("test2.tif", img2_tagged) 

Also, will it be possible to add depth (z-axis) and time resolution information?

@tlnagy
Copy link
Owner

tlnagy commented Sep 18, 2023

When I load the newly updated tiff file in Julia, resolution information in ifds seems to be lost. Would this be normal behavior?

This is the expected behavior because you're creating a new TIFF image with this line:

img2_tagged = TiffImages.DenseTaggedImage(img2) # Information loss.

Why not just use img2?

Also, will it be possible to add depth (z-axis) and time resolution information?

TIFF doesn't have a standard way of handling Z and T information. You could use ImageJ's approach and write it to into a IMAGE_DESCRIPTION tag in the first IFD, something like this:

img0 = Gray.(zeros(UInt8, 10,10, 12))
img = TiffImages.DenseTaggedImage(img0)
ifds = img.ifds

res = Rational{UInt32}(round(1e4/0.653, digits = 3))

[ifds[i][TiffImages.XRESOLUTION] = res for i in axes(ifds,1)]
[ifds[i][TiffImages.YRESOLUTION] = res for i in axes(ifds,1)]
[ifds[i][TiffImages.RESOLUTIONUNIT] = UInt8(3) for i in axes(ifds,1)]

# only in the first IFD
ifds[1][TiffImages.IMAGEDESCRIPTION] = "ImageJ=1.51d
images=12
frames=3
slices=4
hyperstack=true
spacing=5.0
unit=um
finterval=0.2
axes=TZYX"

tmpf = mktemp()
TiffImages.save(tmpf[2], img)

image

My understanding is ImageJ's metadata processing is quite undocumented so playing around with the values and some googlefu will help you figure it all out.

@mdhe1248
Copy link
Contributor Author

Thank you so much! I will close this.

@tlnagy
Copy link
Owner

tlnagy commented Sep 19, 2023

Great! If you have a chance, do you mind writing this up as a small little example for the docs? I think it might be useful for others.

@mdhe1248
Copy link
Contributor Author

Sure, I will.
Would you like me to update the readme file (and pull request)? Or I can add comment here.

@tlnagy
Copy link
Owner

tlnagy commented Sep 19, 2023

I was thinking to have a short examples section here: https://tamasnagy.com/TiffImages.jl/dev/

You could open a PR to do that. Or if it's easier, you can post it here and I can do it.

@mdhe1248
Copy link
Contributor Author

Okay! I got this. I will open a PR when I am ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested waiting on author
Projects
None yet
Development

No branches or pull requests

2 participants