diff --git a/CHANGES.txt b/CHANGES.txt index 0f63f7f1..f1d100a1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,10 +8,10 @@ Breaking changes: - In the GeoJSON output of rio-blocks, the windows are now JSON representations of the `Window` class (#1074). -- The `rasterio.windows.Window` class no longer derives from `tuple`. - Comparisons like `Window(0, 0, 1, 1) == ((0, 1), (0, 1))` are no - longer possible. Instead, call the `.toranges()` method of the - former or coerce the latter using `Window.from_ranges()` (#1074). +- The ``rasterio.windows.Window`` class no longer derives from ``tuple``. + Comparisons like ``Window(0, 0, 1, 1) == ((0, 1), (0, 1))`` are no + longer possible. Instead, call the ``.toranges()`` method of the + former or coerce the latter using ``Window.from_ranges()`` (#1074). New features: @@ -19,6 +19,7 @@ New features: Rasterio (#1074). - Use of old style range tuples as windows is deprecated and warned against (#1074). +- Addition of dataset ``block()`` method (#1077). 1.0a9 (2017-06-02) ------------------ diff --git a/rasterio/_base.pyx b/rasterio/_base.pyx index 88e1df13..3df9d28d 100644 --- a/rasterio/_base.pyx +++ b/rasterio/_base.pyx @@ -449,6 +449,45 @@ cdef class DatasetBase(object): GDALGetRasterUnitType(self.band(j)) for j in self.indexes) return self._units + def block(self, bidx, i, j): + """Returns info about a particular block + + Parameters + ---------- + bidx: int + Band index, starting with 1. + i: int + Row index of the block, starting with 0. + j: int + Column index of the block, starting with 0. + + Returns + ------- + {'window': Window, 'size': int (bytes)} + """ + cdef GDALMajorObjectH obj = NULL + cdef char *value = NULL + cdef const char *key_c = NULL + + obj = self.band(bidx) + + if self.driver == 'GTiff': + key_b = 'BLOCK_SIZE_{0}_{1}'.format(j, i).encode('utf-8') + key_c = key_b + value = GDALGetMetadataItem(obj, key_c, 'TIFF') + size = int(value) + else: + size = None + + h, w = self.block_shapes[bidx-1] + row = i * h + height = min(h, self.height - row) + col = j * w + width = min(w, self.width - col) + window = windows.Window(col, row, width, height) + + return {'window': window, 'size': size} + def block_windows(self, bidx=0): """Returns an iterator over a band's blocks and their corresponding windows. Produces tuples like ``(block, window)``. The primary use diff --git a/tests/test_blocks.py b/tests/test_blocks.py index 5f04cc34..22734d7a 100644 --- a/tests/test_blocks.py +++ b/tests/test_blocks.py @@ -162,3 +162,12 @@ def test_block_windows_filtered_none(path_rgb_byte_tif): itr = ((ij, win) for ij, win in src.block_windows() if filter_func(win)) with pytest.raises(StopIteration): next(itr) + + +def test_block_tiff(path_rgb_byte_tif): + """Without compression a TIFF's blocks are all the same size""" + with rasterio.open(path_rgb_byte_tif) as src: + block_windows = list(src.block_windows()) + sizes = [src.block(1, i, j)['size'] for (i, j), w in block_windows] + assert sizes.count(2373) == 1 + assert sizes.count(7119) == len(block_windows) - 1