rasterio "invalid dtype: 'bool'"
Yes, you can write a one bit raster with rasterio*.
You need to:
- write to a format that supports a 1bit dataset, such as GeoTIFF;
- ensure your numpy array is
np.uint8/ubyte
so rasterio doesnt raise theTypeError: invalid dtype: 'bool'
exception; and - pass the
NBITS=1
creation option to tell the underlying GDAL GeoTIFF driver to create a one bit file.
import numpy as np
import rasterio as rio
with rio.open('test_byte.tif') as src:
data = src.read()
profile = src.profile
with rio.open('test_bit.tif', 'w', nbits=1, **profile) as dst:
dst.write(data)
# If your array is not a byte dtype, you need to cast it as ubyte/uint8
# dst.write(data.astype(np.uint8))
$ ls -sh test_bit.tif
228K test_bit.tif
$ ls -sh test_byte.tif
1.8M test_byte.tif
$ gdalinfo test_bit.tif
Driver: GTiff/GeoTIFF
Files: test_bit.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x41 Type=Byte, ColorInterp=Palette
Image Structure Metadata:
NBITS=1
$ gdalinfo test_byte.tif
Driver: GTiff/GeoTIFF
Files: test_byte.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x5 Type=Byte, ColorInterp=Gray
* whether or not any software other than GDAL based can read it, I don't know...
If you call rasterio.dtypes.check_dtype(np.bool_)
you'll see that it's not a known dtype, because gdal doesn't support a true 1-bit dtype. GDT_Byte
is the smallest. The list that rasterio is checking against is:
dtype_fwd = {
0: None, # GDT_Unknown
1: ubyte, # GDT_Byte
2: uint16, # GDT_UInt16
3: int16, # GDT_Int16
4: uint32, # GDT_UInt32
5: int32, # GDT_Int32
6: float32, # GDT_Float32
7: float64, # GDT_Float64
8: complex_, # GDT_CInt16
9: complex_, # GDT_CInt32
10: complex64, # GDT_CFloat32
11: complex128} # GDT_CFloat64
uint8
and int8
are mapped to the ubyte
, as seen here:
https://github.com/mapbox/rasterio/blob/master/rasterio/dtypes.py#L29-L45