I have written a script that access cogs on GCS (google cloud storage), clip it with several vectors I have, and then uploading it back to GCS. I thought that the clipped image size should be the same/lower size after the clipping, however, I was surprise to see that even though the images are the same , It is now heavier.
for example. an image with size of 635.6 MB before the clipping, is 951 MB after.
Details about how I preformed the clipping:
- read data from GCS - vector data and each time one raster
- used rastio.mask.mask to mask the raster
- saved the raster locally with rasterio, using the following parameters:
with rasterio.open(savedir /'clipped.tif',
'w',
driver='cog',
height=img_arr.shape[1],
width=img_arr.shape[2],
count=25,
dtype=img_arr.dtype,
crs=crs_img,
nodata=None,
transform=transf) as dst:
for n in np.arange(0,number_of_bands):
dst.write(img[n,:,:],int(n+1))
dst.set_band_description(int(n+1), band_names[n])
- uploaded to GCS
the pixels of the two images (before and after) have the same values (where they are not clipped) . I thought maybe it has to do with image dtype/ saving as cog, but I need clue for understanding why I have this difference.
I have seen this post but I am not sure if it's the same on rasterio and if my solution will be just to add to "compress='lzw'" parameter, and how will it affect the images.
My goal is to understand what could increase the size of my GeoTIFFs
EDIT: Overviews based on user2856 comment, I have checked the overviews and I found out that the clipped image is saved with overview:
metadata = src.meta
# Get overviews
overviews = src.overviews(1) # the first band
# Print the metadata and overviews
print(metadata)
print(overviews)
>>>
{'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 3340, 'height': 3342, 'count': 22, 'crs': CRS.from_epsg(4326), 'transform': Affine(removed)}
[]
...
metadata = clipped.meta
# Get overviews
overviews = clipped.overviews(1) # first band
# Print the metadata and overviews
print(metadata)
print(overviews)
>>>
{'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 3340, 'height': 3342, 'count': 22, 'crs': CRS.from_epsg(4326), 'transform': Affine(removed)}
[2, 4, 8]
I saw that there are ways to remove overviews after openin the image, still looking for a ways to save the image without the overviews.
Edit 3: based on user2856 comments, I have checked the profile:
src.profile
>>>
{'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 3340, 'height': 3342, 'count': 22, 'crs': CRS.from_epsg(4326), 'transform': Affine(removed), 'blockxsize': 256, 'blockysize': 256, 'tiled': True, 'compress': 'lzw', 'interleave': 'pixel'}
clipped.profile
>>>
{'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 3340, 'height': 3342, 'count': 22, 'crs': CRS.from_epsg(4326), 'transform': Affine(removed), 'blockxsize': 512, 'blockysize': 512, 'tiled': True, 'compress': 'lzw', 'interleave': 'pixel'}
I have immediately realized that the difference between the clipped image to the original image is that the clipped image has different blocksize (512 instead of 256) I was trying to force the clipped image to have 256 when I write it.:
with rasterio.open(savedir /tiff_name,
'w',
driver='cog',
height=img.shape[1],
width=img.shape[2],
count=number_of_bands,
dtype=img.dtype,
crs=crs_img,
nodata=None, # change if data has nodata value,
blockxsize=256,
blockysize=256,
transform=transf) as dst:
for n in np.arange(0,number_of_bands):
dst.write(img[n,:,:],int(n+1))
dst.set_band_description(int(n+1), band_names[n])
But when I was checking the size of the forced blocksize, it still was too large (954MB...) and it seems like blocksize doesn't really change when I print profile
rio info filename.tif
andrio overview --ls filename.tif
orgdalinfo filename.tif
for both the input and output rasters.