Skip to content

Commit

Permalink
Merge pull request #18 from marxt/geotiff-zip
Browse files Browse the repository at this point in the history
add zipped geotiff reading
  • Loading branch information
cnavacch authored Jul 3, 2023
2 parents 39fe087 + 186cb09 commit e25384f
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/veranda/raster/native/geotiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import struct
from zipfile import ZipFile
import numpy as np
from osgeo import gdal
from typing import List
Expand Down Expand Up @@ -128,8 +129,16 @@ def is_file_bigtiff(filepath) -> bool:
True if the given file is a BigTIFF, else False.
"""
with open(filepath, 'rb') as f:
header = f.read(4)
if '.zip' in filepath:
if filepath.startswith('/vsizip/'):
filepath = filepath[len('/vsizip/'):] # removes gdal virtual file system prefix to open w ZipFile
zip_filepath, inzip_filepath = filepath.split('.zip')
with ZipFile(zip_filepath + '.zip') as zip:
with zip.open(inzip_filepath[1:], 'r') as f:
header = f.read(4) # tests reads bytes not str, no need covert to bytearray
else:
with open(filepath, 'rb') as f:
header = f.read(4)
byteorder = {b'II': '<', b'MM': '>', b'EP': '<'}[header[:2]]
version = struct.unpack(byteorder + "H", header[2:4])[0]
return version == 43
Expand Down Expand Up @@ -171,7 +180,20 @@ def _open(self):
"""
if self.mode == 'r':
if not os.path.exists(self.filepath):
if '.zip' in self.filepath:
if self.filepath.startswith('/vsizip/'):
self.filepath = self.filepath[len('/vsizip/'):] # removes gdal virtual file system prefix if its there
zip_filepath, inzip_filepath = self.filepath.split('.zip')
zip_filepath += '.zip'
if not os.path.exists(zip_filepath): # checks zip file
err_msg = f"File '{zip_filepath}' does not exist."
raise FileNotFoundError(err_msg)
with ZipFile(zip_filepath) as zip:
if inzip_filepath[1:] not in zip.namelist(): # checks file in zip
err_msg = f"File '{self.filepath}' does not exist."
raise FileNotFoundError(err_msg)
self.filepath = '/vsizip/' + self.filepath # adds the gdal vsi prefix
elif not os.path.exists(self.filepath):
err_msg = f"File '{self.filepath}' does not exist."
raise FileNotFoundError(err_msg)
self.src = gdal.Open(self.filepath, gdal.GA_ReadOnly)
Expand Down Expand Up @@ -621,4 +643,4 @@ def _fill_vrt_file_per_band(et_root, filepath, bands, band_idx, entry_idx, n_col


if __name__ == '__main__':
pass
pass
25 changes: 25 additions & 0 deletions tests/raster/native/geotiff/test_geotiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np
from osgeo import gdal
from tempfile import mkdtemp
from zipfile import ZipFile

from veranda.raster.native.geotiff import GeoTiffFile

Expand Down Expand Up @@ -137,3 +138,27 @@ def test_sref(filepath):
sref_val = src.sref_wkt

assert sref_val == sref_ref


def test_read_one_band_zip(filepath):

data = np.ones((1, 100, 100), dtype=np.float32)

filename = os.path.basename(filepath)
zip_filepath = os.path.splitext(filepath)[0] + r'.zip'

with ZipFile(zip_filepath, 'w') as zip:
with GeoTiffFile(filepath, mode='w') as src:
src.write(data)
zip.write(filepath)

in_zip_filename = [name for name in zip.namelist() if name.endswith('.tif')][0]

read_filepath = os.path.join(zip_filepath, in_zip_filename)

with GeoTiffFile(read_filepath) as src:
ds = src.read()

np.testing.assert_array_equal(ds[1], data[0, :, :])

os.remove(zip_filepath)

0 comments on commit e25384f

Please sign in to comment.