# How to make image3d smaller? Is ImageResolution useful?

I want to make the output of Image3D much smaller. For example

test = Image3D[
Table[Sin[x + y + z], {x, 1, 100}, {y, 1, 100}, {z, 1, 100}]]


It outputs

We can look at how much memory this image takes

ByteCount[test]/1024/1024.


it takes 7.62976 MB

If I want to generate many such kind of image3D in a notebook for studying. The notebook will become very large.

I notice in the "interactive example" section of "ref/Image3DSlices", there is a delicate image of a human head (NMR??). Which only takes up 0.9 MB.

So I was wondering how to make the output of Image3D smaller?

Update

I also want to know what is the usage of ImageResolution in Image3D? I tried it, but I didn't see any difference after using it.

• "Real32" as the second argument reduces the image size by a factor of two. Feb 7, 2016 at 5:57
• @bbgodfrey Thank you bbgodfrey. That works. But the size reduction is not enough. Feb 7, 2016 at 8:25
• – user9660
Feb 7, 2016 at 8:52
• Base on the comment by @Louis and my own comment above, small = ImportString[ExportString[test, "JPEG"], "JPEG"] returns the plot in the figure but at a ByteCount of 422720. Feb 7, 2016 at 15:07
• However, although the image returned by the code in my last comment looks the same as the image in the question, it no longer is 3D and so cannot be processed by such functions as Image3DSlices. So, whether this is a good solution depends on the use to which the compressed image is to be put. Feb 7, 2016 at 15:15

There are several ways to reduce the size of the image. Perhaps the simplest is to reduce the number of pixels when it is generated. For example, if you do:

test = Image3D[Table[Sin[x + y + z],
{x, 1, 100, 3}, {y, 1, 100, 3}, {z, 1, 100, 3}]]


Then you get an image that looks much the same and the memory is 0.3 MB

ByteCount[test]/1024/1024 // N


If you want to make it smaller after the initial image generation (or to make an imported image smaller) then you can downsample:

test = Image3D[Table[Sin[x + y + z], {x, 1, 100}, {y, 1, 100}, {z, 1, 100}]];
test2 = Image3D[Downsample[ImageData[test], 3]]


Again, this is about 0.3 MB.

Both of these decrease the resolution of the image. If your data is real-valued, then you can also reduce the size by storing the image data as integers. For example, the CT scan of the head is a 100x100x100 image that takes up only 1 MB (instead of 7). This is accomplished by storing the image as integers instead of reals. This can be done by changing the second argument of the Image3D:

q = Image3D[test, "Byte"]


This is now about 1 MB.

• Hi, Bill S. Thank you very much for your answer. But I think your approach maybe not what I want. Take the CT human head as an example, I think your method probably can not achieve that effect. I think the head should be generated in high detail first, and then efficiently rasterized and adjust resolution instead of directly deleting data point. I tried your method on my data, it seems not producing good looking quality. Feb 7, 2016 at 16:35
• I reconsidered and realized that I actually don't know the basic of rasterization, I am not familiar with image compression, wish you could correct me if I am wrong : ) Feb 7, 2016 at 16:46
• I notice in the human head example, the size is 100, that means if it were simply array of pixels, it should be 7MB, am I right? Feb 7, 2016 at 16:54
• It would be pretty common to apply some kind of low pass filter (maybe Gaussian) to the image before downsampling. This might help a little, but you can't expect miracles. Reducing the resolution of the image will make it look worse. Feb 7, 2016 at 16:55
• Oh, Byte ! This is useful. Thank you bill s Feb 8, 2016 at 0:54