I have a GeoTIFF (RGB) 8-bit per channel file that was classified to four classes. Theoretically I could save the file as a 3-bit and make the file significantly smaller. For my application files size is very important. Yet from what I can tell from the GDAL documentation http://www.gdal.org/frmt_gtiff.html I think am out of luck. Since each pixel is a stand-alone, aggregating the pixels and converting them into a polygon does not seem it would do the trick. For my processes I have been using GDAL API with Python 3.5. Does anyone have any thoughts on how to take advantage of the classified data to convert to s smaller file size?
2 Answers
GDAL seems perfectly happy with non-8-bit values for pixels by creating with the NBITS option.
As a test, I created a 1000x1000 raster with integer values from 1 to 4 in R and saved as TIFFs with different NBITS values (and used COMPRESS=NONE so that the file size wasn't masked by a compression algorithm):
writeRaster(d,datatype="INT1U","d8.tiff",options=c("NBITS=8","COMPRESS=NONE"),overwrite=TRUE)
writeRaster(d,datatype="INT1U","d1.tiff",options=c("NBITS=1","COMPRESS=NONE"),overwrite=TRUE)
writeRaster(d,datatype="INT1U","d2.tiff",options=c("NBITS=2","COMPRESS=NONE"),overwrite=TRUE)
writeRaster(d,datatype="INT1U","d3.tiff",options=c("NBITS=3","COMPRESS=NONE"),overwrite=TRUE)
The sizes of the files came out like this:
124 d1.tif
248 d2.tif
368 d3.tif
980 d8.tif
The one-bit file is clearly not going to be able to store enough info for four categories, but I include it for completeness. The two-bit file should be able to store four categories but I think GDAL is reserving a value for "NODATA" and so the two-bit file doesn't work when loaded into QGIS (I only see three categories). This might be fixable with more options relating to NODATA.
So the 3-bit file, at 368kbytes, is a third the size of the 8 bit file, at 980kbytes, as expected. Further size savings can be made by using a COMPRESS option, but these savings will be much larger in the 8 bit files since there's five or six bits of entropy to play with in those cases.
You can make your image significantly smaller by converting it into a single-band paletted TIFF with rgb2pct.py. Moreover, you can continue and reduce the bit depth of the single band TIFF with gdal_translate by using the GeoTIFF creation option "nbits" as documented in http://www.gdal.org/frmt_gtiff.html. Using compression will reduce the file size further.
I made a simple test with the following commands
rgb2pct test.tif test_palette.tif
gdal_translate -of GTiff -co nbits=3 test_palette.tif test_palette_3bit.tif
gdal_translate -of GTiff -co compress=DEFLATE test_palette_3bit.tif test_palette_3bit_deflate.tif
Here are the file sizes of the original file and the three processed files
test.tif 10 264 936
test_palette.tif 3 422 122
test_palette_3bit.tif 1 282 834
test_palette_3bit_deflate.tif 113 183